Forward port new boot menu features from bochs bios.
authorKevin O'Connor <kevin@koconnor.net>
Sat, 5 Apr 2008 19:51:12 +0000 (15:51 -0400)
committerKevin O'Connor <kevin@koconnor.net>
Sat, 5 Apr 2008 19:51:12 +0000 (15:51 -0400)
Support boot menu during last stage of post.
Improve description of option roms.
Support printf of "%.s" to force printing strings on stack.
Enhance memcpy so that it also works in real-mode.

Makefile
src/biosvar.h
src/boot.c
src/output.c
src/post.c
src/post_menu.c [new file with mode: 0644]
src/romlayout.S
src/util.c
src/util.h

index cb1cdd0afec2ca7c9ebb7752dbd1c911b91c0324..3808086d77e14354b35cfeb4c3bd0632c5ff6047 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -10,7 +10,7 @@ OUT=out/
 # Source files
 SRC16=floppy.c disk.c system.c clock.c serial.c kbd.c mouse.c output.c \
       boot.c ata.c cdrom.c apm.c util.c pcibios.c pci.c
-SRC32=post.c output.c rombios32.c util.c ata.c kbd.c pci.c
+SRC32=post.c output.c rombios32.c util.c ata.c kbd.c pci.c boot.c post_menu.c
 TABLESRC=font.c cbt.c floppy_dbt.c
 
 cc-option = $(shell if test -z "`$(1) $(2) -S -o /dev/null -xc \
index fe957e57304365676d15036108ae864b19534d28..1c791dca5e3141830b5f2f99352922b870b2983e 100644 (file)
@@ -213,6 +213,7 @@ struct ipl_s {
     struct ipl_entry_s table[8];
     u16 count;
     u16 sequence;
+    u16 bootfirst;
 };
 
 #define IPL_TYPE_FLOPPY      0x01
index c1f88469d570ef56e31419a257b3def77734adc8..53577ecfe3a60b5a21c18d63b2264892447522ae 100644 (file)
@@ -26,17 +26,36 @@ static const char drivetypes[][10]={
     "", "Floppy","Hard Disk","CD-Rom", "Network"
 };
 
-static void
-print_boot_device(u16 type)
+void
+printf_bootdev(u16 bootdev)
 {
+    u16 type = GET_EBDA(ipl.table[bootdev].type);
+
     /* NIC appears as type 0x80 */
     if (type == IPL_TYPE_BEV)
         type = 0x4;
     if (type == 0 || type > 0x4)
         BX_PANIC("Bad drive type\n");
-    printf("Booting from %s...\n", drivetypes[type]);
+    printf("%s", drivetypes[type]);
+
+    /* print product string if BEV */
+    void *far_description = (void*)GET_EBDA(ipl.table[bootdev].description);
+    if (type == 4 && far_description != 0) {
+        char description[33];
+        /* first 32 bytes are significant */
+        memcpy(MAKE_FARPTR(GET_SEG(SS), &description), far_description, 32);
+        /* terminate string */
+        description[32] = 0;
+        printf(" [%.s]", description);
+    }
+}
 
-    // XXX - latest cvs has BEV description
+static void
+print_boot_device(u16 bootdev)
+{
+    printf("Booting from ");
+    printf_bootdev(bootdev);
+    printf("...\n");
 }
 
 //--------------------------------------------------------------------------
@@ -67,14 +86,20 @@ try_boot(u16 seq_nr)
 
     SET_EBDA(ipl.sequence, seq_nr);
 
-    u16 bootseg;
-    u8 bootdrv = 0;
-    u16 bootdev, bootip;
-
-    bootdev = inb_cmos(CMOS_BIOS_BOOTFLAG2);
+    u16 bootdev = inb_cmos(CMOS_BIOS_BOOTFLAG2);
     bootdev |= ((inb_cmos(CMOS_BIOS_BOOTFLAG1) & 0xf0) << 4);
     bootdev >>= 4 * seq_nr;
     bootdev &= 0xf;
+
+    /* Read user selected device */
+    u16 bootfirst = GET_EBDA(ipl.bootfirst);
+    if (bootfirst != 0xFFFF) {
+        bootdev = bootfirst;
+        /* Reset boot sequence */
+        SET_EBDA(ipl.bootfirst, 0xFFFF);
+        SET_EBDA(ipl.sequence, 0xFFFF);
+    }
+
     if (bootdev == 0)
         BX_PANIC("No bootable device.\n");
 
@@ -85,12 +110,15 @@ try_boot(u16 seq_nr)
         BX_INFO("Invalid boot device (0x%x)\n", bootdev);
         return;
     }
-    u16 type = GET_EBDA(ipl.table[bootdev].type);
 
     /* Do the loading, and set up vector as a far pointer to the boot
      * address, and bootdrv as the boot drive */
-    print_boot_device(type);
+    print_boot_device(bootdev);
+
+    u16 type = GET_EBDA(ipl.table[bootdev].type);
 
+    u16 bootseg, bootip;
+    u8 bootdrv = 0;
     struct bregs cr;
     switch(type) {
     case IPL_TYPE_FLOPPY: /* FDD */
index 8983f979d5b322bfc2ddf113e96dce92fc3e3c11..3d5361366ef69fcee78ea99a4af89c1508ff08c8 100644 (file)
@@ -154,6 +154,14 @@ bvprintf(u16 action, const char *fmt, va_list args)
             val = va_arg(args, int);
             putc(action, val);
             break;
+        case '.':
+            // Hack to support "%.s" - meaning string on stack.
+            if (GET_VAR(CS, *(u8*)(n+1)) != 's')
+                break;
+            n++;
+            sarg = va_arg(args, const char *);
+            puts(action, sarg);
+            break;
         case 's':
             sarg = va_arg(args, const char *);
             puts_cs(action, sarg);
index 5ba9a2926ed3dc3c46de43e2d5c9caffc819d5dc..47349916fa9e4663d6423dc15e3f69a664ce5488 100644 (file)
@@ -289,6 +289,7 @@ init_boot_vectors()
 
     ebda->ipl.count = ip - ebda->ipl.table;
     ebda->ipl.sequence = 0xffff;
+    ebda->ipl.bootfirst = 0xffff;
 }
 
 static void
@@ -340,7 +341,7 @@ rom_scan(u32 start, u32 end)
 
         u16 desc = *(u16*)&rom[0x1a+0x10];
         if (desc)
-            ip->description = (FARPTR_TO_SEG(rom) << 16) | desc;
+            ip->description = (u32)MAKE_FARPTR(FARPTR_TO_SEG(rom), desc);
 
         ebda->ipl.count++;
     }
@@ -385,6 +386,8 @@ post()
 
     rom_scan(0xc8000, 0xe0000);
 
+    interactive_bootmenu();
+
     // reset the memory (some boot loaders such as syslinux suppose
     // that the memory is set to zero)
     memset((void*)0x40000, 0, 0x40000); // XXX - shouldn't use globals
diff --git a/src/post_menu.c b/src/post_menu.c
new file mode 100644 (file)
index 0000000..91b18fe
--- /dev/null
@@ -0,0 +1,81 @@
+// Menu presented during final phase of "post".
+//
+// Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
+// Copyright (C) 2002  MandrakeSoft S.A.
+//
+// This file may be distributed under the terms of the GNU GPLv3 license.
+
+#include "biosvar.h" // GET_EBDA
+#include "util.h" // usleep
+
+static u8
+check_for_keystroke()
+{
+    struct bregs br;
+    memset(&br, 0, sizeof(br));
+    br.ah = 1;
+    call16_int(0x16, &br);
+    return !(br.flags & F_ZF);
+}
+
+static u8
+get_keystroke()
+{
+    struct bregs br;
+    memset(&br, 0, sizeof(br));
+    call16_int(0x16, &br);
+    return br.ah;
+}
+
+static void
+udelay_and_check_for_keystroke(u32 usec, int count)
+{
+    int i;
+    for (i = 1; i <= count; i++) {
+        usleep(usec);
+        if (check_for_keystroke())
+            break;
+    }
+}
+
+void
+interactive_bootmenu()
+{
+    while (check_for_keystroke())
+        get_keystroke();
+
+    printf("Press F12 for boot menu.\n\n");
+
+    udelay_and_check_for_keystroke(500000, 5);
+    if (! check_for_keystroke())
+        return;
+    u8 scan_code = get_keystroke();
+    if (scan_code != 0x58)
+        /* not F12 */
+        return;
+
+    while (check_for_keystroke())
+        get_keystroke();
+
+    printf("Select boot device:\n\n");
+
+    int count = GET_EBDA(ipl.count);
+    int i;
+    for (i = 0; i < count; i++) {
+        printf("%d. ", i+1);
+        printf_bootdev(i);
+        printf("\n");
+    }
+
+    for (;;) {
+        scan_code = get_keystroke();
+        if (scan_code == 0x01 || scan_code == 0x58)
+            /* ESC or F12 */
+            break;
+        if (scan_code <= count + 1) {
+            SET_EBDA(ipl.bootfirst, scan_code - 1);
+            break;
+        }
+    }
+    printf("\n");
+}
index c5f48eb68b7fe282f1db81f94d80377b9c2d6ed5..baf68f354cdbea4ca210161e901e0b95e9790e81 100644 (file)
@@ -411,6 +411,7 @@ entry_18:
         IRQ_TRAMPOLINE 10
         IRQ_TRAMPOLINE 13
         IRQ_TRAMPOLINE 15
+        IRQ_TRAMPOLINE 16
         IRQ_TRAMPOLINE 18
         IRQ_TRAMPOLINE 19
         IRQ_TRAMPOLINE 1c
index 438bf755eb091f9df08afa0b3ff8048c2fb49665..845609bc0613a133ca3141aaf6d0a2db31ae3090 100644 (file)
@@ -31,15 +31,18 @@ memset(void *s, int c, size_t n)
 }
 
 void *
-memcpy(void *d1, const void *s1, size_t len)
+memcpy(void *far_d1, const void *far_s1, size_t len)
 {
-    u8 *d = d1;
-    const u8 *s = s1;
+    u8 *d = far_d1;
+    u8 *s = (u8*)far_s1;
 
-    while (len--)
-        *d++ = *s++;
+    while (len--) {
+        SET_FARPTR(*d, GET_FARPTR(*s));
+        d++;
+        s++;
+    }
 
-    return d1;
+    return far_d1;
 }
 
 void
index 1566adfb7d70037e666977cec4420873b572eabb..dff1a1166733de3a8defe2a9f95b2fb714cd0ac2 100644 (file)
@@ -154,4 +154,10 @@ void usleep(u32 count);
 // rombios32.c
 void rombios32_init(void);
 
+// boot.c
+void printf_bootdev(u16 bootdev);
+
+// post_menu.c
+void interactive_bootmenu();
+
 #endif // util.h