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
diff -u -u -r1.182 rombios.c
--- rombios.c 1 Aug 2007 17:09:51 -0000 1.182
+++ rombios.c 11 Sep 2007 15:10:53 -0000
@@ -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
kvm-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/kvm-devel