ISO icon indicating copy to clipboard operation
ISO copied to clipboard

Allow bootloader to react to certain keys

Open grahamperrin opened this issue 4 years ago • 16 comments

Safe mode

From https://github.com/helloSystem/ISO/issues/103#issuecomment-761563074:

… At the time when the boot command prompt shows it is probably already too late to change this by setting/unsetting the environment variable.

Possibly there is a way to load the boot loader menu on the Live system …

Boot environments

From https://github.com/helloSystem/ISO/issues/55#issuecomment-803288965:

  • We need a way to select BEs from the bootloader, which means we need to work on the bootloader to be completely silent unless a key combo (e.g., Command-B-E for Boot Environments) is held down

Until user-friendly silence can be achieved with helloSystem:

  • there should be a method – any method – of breaking silence, to present the normal FreeBSD loader, when required, for BE purposes.

Blocking normal presentation:

https://github.com/helloSystem/ISO/commit/35e19f2b8cbadf4d4453b1c965c5d5aba3a8cc2f

Reference

https://cgit.freebsd.org/src/tree/stand/forth/loader.4th

https://cgit.freebsd.org/src/tree/stand/forth/beastie.4th

beastie.4th(8)

FreeBSD bug 254431 – beastie.4th(8) is no longer ASCII art

grahamperrin avatar Mar 20 '21 11:03 grahamperrin

The desired behavior is described in https://support.apple.com/en-us/HT201255

  • By default, no boot loader messages should be shown at all
  • If the user holds down Command+V (for verbose) during boot, then unset boot_mute and boot -v should happen (in the bootloader, Ctrl, Windows, and Alt should all act as Command)
  • If the user holds down Command+B (for bootloader) during boot, then Beastie menu should be shown

Do you know how to achieve this in Forth?

probonopd avatar Mar 20 '21 11:03 probonopd

Why did you change my title?

We need something sooner than the luxury of snag keys. https://github.com/helloSystem/ISO/commit/35e19f2b8cbadf4d4453b1c965c5d5aba3a8cc2f reduces the usability of boot environments; makes things potentially difficult for end users.

Command+B (for bootloader)

Why not Alt?

grahamperrin avatar Mar 20 '21 12:03 grahamperrin

Because Command+S stands for safe mode.

If technically possible, it would be great if we could use Command+B+Et o go to the Boot Environments screen directly.

(On PC keyboards, we use Alt as the Command key. On Mac keyboards, we use the Apple key as the Command key. Command stands for "the key on the left side to the space bar" as far as I am concerned.)

probonopd avatar Mar 20 '21 13:03 probonopd

For a moment, forget the Command key.

Alt is used by Apple with Apple keyboards with Mac hardware.

grahamperrin avatar Mar 20 '21 14:03 grahamperrin

Actually, https://support.apple.com/en-us/HT201255 says

  • Shift (⇧): Start up in safe mode.
  • Command-S: Start up in single-user mode

probonopd avatar Mar 20 '21 15:03 probonopd

Some disorientation from the change of title, which was not intended to focus on safe mode or single user mode.

To refocus on what was originally in my title, I simply want a method to present:

  • the beastie.4th boot loader

– from there, people can step to safe mode, single user mode and so on; most importantly, boot environments.

Corrected above. It's Alt (not Alt-S):

image

(The mid-sentence uppercase S is quite un-British. I misread it as part of the shortcut.)

grahamperrin avatar Mar 20 '21 15:03 grahamperrin

I agree that this would be cool.

probonopd avatar Mar 20 '21 16:03 probonopd

https://github.com/freebsd/freebsd-src/blob/839fdcfc0c1dba34f728813d9756515ad82ff58a/stand/common/boot.c#L215

has printf("%s\n", (prompt == NULL) ? "Hit [Enter] to boot immediately, or any other key for command prompt." : prompt); - so we could hook in there and do something else if specific keys were pressed.

But the question is, can we do everything in Forth without compilation?

That would probably mean to not skip Beastie altogether, but to modify Beastie to show up even if beastie_disable is selected in case the the Alt key is pressed?

Probably we would have to hook this in around here: https://github.com/freebsd/freebsd-src/blob/839fdcfc0c1dba34f728813d9756515ad82ff58a/stand/forth/beastie.4th#L91-L101

Does anyone know any Forth?

probonopd avatar Mar 20 '21 18:03 probonopd

Can the Forth command EKEY be used to detect whether the Alt or Shift key is being held down?

http://lars.nocrew.org/forth2012/facility/EKEY.html is like Chinese to me.

probonopd avatar Mar 20 '21 18:03 probonopd

Got this information:

Guys, just letting you know that the kernel loader in FreeBSD 12 and 13 uses Lua as a scripting language. The loader in FreeBSD 11 and previous versions uses Forth. Scripts whose names end in .4th are Forth scripts. The Lua scripts have names ending in .lua and they are to be found in the /boot/lua directory. The documentation for the FreeBSD loader is not up-to-date.

probonopd avatar Mar 21 '21 23:03 probonopd

I would like to allow users to boot in verbose mode by just pressing the v (ASCII 76) key.

Added a file /boot/lua/local.lua that contains:

if io.ischar() then
        local ch = io.getchar()
        if ch == 76 then
                loader.perform("unset boot_mute")
                loader.perform("boot -v")
        end
end

Unfortunately I can't seem to get it to work. What am I doing wrong?

(/boot/loader_lua.efi seems ot be able to do a similar thing to what I want, namely if you press e.g., backspace while the kernel is being loaded, then it drops the user to a OK> prompt... so maybe we need to edit its souce code to achieve such a thing?)

probonopd avatar Apr 01 '21 16:04 probonopd

Maybe we need to patch stand/common/boot.c with something like this:

                                if ((c == 'V') || (c == 'v')) {
                                        yes = 1;
                                        argv[0] = "boot -v";
                                        argv[1] = NULL;
                                        return(command_boot(1, argv));
                                        break;
                                }

probonopd avatar Apr 07 '21 17:04 probonopd

     <-- User should be able to press 'v' or 's' here

    Hit [Enter] to boot immediately, or any other key for command prompt.
    Booting [kernel] in 1 seconds
    
    Type '?' for a list of commands, 'help' for more detailed help.
    OK

Out of the box, pressing s or v while the early stages of the bootloader are running prevents autoboot from happening and dumps one to an OK prompt. This prevents us from solving this (purely) by Lua scripting. Even if Lua could get the content of the keyboard buffer, the boot would end before that at the OK prompt.

The bootloader probably needs to be changed so that the OK prompt only shows up in case a certain key had been pressed, e.g., backspace.

"The bootloader" being

grep -r "for more detailed help" /boot
Binary file /boot/loader_simp.efi matches
Binary file /boot/loader matches
Binary file /boot/loader_simp matches
Binary file /boot/loader_lua matches
Binary file /boot/loader_lua.efi matches
Binary file /boot/zfsloader matches
Binary file /boot/userboot.so matches
Binary file /boot/loader.efi matches
Binary file /boot/pxeboot matches
Binary file /boot/loader_4th matches
Binary file /boot/userboot_4th.so matches
Binary file /boot/userboot_lua.so matches
Binary file /boot/loader_4th.efi matches

Is "freebsd-src/stand" the source of the bootloader? (What does stand stand for?)

Maybe @kevans91 knows how to do that?

probonopd avatar Nov 22 '21 13:11 probonopd

By the way, LOADER.CONF(5) says about autoboot_delay:

If set to "0", no delay is inserted, but any keys pressed while the kernel and modules are loaded will enter interactive mode.

That does not seem to work for me. Hence I set it to 1. The objective is to waste no precious seconds but still to be able to get to the OK prompt by pressing backspace here:

     <-- User should be able to press backspace here

    Hit [Enter] to boot immediately, or any other key for command prompt.
    Booting [kernel] in 1 seconds
    
    Type '?' for a list of commands, 'help' for more detailed help.
    OK

probonopd avatar Nov 22 '21 13:11 probonopd

Yes, stand/ is where the loader lives ([stand]alone, iirc). I definitely haven't implemented any sort of key tracking while loadelf is operating in lualoader (stand/lua substantially), so it makes sense that that doesn't work. You can still solve that entirely in lualoader, we just don't do that at the moment; lualoader's what handles the interrupt of autoboot typically.

kevans91 avatar Nov 22 '21 16:11 kevans91

Time to learn Lua then. Has been on my TODO list for a long time anyway :-)

Just to be sure:

When I press any key before the "Loading kernel..." message, then I am still able to catch that in Lua without being dropped to the OK prompt?

probonopd avatar Nov 22 '21 19:11 probonopd

Finally came around to wrapping my head around lua. It's great! Thanks a lot @kevans91.

https://github.com/helloSystem/ISO/blob/27acc69c839fa85826e810a4f1f993ca1096eb05/overlays/boot/boot/lua/local.lua#L35-L36

The way it is working right now is that the user has to press one of the keys s, v, backspace as soon as the local.lua script runs.

Only thing I didn't figure out is how to get at the keyboard buffer, so that I could detect whether certain keys had been pressed by the user before the start of the execution of my lua script.

I think the bootloader can do that for detecting whether backspace had been pressed by the user, even before the bootloader runs...

probonopd avatar Feb 26 '23 01:02 probonopd