Simplify boot code.
authorKevin O'Connor <kevin@koconnor.net>
Sun, 8 Feb 2009 21:57:22 +0000 (16:57 -0500)
committerKevin O'Connor <kevin@koconnor.net>
Sun, 8 Feb 2009 21:57:22 +0000 (16:57 -0500)
Make sure every IPL entry has a description.
Remove output printing helpers - have each caller output what they want.
Add strtcpy function to ensure descriptions don't go over 32 characters.
Breakup code to launch each IPL entry to its own function.

src/boot.c
src/util.c
src/util.h

index 5bcb4a412ae3878874c66d0bd79410cb3f932dc2..9dec69e757f329fa2076ade6bc52ef2a7b4bda3b 100644 (file)
@@ -30,21 +30,24 @@ boot_setup()
     memset(&IPL, 0, sizeof(IPL));
 
     // Floppy drive
-    struct ipl_entry_s *ip = &IPL.table[0];
-    ip->type = IPL_TYPE_FLOPPY;
-    ip++;
+    struct ipl_entry_s *ie = &IPL.table[0];
+    ie->type = IPL_TYPE_FLOPPY;
+    ie->description = "Floppy";
+    ie++;
 
     // First HDD
-    ip->type = IPL_TYPE_HARDDISK;
-    ip++;
+    ie->type = IPL_TYPE_HARDDISK;
+    ie->description = "Hard Disk";
+    ie++;
 
     // CDROM
     if (CONFIG_CDROM_BOOT) {
-        ip->type = IPL_TYPE_CDROM;
-        ip++;
+        ie->type = IPL_TYPE_CDROM;
+        ie->description = "CD-Rom";
+        ie++;
     }
 
-    IPL.count = ip - IPL.table;
+    IPL.count = ie - IPL.table;
     SET_EBDA(boot_sequence, 0xffff);
     if (CONFIG_COREBOOT) {
         // XXX - hardcode defaults for coreboot.
@@ -72,76 +75,16 @@ add_bev(u16 seg, u16 bev, u16 desc)
     if (IPL.count >= ARRAY_SIZE(IPL.table))
         return;
 
-    struct ipl_entry_s *ip = &IPL.table[IPL.count];
-    ip->type = IPL_TYPE_BEV;
-    ip->vector = (seg << 16) | bev;
+    struct ipl_entry_s *ie = &IPL.table[IPL.count];
+    ie->type = IPL_TYPE_BEV;
+    ie->vector = (seg << 16) | bev;
     if (desc)
-        ip->description = MAKE_FLATPTR(seg, desc);
+        ie->description = MAKE_FLATPTR(seg, desc);
 
     IPL.count++;
 }
 
 
-/****************************************************************
- * Printing helpers
- ****************************************************************/
-
-static const char drivetypes[][10]={
-    "", "Floppy", "Hard Disk", "CD-Rom", "Network"
-};
-
-// display a device name
-static void
-printf_bootdev(u16 bootdev)
-{
-    u16 type = IPL.table[bootdev].type;
-
-    /* NIC appears as type 0x80 */
-    if (type == IPL_TYPE_BEV)
-        type = 0x4;
-    if (type == 0 || type > 0x4) {
-        printf("Unknown");
-        return;
-    }
-    printf("%s", drivetypes[type]);
-
-    /* print product string if BEV */
-    char *description_fl = IPL.table[bootdev].description;
-    if (type == 4 && description_fl != 0) {
-        char description[33];
-        /* first 32 bytes are significant */
-        memcpy(description, description_fl, 32);
-        /* terminate string */
-        description[32] = 0;
-        printf(" [%.s]", description);
-    }
-}
-
-// display the boot device
-static void
-print_boot_device(u16 bootdev)
-{
-    printf("Booting from ");
-    printf_bootdev(bootdev);
-    printf("...\n");
-}
-
-// display the reason why a boot failed
-static void
-print_boot_failure(u16 type, u8 reason)
-{
-    printf("Boot failed");
-    if (type < 4) {
-        /* Report the reason too */
-        if (reason==0)
-            printf(": not a bootable disk");
-        else
-            printf(": could not read the boot disk");
-    }
-    printf("\n\n");
-}
-
-
 /****************************************************************
  * Boot menu
  ****************************************************************/
@@ -170,9 +113,10 @@ interactive_bootmenu()
     int count = IPL.count;
     int i;
     for (i = 0; i < count; i++) {
-        printf("%d. ", i+1);
-        printf_bootdev(i);
-        printf("\n");
+        struct ipl_entry_s *ie = &IPL.table[i];
+        char desc[33];
+        printf("%d. %s\n", i+1
+               , strtcpy(desc, ie->description, ARRAY_SIZE(desc)));
     }
 
     for (;;) {
@@ -197,7 +141,80 @@ interactive_bootmenu()
  ****************************************************************/
 
 static void
-try_boot(u16 seq_nr)
+call_boot_entry(u16 bootseg, u16 bootip, u8 bootdrv)
+{
+    dprintf(1, "Booting from %x:%x\n", bootseg, bootip);
+
+    struct bregs br;
+    memset(&br, 0, sizeof(br));
+    br.ip = bootip;
+    br.cs = bootseg;
+    // Set the magic number in ax and the boot drive in dl.
+    br.dl = bootdrv;
+    br.ax = 0xaa55;
+    call16(&br);
+}
+
+// Boot from a disk (either floppy or harddrive)
+static void
+boot_disk(u8 bootdrv, int checksig)
+{
+    u16 bootseg = 0x07c0;
+
+    // Read sector
+    struct bregs br;
+    memset(&br, 0, sizeof(br));
+    br.dl = bootdrv;
+    br.es = bootseg;
+    br.ah = 2;
+    br.al = 1;
+    br.cl = 1;
+    call16_int(0x13, &br);
+
+    if (br.flags & F_CF) {
+        printf("Boot failed: could not read the boot disk\n\n");
+        return;
+    }
+
+    if (checksig) {
+        struct mbr_s *mbr = (void*)0;
+        if (GET_FARVAR(bootseg, mbr->signature) != MBR_SIGNATURE) {
+            printf("Boot failed: not a bootable disk\n\n");
+            return;
+        }
+    }
+
+    /* Canonicalize bootseg:bootip */
+    u16 bootip = (bootseg & 0x0fff) << 4;
+    bootseg &= 0xf000;
+
+    call_boot_entry(bootseg, bootip, bootdrv);
+}
+
+// Boot from a CD-ROM
+static void
+boot_cdrom()
+{
+    if (! CONFIG_CDROM_BOOT)
+        return;
+    int status = cdrom_boot();
+    if (status) {
+        printf("Boot failed: Could not read from CDROM (code %04x)\n", status);
+        return;
+    }
+
+    u16 ebda_seg = get_ebda_seg();
+    u8 bootdrv = GET_EBDA2(ebda_seg, cdemu.emulated_drive);
+    u16 bootseg = GET_EBDA2(ebda_seg, cdemu.load_segment);
+    /* Canonicalize bootseg:bootip */
+    u16 bootip = (bootseg & 0x0fff) << 4;
+    bootseg &= 0xf000;
+
+    call_boot_entry(bootseg, bootip, bootdrv);
+}
+
+static void
+do_boot(u16 seq_nr)
 {
     if (! CONFIG_BOOT)
         BX_PANIC("Boot support not compiled in.\n");
@@ -214,103 +231,34 @@ try_boot(u16 seq_nr)
 
     if (bootdev >= IPL.count) {
         dprintf(1, "Invalid boot device (0x%x)\n", bootdev);
-        return;
+        goto fail;
     }
 
     /* Do the loading, and set up vector as a far pointer to the boot
      * address, and bootdrv as the boot drive */
-    print_boot_device(bootdev);
+    struct ipl_entry_s *ie = &IPL.table[bootdev];
+    char desc[33];
+    printf("Booting from %s...\n"
+           , strtcpy(desc, ie->description, ARRAY_SIZE(desc)));
 
-    u16 type = IPL.table[bootdev].type;
-
-    u16 bootseg, bootip;
-    u8 bootdrv = 0;
-    struct bregs cr;
-    switch(type) {
+    switch(ie->type) {
     case IPL_TYPE_FLOPPY:
+        boot_disk(0x00, IPL.checkfloppysig);
+        break;
     case IPL_TYPE_HARDDISK:
-
-        bootdrv = (type == IPL_TYPE_HARDDISK) ? 0x80 : 0x00;
-        bootseg = 0x07c0;
-
-        // Read sector
-        memset(&cr, 0, sizeof(cr));
-        cr.dl = bootdrv;
-        cr.es = bootseg;
-        cr.ah = 2;
-        cr.al = 1;
-        cr.cl = 1;
-        call16_int(0x13, &cr);
-
-        if (cr.flags & F_CF) {
-            print_boot_failure(type, 1);
-            return;
-        }
-
-        /* Always check the signature on a HDD boot sector; on FDD,
-         * only do the check if configured for it */
-        if (type != IPL_TYPE_FLOPPY || IPL.checkfloppysig) {
-            struct mbr_s *mbr = (void*)0;
-            if (GET_FARVAR(bootseg, mbr->signature) != MBR_SIGNATURE) {
-                print_boot_failure(type, 0);
-                return;
-            }
-        }
-
-        /* Canonicalize bootseg:bootip */
-        bootip = (bootseg & 0x0fff) << 4;
-        bootseg &= 0xf000;
+        boot_disk(0x80, 1);
         break;
-    case IPL_TYPE_CDROM: {
-        /* CD-ROM */
-        if (! CONFIG_CDROM_BOOT)
-            return;
-        int status = cdrom_boot();
-        if (status) {
-            printf("CDROM boot failure code : %04x\n", status);
-            print_boot_failure(type, 1);
-            return;
-        }
-
-        u16 ebda_seg = get_ebda_seg();
-        bootdrv = GET_EBDA2(ebda_seg, cdemu.emulated_drive);
-        bootseg = GET_EBDA2(ebda_seg, cdemu.load_segment);
-        /* Canonicalize bootseg:bootip */
-        bootip = (bootseg & 0x0fff) << 4;
-        bootseg &= 0xf000;
+    case IPL_TYPE_CDROM:
+        boot_cdrom();
         break;
-    }
-    case IPL_TYPE_BEV: {
-        /* Expansion ROM with a Bootstrap Entry Vector (a far
-         * pointer) */
-        u32 vector = IPL.table[bootdev].vector;
-        bootseg = vector >> 16;
-        bootip = vector & 0xffff;
+    case IPL_TYPE_BEV:
+        call_boot_entry(ie->vector >> 16, ie->vector & 0xffff, 0);
         break;
     }
-    default:
-        return;
-    }
-
-    /* Debugging info */
-    dprintf(1, "Booting from %x:%x\n", bootseg, bootip);
-
-    memset(&cr, 0, sizeof(cr));
-    cr.ip = bootip;
-    cr.cs = bootseg;
-    // Set the magic number in ax and the boot drive in dl.
-    cr.dl = bootdrv;
-    cr.ax = 0xaa55;
-    call16(&cr);
-}
-
-static void
-do_boot(u16 seq_nr)
-{
-    try_boot(seq_nr);
 
     // Boot failed: invoke the boot recovery function
     struct bregs br;
+fail:
     memset(&br, 0, sizeof(br));
     call16_int(0x18, &br);
 }
index 6a0849b507ce3cac446963dcc4ec79651f7dbbe1..7eec39d846594d009613b20acb4446473e4390bd 100644 (file)
@@ -166,6 +166,17 @@ memmove(void *d, const void *s, size_t len)
     return d;
 }
 
+// Copy a string - truncating it if necessary.
+char *
+strtcpy(char *dest, const char *src, size_t len)
+{
+    char *d = dest;
+    while (len-- && *src != '\0')
+        *d++ = *src++;
+    *d = '\0';
+    return dest;
+}
+
 // Wait for 'usec' microseconds with irqs enabled.
 static void
 usleep(u32 usec)
index aa82d4bd8a7d542940c1b89a95b6263321e81445..0757fa4dd019fcc8b2398d95ec176aaff1fb3ec3 100644 (file)
@@ -74,6 +74,7 @@ void *memcpy(void *d1, const void *s1, size_t len);
 inline void memcpy_far(u16 d_seg, void *d_far
                        , u16 s_seg, const void *s_far, size_t len);
 void *memmove(void *d, const void *s, size_t len);
+char *strtcpy(char *dest, const char *src, size_t len);
 struct bregs;
 inline void call16(struct bregs *callregs);
 inline void call16big(struct bregs *callregs);