Add support for a basic boot menu to the bios
PATCH 1/1 Add support for a basic boot menu to the bios
I sent this to the bochs list earlier today, but given that kvm is already carrying patches for the BIOS, it may be worthwhile/interesting to add this also as it can make the user experience substantially nicer.
-- Begin forwarded message --
The attached patch adds support for a relatively basic boot device selection menu to the bochs bios code.
Instead of immediately booting from the boot device set in the cmos, we wait for 3 seconds for the user to press F10; if they press it, then we show a basic boot menu that they can select what device to boot from. Otherwise, we continue on with what was setup before running the virtual machine. The advantage is that users can change their boot device just on rebooting a virtual machine rather than having to stop and then restart it.
This includes the wait routines added by VirtualBox
(http://www.virtualbox.org) in their modifications to the rombios as they made things a bit easier.
Jeremy
Index: rombios.c
===================================================================
RCS file: /cvsroot/bochs/bochs/bios/rombios.c,v
retrieving revision 1.182
rombios.c +285 -0
@@ -1950,6 +1950,289 @@return ; } +#define WAIT_HZ 64 +/** +* Check for keystroke. +* @returns True if keystroke available, False if not. +*/ +Bit8u check_for_keystroke() +{ +ASM_START + mov ax, #0x100 + int #0x16 + jz no_key + mov al, #1 + jmp done +no_key: + xor al, al +done: +ASM_END +} + +/** + * Get keystroke. + * @returns BIOS scan code. + */ +Bit8u get_keystroke() +{ +ASM_START + mov ax, #0x0 + int #0x16 + xchg ah, al +ASM_END +} + +/** + * Waits (sleeps) for the given number of ticks. + * Checks for keystroke. + * + * @returns BIOS scan code if available, 0 if not. + * @param ticks Number of ticks to sleep. + * @param stop_on_key Whether to stop immediately upon keypress. + */ +Bit8u wait(ticks, stop_on_key) + Bit16u ticks; + Bit8u stop_on_key; +{ + long ticks_to_wait, delta; + Bit32u prev_ticks, t; + Bit8u scan_code = 0; + + /* + * The 0:046c wraps around at 'midnight' according to a 18.2Hz clock. + * We also have to be careful about interrupt storms. + */ +ASM_START + pushf + sti +ASM_END + ticks_to_wait = ticks; + prev_ticks = read_dword(0x0, 0x46c); + do + { +ASM_START + hlt +ASM_END + t = read_dword(0x0, 0x46c); + if (t > prev_ticks) + { + delta = t - prev_ticks; /* The temp var is required or bcc screws up. */ + ticks_to_wait -= delta; + } + else if (t < prev_ticks) + ticks_to_wait -= t; /* wrapped */ + prev_ticks = t; + + if (check_for_keystroke()) + { + scan_code = get_keystroke(); + bios_printf(BIOS_PRINTF_DEBUG, "Key pressed: %x\n", scan_code); + if (stop_on_key) + return scan_code; + } + } while (ticks_to_wait > 0); +ASM_START + popf +ASM_END + return scan_code; +} + +void wait_init() +{ + /* The default is 18.2 ticks per second (~55ms tick interval). + Set the timer to 16ms ticks (64K / (Hz / (PIT_HZ / 64K)) = count). + 0x10000 / (1000 / (1193182 / 0x10000)) = 1193 (0x04a9) + 0x10000 / ( 128 / (1193182 / 0x10000)) = 9321 (0x2469) + 0x10000 / ( 64 / (1193182 / 0x10000)) = 18643 (0x48d3) */ +ASM_START + mov al, #0x34 ; timer0: binary count, 16bit count, mode 2 + out 0x43, al + mov al, #0xd3 ; Low byte - 64Hz + out 0x40, al + mov al, #0x48 ; High byte - 64Hz + out 0x40, al +ASM_END +} + +void wait_uninit() +{ +ASM_START + pushf + cli + + /* Restore the timer to the default 18.2Hz. */ + mov al, #0x34 ; timer0: binary count, 16bit count, mode 2 + out 0x43, al + xor ax, ax ; maximum count of 0000H = 18.2Hz + out 0x40, al + out 0x40, al + + /* + * Reinitialize the tick and rollover counts since we've + * screwed them up by running the timer at WAIT_HZ for a while. + */ + pushad + push ds + mov ds, ax ; already 0 + call timer_tick_post + pop ds + popad + + popf +ASM_END +} + +static void clearscreen() { + /* Hide cursor, clear screen and move cursor to starting position */ +ASM_START + push bx + push cx + push dx + + mov ax, #0x100 + mov cx, #0x1000 + int #0x10 + + mov ax, #0x700 + mov bh, #7 + xor cx, cx + mov dx, #0x184f + int #0x10 + + mov ax, #0x200 + xor bx, bx + xor dx, dx + int #0x10 + + pop dx + pop cx + pop bx +ASM_END +} + +int bootmenu(selected) + int selected; +{ + Bit8u scode; + int max; + + /* get the number of boot devices */ + max = read_word(IPL_SEG, IPL_COUNT_OFFSET); + + for(;;) { + clearscreen(); + printf("\n\n\n\n\n\n\n"); + printf(" Select boot device\n\n"); + printf(" 1. Floppy\n"); + printf(" 2. Hard drive\n"); + printf(" 3. CD-ROM\n"); + if (max == 4) + printf(" 4. Network\n"); + printf("\n\n Currently selected: %d\n", selected); + + do { + scode = wait(WAIT_HZ, 1); + } while (scode == 0); + switch(scode) { + case 0x02: + case 0x03: + case 0x04: + selected = scode - 1; + break; + case 0x05: + if (max == 4) + selected = scode -1 ; + else + scode = 0; + break; + case 0x48: + selected -= 1; + if (selected < 1) + selected = 1; + scode = 0; + break; + case 0x50: + selected += 1; + if (selected > max) + selected = max; + scode = 0; + break; + case 0x1c: + break; + default: + scode = 0; + break; + } + if (scode != 0) + break; + } + + switch (selected) { + case 1: + return 0x3D; + case 2: + return 0x3E; + case 3: + return 0x3F; + case 4: + return 0x58; + default: + return 0; + } +} + +void interactive_bootkey() +{ + Bit16u i; + Bit8u scan = 0; + + /* Set PIT to 1ms ticks */ + wait_init(); + + printf("\n\nPress F10 to select boot device.\n"); + for (i = 3; i > 0; i--) + { + scan = wait(WAIT_HZ, 0); + switch (scan) { + case 0x3D: + case 0x3E: + case 0x3F: + case 0x58: + break; + case 0x44: + scan = bootmenu(inb_cmos(0x3d)); + break; + default: + scan = 0; + break; + } + if (scan != 0) + break; + } + + /* set the default based on the keypress or menu */ + switch(scan) { + case 0x3D: + outb_cmos(0x3d, 0x01); + break; + case 0x3E: + outb_cmos(0x3d, 0x02); + break; + case 0x3F: + outb_cmos(0x3d, 0x03); + break; + case 0x58: + outb_cmos(0x3d, 0x04); + break; + default: + break; + } + + /* Restore PIT ticks */ + wait_uninit(); +} + + void nmi_handler_msg() {
@@ -10193,6 +10476,8 @@ ;;#endif // BX_ELTORITO_BOOT +call _interactive_bootkey + sti ;; enable interrupts int #0x19
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
kvm-devel mailing list [email protected]
https://lists.sourceforge.net/lists/listinfo/kvm-devel
A message that is not in the archive (sent off-list or not yet received): 1189626953.16586.6.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/[email protected]
Very cool!
My mailer doesn't want to quote your patch, but I noticed the following:
Quoted 12 lines
rombios.c +12
-0+ +/* set the default based on the keypress or menu */ +switch (scan) { +case 0x3D : +outb_cmos (0x3d ,0x01 ); +break ; +case 0x3E : +outb_cmos (0x3d ,0x02 ); +break ; +case 0x3F : +outb_cmos (0x3d ,0x03 ); +break ;
rombios.c line 2233
Quoted 10 lines
rombios.c +10
-0+case 0x58 : +outb_cmos (0x3d ,0x04 ); +break ; +default : +break ; + } + +/* Restore PIT ticks */ +wait_uninit (); +}
But the CMOS memory isn't persisted in QEMU. Another nice patch (although certainly not required IMHO for this to go in), would be to make nvram optionally persistent for QEMU so these settings would persist across boots.
Regards,
Anthony Liguori
Quoted 31 lines · Jeremy Katz
I sent this to the bochs list earlier today, but given that kvm is already carrying patches for the BIOS, it may be worthwhile/interesting to add this also as it can make the user experience substantially nicer.
-- Begin forwarded message --
The attached patch adds support for a relatively basic boot device selection menu to the bochs bios code.
Instead of immediately booting from the boot device set in the cmos, we wait for 3 seconds for the user to press F10; if they press it, then we show a basic boot menu that they can select what device to boot from. Otherwise, we continue on with what was setup before running the virtual machine. The advantage is that users can change their boot device just on rebooting a virtual machine rather than having to stop and then restart it.
This includes the wait routines added by VirtualBox
(http://www.virtualbox.org) in their modifications to the rombios as they made things a bit easier.Jeremy
------------------------------------------------------------------------
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
------------------------------------------------------------------------
Quoted 4 lines
_______________________________________________
kvm-devel mailing list [email protected]
https://lists.sourceforge.net/lists/listinfo/kvm-devel
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
A message that is not in the archive (sent off-list or not yet received): [email protected]
Quoted 1 line · Anthony Liguori
Very cool!
Long-term itch of mine scratched :-)
Quoted 4 lines
My mailer doesn't want to quote your patch, but I noticed the following:
Quoted 2 lines
(quoted diff) +2
-0+ + /* set the default based on the keypress or menu */
[snip]
Quoted 4 lines
But the CMOS memory isn't persisted in QEMU. Another nice patch (although certainly not required IMHO for this to go in), would be to make nvram optionally persistent for QEMU so these settings would persist across boots.
Yeah, the lack of persistence is sort of a "feature" in this case. If you use the similar menus on most real hardware, they don't persist (you have to go into the bios setup screens to make it persist). That said, if things were to persist, then we'd probably want to change the patch to set something else which was looked at prior to the CMOS
Jeremy
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
Hi Jeremy,
I gave this patch a try today against the latest git 1edeb9c05aa034633978f31e2c773a1be55ed337 and I cannot get past the "Press F10..." prompt. I'm on an Intel Core 2 Duo processor. It does work though with -no-kvm.
Have you tested this patch with KVM?
Regards,
Anthony Liguori
Quoted 31 lines · Jeremy Katz
I sent this to the bochs list earlier today, but given that kvm is already carrying patches for the BIOS, it may be worthwhile/interesting to add this also as it can make the user experience substantially nicer.
-- Begin forwarded message --
The attached patch adds support for a relatively basic boot device selection menu to the bochs bios code.
Hi J
Instead of immediately booting from the boot device set in the cmos, we wait for 3 seconds for the user to press F10; if they press it, then we show a basic boot menu that they can select what device to boot from. Otherwise, we continue on with what was setup before running the virtual machine. The advantage is that users can change their boot device just on rebooting a virtual machine rather than having to stop and then restart it.This includes the wait routines added by VirtualBox
(http://www.virtualbox.org) in their modifications to the rombios as they made things a bit easier.Jeremy
------------------------------------------------------------------------
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
------------------------------------------------------------------------
Quoted 4 lines
_______________________________________________
kvm-devel mailing list [email protected]
https://lists.sourceforge.net/lists/listinfo/kvm-devel
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
Quoted 17 lines · Jeremy Katz
I sent this to the bochs list earlier today, but given that kvm is already carrying patches for the BIOS, it may be worthwhile/interesting to add this also as it can make the user experience substantially nicer.
-- Begin forwarded message --
The attached patch adds support for a relatively basic boot device selection menu to the bochs bios code.
Instead of immediately booting from the boot device set in the cmos, we wait for 3 seconds for the user to press F10; if they press it, then we show a basic boot menu that they can select what device to boot from. Otherwise, we continue on with what was setup before running the virtual machine. The advantage is that users can change their boot device just on rebooting a virtual machine rather than having to stop and then restart it.
Quoted 5 lines
This includes the wait routines added by VirtualBox
(http://www.virtualbox.org) in their modifications to the rombios as they made things a bit easier.
This is nice! Two comments:
- it would be nice for qemu to provide the bios an indication if the '-boot' parameter was specified to qemu. if so, the bios should skip the menu on first bootup, reducing the boot delay. On subsequent boots the menu should be offered. This is primarily useful in managed environments.
- coding this stuff in rombios32.c instead of rombios.c (with its strange idea of C) is *much* preferable for maintainability. As far as i can tell, there is no reason not to do so, especially for code which is not called from the 16-bit OS.
Signature · 7 lines
Any sufficiently difficult bug is indistinguishable from a feature. ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
A message that is not in the archive (sent off-list or not yet received): 46ED8B5B.40903-atKUWr5tajBWk0Htik3J/[email protected]
Quoted 2 lines · Avi Kivity
- coding this stuff in
rombios32.cinstead ofrombios.c(with its strange idea of C) is *much* preferable for maintainability.
The strange code style is due to the compiler used (bcc). I see that today it's possible to make as and gcc to emit 16bit code (e.g. HPA rewrote i386 boot code in plain C)...
Luca
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
A message that is not in the archive (sent off-list or not yet received): 68676e00709170823m3247c3eaj7d268166ecc8c013-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org
Quoted 11 lines · Luca
Quoted 3 lines · Avi Kivity
- coding this stuff in
rombios32.cinstead ofrombios.c(with its strange idea of C) is *much* preferable for maintainability.The strange code style is due to the compiler used (bcc). I see that today it's possible to make as and gcc to emit 16bit code (e.g. HPA rewrote i386 boot code in plain C)...
It's simpler and better to code it in 32-bit mode in rombios32.c, where there are no restrictions like with the 16-bit mode.
Signature · 7 lines
Do not meddle in the internals of kernels, for they are subtle and quick to panic. ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
Quoted 2 lines · Avi Kivity
Quoted 2 lines
The attached patch adds support for a relatively basic boot device selection menu to the bochs bios code.
[snip]
Quoted 7 lines
This is nice! Two comments:
- it would be nice for qemu to provide the bios an indication if the '-boot' parameter was specified to qemu. if so, the bios should skip the menu on first bootup, reducing the boot delay. On subsequent boots the menu should be offered. This is primarily useful in managed environments.
While this could be nice, at the same time, -boot is going to be getting passed for a long time, even when it's no longer needed, just due to people not updating their tools. So I almost think it's better to take the 3 second hit since it's going to be there every other time. We could tweak it to be a little bit less, but 3 seems in line with what other BIOSes seem to do.
Quoted 4 lines
- coding this stuff in
rombios32.cinstead ofrombios.c(with its strange idea of C) is *much* preferable for maintainability. As far as i can tell, there is no reason not to do so, especially for code which is not called from the 16-bit OS.
The code is called from the 16-bit OS, though. It needs to be done after rom scanning has been done so that we can show network or not as appropriate. And unless I'm missing something, calling into rombios32.c outside of rombios32_init() is going to add just as much hard-to-maintain code.
Updated patch against kvm git attached that actually works with kvm. Also ends up being a little bit simpler because we're doing less mucking around with the timer.
Jeremy
bios/BIOS-bochs-latest binary +0 -0
bios/BIOS-bochs-legacy binary +0 -0
bios/rombios.c +224 -0
236 lines not on this page · raw message
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
kvm-devel mailing list [email protected]
https://lists.sourceforge.net/lists/listinfo/kvm-devel
A message that is not in the archive (sent off-list or not yet received): 1190232486.10222.37.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/[email protected]
Quoted 16 lines · Jeremy Katz
Quoted 3 lines · Avi Kivity
Quoted 3 lines
The attached patch adds support for a relatively basic boot device selection menu to the bochs bios code.
[snip]
Quoted 8 lines
This is nice! Two comments:
- it would be nice for qemu to provide the bios an indication if the '-boot' parameter was specified to qemu. if so, the bios should skip the menu on first bootup, reducing the boot delay. On subsequent boots the menu should be offered. This is primarily useful in managed environments.
Quoted 8 lines
While this could be nice, at the same time, -boot is going to be getting passed for a long time, even when it's no longer needed, just due to people not updating their tools. So I almost think it's better to take the 3 second hit since it's going to be there every other time. We could tweak it to be a little bit less, but 3 seems in line with what other BIOSes seem to do.
I almost agree. Let people upgrade their tools, they ought to have many reasons besides the boot menu.
[we could add a -dont-show-boot-menu parameter to make this explicit, but I don't think we should]
Quoted 7 lines
Quoted 5 lines
- coding this stuff in
rombios32.cinstead ofrombios.c(with its strange idea of C) is *much* preferable for maintainability. As far as i can tell, there is no reason not to do so, especially for code which is not called from the 16-bit OS.The code is called from the 16-bit OS, though.
No, it's called from the boot code. We're not returning to DOS after int 19.
Quoted 6 lines
It needs to be done
after rom scanning has been done so that we can show network or not as appropriate. And unless I'm missing something, calling intorombios32.coutside ofrombios32_init()is going to add just as much hard-to-maintain code.
Why? the thunk into 32-bit mode can be shared and is a small piece of code. The boot menu is much larger and can potentially grow (to control other options besides the boot device).
Signature · 7 lines
Do not meddle in the internals of kernels, for they are subtle and quick to panic. ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/