From: Casey Connolly Date: Thu, 23 Oct 2025 14:26:46 +0000 (+0200) Subject: efi_loader: efi_console: support editable input fields X-Git-Tag: v2026.01-rc1~3^2~14 X-Git-Url: http://git.openpandora.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=419cc25aa15784510a276f78441efbaf470b8577;p=pandora-u-boot.git efi_loader: efi_console: support editable input fields 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 Acked-by: Ilias Apalodimas Tested-by: Ilias Apalodimas Signed-off-by: Heinrich Schuchardt --- diff --git a/cmd/eficonfig.c b/cmd/eficonfig.c index 8ac0fb98e02..d8d946c87ac 100644 --- a/cmd/eficonfig.c +++ b/cmd/eficonfig.c @@ -974,6 +974,8 @@ static efi_status_t handle_user_input(u16 *buf, int buf_size, 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 953f6831466..068d1a0a7b7 100644 --- a/lib/efi_loader/efi_console.c +++ b/lib/efi_loader/efi_console.c @@ -1384,7 +1384,9 @@ efi_status_t efi_console_get_u16_string(struct efi_simple_text_input_protocol *c 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 @@ -1393,25 +1395,51 @@ efi_status_t efi_console_get_u16_string(struct efi_simple_text_input_protocol *c 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 == 5) { /* Home */ + cursor = 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; @@ -1428,8 +1456,17 @@ 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); } }