[PATCH v3 06/11] efi_loader: move console-input helpers to efi_app_common
Ilias Apalodimas
ilias.apalodimas at linaro.org
Thu Jul 2 09:43:33 CEST 2026
On Sun, 28 Jun 2026 at 11:28, Heinrich Schuchardt
<heinrich.schuchardt at canonical.com> wrote:
>
> Move the shared console-input helpers to efi_app_common:
>
> * efi_drain_input() - drain the console input queue
> * efi_input_yn() - read a y/n/ESC key from the user
> * efi_input() - read a UTF-16 string from the console
>
> The common efi_input_yn() calls efi_drain_input() once at entry,
> replacing the open-coded cin->reset() calls that each application
> previously duplicated.
>
> dbginfodump and smbiosdump had no efi_drain_input() call in their
> command loops; add the call so the console queue is drained before
> each prompt, fixing a latent input-echo artefact.
>
> The common state is extended with a cin pointer (initialized by
> efi_app_init from sys_table->con_in) so the helpers can access the
> console-input protocol without additional parameters.
>
> Remove the now-duplicate static definitions from dtbdump, initrddump,
> smbiosdump and dbginfodump.
>
> smbiosdump: fix kernel-doc tag for command_loop() from "command_loop -"
> to "command_loop() -" to follow the kernel-doc convention.
>
> Reviewed-by: Simon Glass <sjg at chromium.org>
> Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt at canonical.com>
Acked-by: Ilias Apalodimas <ilias.apalodimas at linaro.org>
> ---
> v3:
> actually add drain_input() to dbginfodump
> v2:
> new patch
> ---
> lib/efi_loader/dbginfodump.c | 62 +-----------------
> lib/efi_loader/dtbdump.c | 109 --------------------------------
> lib/efi_loader/efi_app_common.c | 88 ++++++++++++++++++++++++++
> lib/efi_loader/efi_app_common.h | 29 +++++++++
> lib/efi_loader/initrddump.c | 109 --------------------------------
> lib/efi_loader/smbiosdump.c | 108 +------------------------------
> 6 files changed, 120 insertions(+), 385 deletions(-)
>
> diff --git a/lib/efi_loader/dbginfodump.c b/lib/efi_loader/dbginfodump.c
> index 2dcff2a11fe..b39d47ff9bb 100644
> --- a/lib/efi_loader/dbginfodump.c
> +++ b/lib/efi_loader/dbginfodump.c
> @@ -14,7 +14,6 @@
> #define BUFFER_SIZE 64
>
> static struct efi_simple_text_output_protocol *cout;
> -static struct efi_simple_text_input_protocol *cin;
> static efi_handle_t handle;
> static struct efi_system_table *systable;
> static struct efi_boot_services *bs;
> @@ -83,65 +82,6 @@ static void printp(void *p)
> print(str);
> }
>
> -/**
> - * efi_input() - read string from console
> - *
> - * @buffer: input buffer
> - * @buffer_size: buffer size
> - * Return: status code
> - */
> -static efi_status_t efi_input(u16 *buffer, efi_uintn_t buffer_size)
> -{
> - struct efi_input_key key = {0};
> - efi_uintn_t index;
> - efi_uintn_t pos = 0;
> - u16 outbuf[2] = u" ";
> - efi_status_t ret;
> -
> - /* Drain the console input */
> - ret = cin->reset(cin, true);
> - *buffer = 0;
> - for (;;) {
> - ret = bs->wait_for_event(1, &cin->wait_for_key, &index);
> - if (ret != EFI_SUCCESS)
> - continue;
> - ret = cin->read_key_stroke(cin, &key);
> - if (ret != EFI_SUCCESS)
> - continue;
> - switch (key.scan_code) {
> - case 0x17: /* Escape */
> - print(u"\r\nAborted\r\n");
> - return EFI_ABORTED;
> - default:
> - break;
> - }
> - switch (key.unicode_char) {
> - case 0x08: /* Backspace */
> - if (pos) {
> - buffer[pos--] = 0;
> - print(u"\b \b");
> - }
> - break;
> - case 0x0a: /* Linefeed */
> - case 0x0d: /* Carriage return */
> - print(u"\r\n");
> - return EFI_SUCCESS;
> - default:
> - break;
> - }
> - /* Ignore surrogate codes */
> - if (key.unicode_char >= 0xD800 && key.unicode_char <= 0xDBFF)
> - continue;
> - if (key.unicode_char >= 0x20 &&
> - pos < buffer_size - 1) {
> - *outbuf = key.unicode_char;
> - buffer[pos++] = key.unicode_char;
> - buffer[pos] = 0;
> - print(outbuf);
> - }
> - }
> -}
> -
> /**
> * skip_whitespace() - skip over leading whitespace
> *
> @@ -277,7 +217,6 @@ efi_status_t EFIAPI efi_main(efi_handle_t image_handle,
> handle = image_handle;
> systable = systab;
> cout = systable->con_out;
> - cin = systable->con_in;
> bs = systable->boottime;
>
> cout->set_attribute(cout, EFI_LIGHTBLUE | EFI_BACKGROUND_BLACK);
> @@ -298,6 +237,7 @@ efi_status_t EFIAPI efi_main(efi_handle_t image_handle,
> u16 *pos;
> efi_uintn_t ret;
>
> + efi_drain_input();
> print(u"=> ");
> ret = efi_input(command, sizeof(command));
> if (ret == EFI_ABORTED)
> diff --git a/lib/efi_loader/dtbdump.c b/lib/efi_loader/dtbdump.c
> index 1468955eb8c..716daf4a90f 100644
> --- a/lib/efi_loader/dtbdump.c
> +++ b/lib/efi_loader/dtbdump.c
> @@ -16,7 +16,6 @@
>
> #define efi_size_in_pages(size) ((size + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT)
>
> -static struct efi_simple_text_input_protocol *cin;
> static struct efi_boot_services *bs;
> static const efi_guid_t fdt_guid = EFI_FDT_GUID;
> static const efi_guid_t loaded_image_guid = EFI_LOADED_IMAGE_PROTOCOL_GUID;
> @@ -50,113 +49,6 @@ static void print_char(unsigned char c)
> print(out);
> }
>
> -/**
> - * efi_drain_input() - drain console input
> - */
> -static void efi_drain_input(void)
> -{
> - cin->reset(cin, true);
> -}
> -
> -/**
> - * efi_input_yn() - get answer to yes/no question
> - *
> - * Return:
> - * y or Y
> - * EFI_SUCCESS
> - * n or N
> - * EFI_ACCESS_DENIED
> - * ESC
> - * EFI_ABORTED
> - */
> -static efi_status_t efi_input_yn(void)
> -{
> - struct efi_input_key key = {0};
> - efi_uintn_t index;
> - efi_status_t ret;
> -
> - for (;;) {
> - ret = bs->wait_for_event(1, &cin->wait_for_key, &index);
> - if (ret != EFI_SUCCESS)
> - continue;
> - ret = cin->read_key_stroke(cin, &key);
> - if (ret != EFI_SUCCESS)
> - continue;
> - switch (key.scan_code) {
> - case 0x17: /* Escape */
> - return EFI_ABORTED;
> - default:
> - break;
> - }
> - /* Convert to lower case */
> - switch (key.unicode_char | 0x20) {
> - case 'y':
> - return EFI_SUCCESS;
> - case 'n':
> - return EFI_ACCESS_DENIED;
> - default:
> - break;
> - }
> - }
> -}
> -
> -/**
> - * efi_input() - read string from console
> - *
> - * @buffer: input buffer
> - * @buffer_size: buffer size
> - * Return: status code
> - */
> -static efi_status_t efi_input(u16 *buffer, efi_uintn_t buffer_size)
> -{
> - struct efi_input_key key = {0};
> - efi_uintn_t index;
> - efi_uintn_t pos = 0;
> - u16 outbuf[2] = u" ";
> - efi_status_t ret;
> -
> - *buffer = 0;
> - for (;;) {
> - ret = bs->wait_for_event(1, &cin->wait_for_key, &index);
> - if (ret != EFI_SUCCESS)
> - continue;
> - ret = cin->read_key_stroke(cin, &key);
> - if (ret != EFI_SUCCESS)
> - continue;
> - switch (key.scan_code) {
> - case 0x17: /* Escape */
> - print(u"\r\nAborted\r\n");
> - return EFI_ABORTED;
> - default:
> - break;
> - }
> - switch (key.unicode_char) {
> - case 0x08: /* Backspace */
> - if (pos) {
> - buffer[pos--] = 0;
> - print(u"\b \b");
> - }
> - break;
> - case 0x0a: /* Linefeed */
> - case 0x0d: /* Carriage return */
> - print(u"\r\n");
> - return EFI_SUCCESS;
> - default:
> - break;
> - }
> - /* Ignore surrogate codes */
> - if (key.unicode_char >= 0xD800 && key.unicode_char <= 0xDBFF)
> - continue;
> - if (key.unicode_char >= 0x20 &&
> - pos < buffer_size - 1) {
> - *outbuf = key.unicode_char;
> - buffer[pos++] = key.unicode_char;
> - buffer[pos] = 0;
> - print(outbuf);
> - }
> - }
> -}
> -
> /*
> * Convert FDT value to host endianness.
> *
> @@ -702,7 +594,6 @@ efi_status_t EFIAPI efi_main(efi_handle_t image_handle,
>
> handle = image_handle;
> systable = systab;
> - cin = systable->con_in;
> bs = systable->boottime;
>
> color(EFI_LIGHTBLUE);
> diff --git a/lib/efi_loader/efi_app_common.c b/lib/efi_loader/efi_app_common.c
> index e9e9334acc7..406cd236f6f 100644
> --- a/lib/efi_loader/efi_app_common.c
> +++ b/lib/efi_loader/efi_app_common.c
> @@ -9,6 +9,7 @@
> #include "efi_app_common.h"
>
> static efi_handle_t app_handle;
> +static struct efi_simple_text_input_protocol *cin;
> static struct efi_simple_text_output_protocol *cout;
> struct efi_boot_services *bs;
> static bool nocolor;
> @@ -40,6 +41,7 @@ void efi_app_init(struct efi_system_table *sys_table, efi_handle_t image_handle)
>
> app_handle = image_handle;
> systable = sys_table;
> + cin = sys_table->con_in;
> cout = sys_table->con_out;
> bs = sys_table->boottime;
>
> @@ -104,3 +106,89 @@ bool starts_with(u16 *string, u16 *keyword)
> }
> return true;
> }
> +
> +void efi_drain_input(void)
> +{
> + cin->reset(cin, true);
> +}
> +
> +efi_status_t efi_input_yn(void)
> +{
> + struct efi_input_key key = { 0 };
> + efi_uintn_t index;
> + efi_status_t ret;
> +
> + efi_drain_input();
> + for (;;) {
> + ret = bs->wait_for_event(1, &cin->wait_for_key, &index);
> + if (ret != EFI_SUCCESS)
> + continue;
> + ret = cin->read_key_stroke(cin, &key);
> + if (ret != EFI_SUCCESS)
> + continue;
> + switch (key.scan_code) {
> + case 0x17: /* Escape */
> + return EFI_ABORTED;
> + default:
> + break;
> + }
> + /* Convert to lower case */
> + switch (key.unicode_char | 0x20) {
> + case 'y':
> + return EFI_SUCCESS;
> + case 'n':
> + return EFI_ACCESS_DENIED;
> + default:
> + break;
> + }
> + }
> +}
> +
> +efi_status_t efi_input(u16 *buffer, efi_uintn_t buffer_size)
> +{
> + struct efi_input_key key = { 0 };
> + efi_uintn_t index;
> + efi_uintn_t pos = 0;
> + u16 outbuf[2] = u" ";
> + efi_status_t ret;
> +
> + *buffer = 0;
> + for (;;) {
> + ret = bs->wait_for_event(1, &cin->wait_for_key, &index);
> + if (ret != EFI_SUCCESS)
> + continue;
> + ret = cin->read_key_stroke(cin, &key);
> + if (ret != EFI_SUCCESS)
> + continue;
> + switch (key.scan_code) {
> + case 0x17: /* Escape */
> + print(u"\r\nAborted\r\n");
> + return EFI_ABORTED;
> + default:
> + break;
> + }
> + switch (key.unicode_char) {
> + case 0x08: /* Backspace */
> + if (pos) {
> + buffer[pos--] = 0;
> + print(u"\b \b");
> + }
> + break;
> + case 0x0a: /* Linefeed */
> + case 0x0d: /* Carriage return */
> + print(u"\r\n");
> + return EFI_SUCCESS;
> + default:
> + break;
> + }
> + /* Ignore surrogate codes */
> + if (key.unicode_char >= 0xD800 && key.unicode_char <= 0xDBFF)
> + continue;
> + if (key.unicode_char >= 0x20 && pos < buffer_size - 1) {
> + *outbuf = key.unicode_char;
> + buffer[pos++] = key.unicode_char;
> + buffer[pos] = 0;
> + print(outbuf);
> + }
> + }
> +}
> diff --git a/lib/efi_loader/efi_app_common.h b/lib/efi_loader/efi_app_common.h
> index 45c17a8ed99..4498607ef07 100644
> --- a/lib/efi_loader/efi_app_common.h
> +++ b/lib/efi_loader/efi_app_common.h
> @@ -64,4 +64,33 @@ void error(u16 *string);
> */
> bool starts_with(u16 *string, u16 *keyword);
>
> +/**
> + * efi_drain_input() - drain console input
> + */
> +void efi_drain_input(void);
> +
> +/**
> + * efi_input_yn() - get answer to yes/no question
> + *
> + * Drains the console input before reading.
> + *
> + * Return:
> + * y or Y
> + * EFI_SUCCESS
> + * n or N
> + * EFI_ACCESS_DENIED
> + * ESC
> + * EFI_ABORTED
> + */
> +efi_status_t efi_input_yn(void);
> +
> +/**
> + * efi_input() - read string from console
> + *
> + * @buffer: input buffer
> + * @buffer_size: buffer size
> + * Return: status code
> + */
> +efi_status_t efi_input(u16 *buffer, efi_uintn_t buffer_size);
> +
> #endif /* _EFI_APP_COMMON_H */
> diff --git a/lib/efi_loader/initrddump.c b/lib/efi_loader/initrddump.c
> index 60f8a020e8c..52562be048d 100644
> --- a/lib/efi_loader/initrddump.c
> +++ b/lib/efi_loader/initrddump.c
> @@ -19,7 +19,6 @@
>
> static struct efi_system_table *systable;
> static struct efi_boot_services *bs;
> -static struct efi_simple_text_input_protocol *cin;
> static const efi_guid_t loaded_image_guid = EFI_LOADED_IMAGE_PROTOCOL_GUID;
> static const efi_guid_t guid_simple_file_system_protocol =
> EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID;
> @@ -46,113 +45,6 @@ static const struct efi_lo_dp_prefix initrd_dp = {
> }
> };
>
> -/**
> - * efi_drain_input() - drain console input
> - */
> -static void efi_drain_input(void)
> -{
> - cin->reset(cin, true);
> -}
> -
> -/**
> - * efi_input_yn() - get answer to yes/no question
> - *
> - * Return:
> - * y or Y
> - * EFI_SUCCESS
> - * n or N
> - * EFI_ACCESS_DENIED
> - * ESC
> - * EFI_ABORTED
> - */
> -static efi_status_t efi_input_yn(void)
> -{
> - struct efi_input_key key = {0};
> - efi_uintn_t index;
> - efi_status_t ret;
> -
> - for (;;) {
> - ret = bs->wait_for_event(1, &cin->wait_for_key, &index);
> - if (ret != EFI_SUCCESS)
> - continue;
> - ret = cin->read_key_stroke(cin, &key);
> - if (ret != EFI_SUCCESS)
> - continue;
> - switch (key.scan_code) {
> - case 0x17: /* Escape */
> - return EFI_ABORTED;
> - default:
> - break;
> - }
> - /* Convert to lower case */
> - switch (key.unicode_char | 0x20) {
> - case 'y':
> - return EFI_SUCCESS;
> - case 'n':
> - return EFI_ACCESS_DENIED;
> - default:
> - break;
> - }
> - }
> -}
> -
> -/**
> - * efi_input() - read string from console
> - *
> - * @buffer: input buffer
> - * @buffer_size: buffer size
> - * Return: status code
> - */
> -static efi_status_t efi_input(u16 *buffer, efi_uintn_t buffer_size)
> -{
> - struct efi_input_key key = {0};
> - efi_uintn_t index;
> - efi_uintn_t pos = 0;
> - u16 outbuf[2] = u" ";
> - efi_status_t ret;
> -
> - *buffer = 0;
> - for (;;) {
> - ret = bs->wait_for_event(1, &cin->wait_for_key, &index);
> - if (ret != EFI_SUCCESS)
> - continue;
> - ret = cin->read_key_stroke(cin, &key);
> - if (ret != EFI_SUCCESS)
> - continue;
> - switch (key.scan_code) {
> - case 0x17: /* Escape */
> - print(u"\r\nAborted\r\n");
> - return EFI_ABORTED;
> - default:
> - break;
> - }
> - switch (key.unicode_char) {
> - case 0x08: /* Backspace */
> - if (pos) {
> - buffer[pos--] = 0;
> - print(u"\b \b");
> - }
> - break;
> - case 0x0a: /* Linefeed */
> - case 0x0d: /* Carriage return */
> - print(u"\r\n");
> - return EFI_SUCCESS;
> - default:
> - break;
> - }
> - /* Ignore surrogate codes */
> - if (key.unicode_char >= 0xD800 && key.unicode_char <= 0xDBFF)
> - continue;
> - if (key.unicode_char >= 0x20 &&
> - pos < buffer_size - 1) {
> - *outbuf = key.unicode_char;
> - buffer[pos++] = key.unicode_char;
> - buffer[pos] = 0;
> - print(outbuf);
> - }
> - }
> -}
> -
> /**
> * skip_whitespace() - skip over leading whitespace
> *
> @@ -356,7 +248,6 @@ efi_status_t EFIAPI efi_main(efi_handle_t image_handle,
>
> handle = image_handle;
> systable = systab;
> - cin = systable->con_in;
> bs = systable->boottime;
>
> color(EFI_WHITE);
> diff --git a/lib/efi_loader/smbiosdump.c b/lib/efi_loader/smbiosdump.c
> index e19214d798f..100e03294e5 100644
> --- a/lib/efi_loader/smbiosdump.c
> +++ b/lib/efi_loader/smbiosdump.c
> @@ -15,7 +15,6 @@
>
> #define BUFFER_SIZE 64
>
> -static struct efi_simple_text_input_protocol *cin;
> static struct efi_boot_services *bs;
> static efi_handle_t handle;
> static struct efi_system_table *systable;
> @@ -26,109 +25,6 @@ static const efi_guid_t guid_simple_file_system_protocol =
> EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID;
> static const efi_guid_t efi_system_partition_guid = PARTITION_SYSTEM_GUID;
>
> -/**
> - * efi_input_yn() - get answer to yes/no question
> - *
> - * Return:
> - * y or Y
> - * EFI_SUCCESS
> - * n or N
> - * EFI_ACCESS_DENIED
> - * ESC
> - * EFI_ABORTED
> - */
> -static efi_status_t efi_input_yn(void)
> -{
> - struct efi_input_key key = {0};
> - efi_uintn_t index;
> - efi_status_t ret;
> -
> - /* Drain the console input */
> - ret = cin->reset(cin, true);
> - for (;;) {
> - ret = bs->wait_for_event(1, &cin->wait_for_key, &index);
> - if (ret != EFI_SUCCESS)
> - continue;
> - ret = cin->read_key_stroke(cin, &key);
> - if (ret != EFI_SUCCESS)
> - continue;
> - switch (key.scan_code) {
> - case 0x17: /* Escape */
> - return EFI_ABORTED;
> - default:
> - break;
> - }
> - /* Convert to lower case */
> - switch (key.unicode_char | 0x20) {
> - case 'y':
> - return EFI_SUCCESS;
> - case 'n':
> - return EFI_ACCESS_DENIED;
> - default:
> - break;
> - }
> - }
> -}
> -
> -/**
> - * efi_input() - read string from console
> - *
> - * @buffer: input buffer
> - * @buffer_size: buffer size
> - * Return: status code
> - */
> -static efi_status_t efi_input(u16 *buffer, efi_uintn_t buffer_size)
> -{
> - struct efi_input_key key = {0};
> - efi_uintn_t index;
> - efi_uintn_t pos = 0;
> - u16 outbuf[2] = u" ";
> - efi_status_t ret;
> -
> - /* Drain the console input */
> - ret = cin->reset(cin, true);
> - *buffer = 0;
> - for (;;) {
> - ret = bs->wait_for_event(1, &cin->wait_for_key, &index);
> - if (ret != EFI_SUCCESS)
> - continue;
> - ret = cin->read_key_stroke(cin, &key);
> - if (ret != EFI_SUCCESS)
> - continue;
> - switch (key.scan_code) {
> - case 0x17: /* Escape */
> - print(u"\r\nAborted\r\n");
> - return EFI_ABORTED;
> - default:
> - break;
> - }
> - switch (key.unicode_char) {
> - case 0x08: /* Backspace */
> - if (pos) {
> - buffer[pos--] = 0;
> - print(u"\b \b");
> - }
> - break;
> - case 0x0a: /* Linefeed */
> - case 0x0d: /* Carriage return */
> - print(u"\r\n");
> - return EFI_SUCCESS;
> - default:
> - break;
> - }
> - /* Ignore surrogate codes */
> - if (key.unicode_char >= 0xD800 && key.unicode_char <= 0xDBFF)
> - continue;
> - if (key.unicode_char >= 0x20 &&
> - pos < buffer_size - 1) {
> - *outbuf = key.unicode_char;
> - buffer[pos++] = key.unicode_char;
> - buffer[pos] = 0;
> - print(outbuf);
> - }
> - }
> -}
> -
> /**
> * skip_whitespace() - skip over leading whitespace
> *
> @@ -467,7 +363,7 @@ static efi_status_t do_save(u16 *filename)
> }
>
> /**
> - * command_loop - process user commands
> + * command_loop() - process user commands
> */
> static void command_loop(void)
> {
> @@ -476,6 +372,7 @@ static void command_loop(void)
> u16 *pos;
> efi_uintn_t ret;
>
> + efi_drain_input();
> print(u"=> ");
> ret = efi_input(command, sizeof(command));
> if (ret == EFI_ABORTED)
> @@ -509,7 +406,6 @@ efi_status_t EFIAPI efi_main(efi_handle_t image_handle,
>
> handle = image_handle;
> systable = systab;
> - cin = systable->con_in;
> bs = systable->boottime;
>
> color(EFI_WHITE);
> --
> 2.53.0
>
More information about the U-Boot
mailing list