On Sun, 2007-09-16 at 22:00 +0200, Avi Kivity wrote:
> > The attached patch adds support for a relatively basic boot device
> > selection menu to the bochs bios code.  
[snip]
> 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.

> - 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.

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.

Signed-off-by: Jeremy Katz <[EMAIL PROTECTED]>

Jeremy
diff --git a/bios/BIOS-bochs-latest b/bios/BIOS-bochs-latest
index c10ae62..e13af69 100644
Binary files a/bios/BIOS-bochs-latest and b/bios/BIOS-bochs-latest differ
diff --git a/bios/BIOS-bochs-legacy b/bios/BIOS-bochs-legacy
index 131e62b..5c03460 100644
Binary files a/bios/BIOS-bochs-legacy and b/bios/BIOS-bochs-legacy differ
diff --git a/bios/rombios.c b/bios/rombios.c
index ac918ad..4ebdb71 100644
--- a/bios/rombios.c
+++ b/bios/rombios.c
@@ -1950,6 +1950,228 @@ print_cdromboot_failure( code )
   return;
 }
 
+#define WAIT_HZ 18
+/**
+ * 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.
+     */
+    ticks_to_wait = ticks;
+    prev_ticks = read_dword(0x0, 0x46c);
+    do
+    {
+        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);
+    return scan_code;
+}
+
+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();
+        bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, "\n\n\n\n\n\n\n");
+        bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, "          Select boot device\n\n");
+        bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, "            1. Floppy\n");
+        bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, "            2. Hard drive\n");
+        bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, "            3. CD-ROM\n");
+        if (max == 4)
+            bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, "            4. Network\n");
+        bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, "\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;
+
+    bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, "\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;
+    }
+}
+
+
 void
 nmi_handler_msg()
 {
@@ -10226,6 +10448,8 @@ post_default_ints:
   ;;
 #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

Reply via email to