Page MenuHomeFreeBSD

bootloader prompt: Add support for editing, history, and command/argument completion
Needs ReviewPublic

Authored by connorbailey777_gmail.com on Sep 14 2022, 9:31 PM.
Tags
None
Referenced Files
Unknown Object (File)
Thu, Sep 25, 6:17 PM
Unknown Object (File)
Aug 27 2025, 7:30 PM
Unknown Object (File)
Aug 26 2025, 7:38 PM
Unknown Object (File)
Aug 26 2025, 7:29 AM
Unknown Object (File)
Aug 25 2025, 11:45 AM
Unknown Object (File)
Aug 15 2025, 11:22 PM
Unknown Object (File)
Aug 13 2025, 8:35 AM
Unknown Object (File)
Jul 26 2025, 12:10 PM
Subscribers

Details

Reviewers
imp
manu
Summary

Fixes special/unknown keys clobbering the prompt input line.
Changes the BIOS/UEFI consoles to pass through more special keys and modifiers.
Implements binding keystrokes to actions, provides common editing actions along with default bindings.
Adds the 'keybind', 'keyunbind', 'keybinds', 'showkey', and 'history' simp commands for managing keybinds/history.
Adds the Lua 'keybind' and 'history' libraries, for managing keybinds/history.
Adds completions for command names, some command arguments, and for Lua keywords/identifiers.

Builds on top of existing prompt input flow, shouldn't break any existing correct behavior.

Test Plan

I've tested all functionality on virtualized amd64 UEFI, i386 BIOS, i386 PXE, and U-Boot on a Raspberry Pi 4 (with an expected problem described below).

Running through the default keybindings should reach a solid percentage of coverage, with one exception:
On certain platforms, some keystrokes won't trigger any action or type any characters at the prompt, since the console either sends the key with the wrong modifiers or does not send the key at all.
For example, U-Boot's console (which just wraps U-Boot getc) does not pass home/end/insert/delete or the alt modifier.
I'm not certain which other consoles might have similiar problems, but I've ensured that the BIOS and UEFI consoles support a majority of keys/modifiers.

I've worked around potential console limitations by providing multiple distinct bindings for editing actions, since fixing missing keys is likely to require upstream changes.
Additionally, keys can be re-bound at runtime or through any 'include'-d file, allowing a problematic binding to be swapped out.

Beyond that, any keystrokes which print garbage to the console or silently corrupt the input line are definitely a problem, so keymash is on the table.

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Passed
Unit
No Test Coverage
Build Status
Buildable 47418
Build 44305: arc lint + arc unit

Event Timeline

first round

stand/common/prompt_bindings.c
2

Need a copyright statement here.
And you don't need the sys/devs.h / __FBSDID stuff

38–40

please use 'isupper()' to test and 'tolower()' to set.

60

#define ESC '\x1b' above and use ESC here

63

isctrl() and BS, TAB and CR. similar to above.

64

This { should be at the end of the prior line

87

I'm torn on this one... I think it's right because ANSI escape sequences are ASCII and in this range.

173

islower()

174

toupper()

278

#defines might not be bad to use here, and also as characters...

448–451

Same comments isupper / tolower

  • Add license comments
  • Remove __FBSDID, fix style, use ctype functions for parsing
stand/common/interp.c
105

Make sure there's not a tab and then a newline here please.

122–131

ditto, and there's several more below, but you can cope with finding them :)

174

0xd should likely be '\r' here, no?

Also, style(9) would have the { on the next line at the end of this one:

if (n == '\r') {
    break;
} else if (n != 0) {
    prompt_rawoutput(n);
}

but with the tab indentation that you already have.

188

Question: is there some way we can structure this to make the extra command line editing optional?
If it's easy, I'd like to do it now, if it is hard, we should chat elsewhere about that.

stand/common/interp_lua.c
260

why 20?

291

Generally, the style in FreeBSD is to have all the variables declared at the start of the function. This is for a lot of old-school reasons. Elsewhere you have them initialized in the middle, which isn't so bad (a technical violation, but the code is readable either way). Here, though, it just seems to float.

620

need to end the file with a newline please.

stand/common/prompt_bindings.c
76

this newline looks weird to my eye

stand/common/prompt_bindings.h
35

I wonder if 8 bits are enough here. While there's not a lot of support for it, I don't want people to not be able to boot kernels with upper ascii characters in the names because they can't type them at the command prompt.

76

please add newline.

stand/common/prompt_editing.c
91

extra newline

93

extra newline

209

Generally, there's not a blank line after a comment before code.

228

A weird thing is that we tend to write this as

for (; run < cursorsize && isspace(LINE[CURSOR - run - 1]); run++)
    continue;

so that we know the ; wasn't accidental. Here and at least on the next line.

916

need newline

stand/i386/libi386/vidconsole.c
1078

{ on next line by itself. Here and several places below I've not called out.

1081

I'd join the next line with this one...
Also, do the bits in kss have a #define value you can use?

  • Remove trailing tabs
  • Style fixes, mainly cuddle comments and add newlines at end of file
  • Lock behind LOADER_EDITING_SUPPORT option
  • Don't clobber extended ASCII