[PATCH 1/2] efi_loader: efi_console: support editable input fields

Ilias Apalodimas ilias.apalodimas at linaro.org
Fri Oct 24 13:58:32 CEST 2025


On Thu, 23 Oct 2025 at 17:26, Casey Connolly <casey.connolly at linaro.org> wrote:
>
> When editing eficonfig "optional data" (typically cmdline arguments)
> it's useful to be able to edit the string rather than having to re-type
> the entire thing. Implement support for editing buffers to make this a
> whole lot nicer. Specifically, add support for moving the cursor with
> the arrow keys and End key as well as deleting backwards with the delete
> key.
>
> Signed-off-by: Casey Connolly <casey.connolly at linaro.org>
> ---
>  cmd/eficonfig.c              |  2 ++
>  lib/efi_loader/efi_console.c | 52 ++++++++++++++++++++++++++++++++++++--------
>  2 files changed, 45 insertions(+), 9 deletions(-)
>
> diff --git a/cmd/eficonfig.c b/cmd/eficonfig.c
> index 8ac0fb98e02e..d8d946c87ac8 100644
> --- a/cmd/eficonfig.c
> +++ b/cmd/eficonfig.c
> @@ -973,8 +973,10 @@ static efi_status_t handle_user_input(u16 *buf, int buf_size,
>         tmp = calloc(1, buf_size * sizeof(u16));
>         if (!tmp)
>                 return EFI_OUT_OF_RESOURCES;
>
> +       /* Populate tmp so user can edit existing string */
> +       u16_strcpy(tmp, buf);
>         ret = efi_console_get_u16_string(cin, tmp, buf_size, NULL, 4, cursor_col);
>         if (ret == EFI_SUCCESS)
>                 u16_strcpy(buf, tmp);
>
> diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c
> index 953f6831466e..7bfd18233feb 100644
> --- a/lib/efi_loader/efi_console.c
> +++ b/lib/efi_loader/efi_console.c
> @@ -1383,36 +1383,61 @@ efi_status_t efi_console_get_u16_string(struct efi_simple_text_input_protocol *c
>                                         efi_console_filter_func filter_func,
>                                         int row, int col)
>  {
>         efi_status_t ret;
> -       efi_uintn_t len = 0;
> +       efi_uintn_t len;
> +       efi_uintn_t cursor;
> +       efi_uintn_t i;
>         struct efi_input_key key;
>
>         printf(ANSI_CURSOR_POSITION
>                ANSI_CLEAR_LINE_TO_END
>                ANSI_CURSOR_SHOW, row, col);
>
>         efi_cin_empty_buffer();
>
> +       len = u16_strlen(buf);
> +       cursor = len;
>         for (;;) {
> +               printf(ANSI_CURSOR_POSITION "%ls"
> +                      ANSI_CLEAR_LINE_TO_END ANSI_CURSOR_POSITION,
> +                      row, col, buf, row, col + (int)cursor);
>                 do {
>                         ret = EFI_CALL(cin->read_key_stroke(cin, &key));
>                         mdelay(10);
>                 } while (ret == EFI_NOT_READY);
>
>                 if (key.unicode_char == u'\b') {
> -                       if (len > 0)
> -                               buf[--len] = u'\0';
> -
> -                       printf(ANSI_CURSOR_POSITION
> -                              "%ls"
> -                              ANSI_CLEAR_LINE_TO_END, row, col, buf);
> +                       if (cursor > 0) {
> +                               if (cursor == len) {
> +                                       buf[--cursor] = u'\0';
> +                               } else {
> +                                       for (i = cursor - 1; i < len; i++)
> +                                               buf[i] = buf[i + 1];
> +                                       cursor--;
> +                               }
> +                               len--;
> +                       }
> +                       continue;
> +               } else if (key.scan_code == 8) { /* delete */
> +                       for (i = cursor; i <= len; i++)
> +                               buf[i] = buf[i + 1];
> +                       len--;
>                         continue;
>                 } else if (key.unicode_char == u'\r') {
>                         buf[len] = u'\0';
>                         return EFI_SUCCESS;
>                 } else if (key.unicode_char == 0x3 || key.scan_code == 23) {
>                         return EFI_ABORTED;
> +               } else if (key.scan_code == 3) { /* Right arrow */
> +                       cursor += (cursor < len) ? 1 : 0;
> +                       continue;
> +               } else if (key.scan_code == 4) { /* Left arrow */
> +                       cursor -= (cursor > 0) ? 1 : 0;
> +                       continue;
> +               } else if (key.scan_code == 6) { /* End */
> +                       cursor = len;
> +                       continue;
>                 } else if (key.unicode_char < 0x20) {
>                         /* ignore control codes other than Ctrl+C, '\r' and '\b' */
>                         continue;
>                 } else if (key.scan_code != 0) {
> @@ -1427,9 +1452,18 @@ efi_status_t efi_console_get_u16_string(struct efi_simple_text_input_protocol *c
>
>                 if (len >= (count - 1))
>                         continue;
>
> -               buf[len] = key.unicode_char;
> +               /*
> +                * Insert the character into the middle of the buffer, shift the
> +                * characters after the cursor along. The check above ensures we
> +                * will never overflow the buffer.
> +                * If the cursor is at the end of the string then this will
> +                * do nothing.
> +                */
> +               for (i = len + 1; i > cursor; i--)
> +                       buf[i] = buf[i - 1];
> +               buf[cursor] = key.unicode_char;
> +               cursor++;
>                 len++;
> -               printf(ANSI_CURSOR_POSITION "%ls", row, col, buf);
>         }
>  }
>
> --
> 2.51.0
>

Acked-by: Ilias Apalodimas <ilias.apalodimas at linaro.org>
Tested-by: Ilias Apalodimas <ilias.apalodimas at linaro.org>


More information about the U-Boot mailing list