[SeaBIOS] [PATCH] Boot from multiple USB drives as well as an HDD

Steve Goodrich steve.goodrich at se-eng.com
Thu Jun 7 21:58:06 CEST 2012


This change adds support for multiple USB mass storage devices in the boot
sequence.  Previously, only one HDD device (which included both USB and SATA
drives) was allowed in the boot sequence; USB drives were treated as HDDs.
This code allows USB drives to be treated separately from SATA drives.  Only
one HDD is allowed to boot (0x80) as has always been the case.  However,
multiple USB drives can be tried in the order they are selected in the
Bootlist.  This allows the user to have a bootorder which specifies USB,
then HDD, then another USB device; the system will attempt to boot the first
USB, then the HDD, then the second USB device.  I believe this does not
violate the BIOS Boot Specification.

Signed-off-by: Steve Goodrich <steve.goodrich at se-eng.com>
---
 src/block.c    |   19 ++++++++++++++++---
 src/blockcmd.c |    8 +++++++-
 src/boot.c     |   29 ++++++++++++++++++++++++++---
 src/boot.h     |    1 +
 src/disk.c     |    6 ++++--
 src/disk.h     |   10 +++++++---
 6 files changed, 61 insertions(+), 12 deletions(-)

diff --git a/src/block.c b/src/block.c
index 44ba9bd..7f973d2 100644
--- a/src/block.c
+++ b/src/block.c
@@ -16,7 +16,8 @@
 
 u8 FloppyCount VAR16VISIBLE;
 u8 CDCount;
-struct drive_s *IDMap[3][CONFIG_MAX_EXTDRIVE] VAR16VISIBLE;
+u8 USBCount; // keep track of USB MSC drives
+struct drive_s *IDMap[EXTTYPE_MAX][CONFIG_MAX_EXTDRIVE] VAR16VISIBLE;
 u8 *bounce_buf_fl VAR16VISIBLE;
 struct dpte_s DefaultDPTE VARLOW;
 
@@ -235,7 +236,7 @@ map_hd_drive(struct drive_s *drive_g)
     ASSERT32FLAT();
     struct bios_data_area_s *bda = MAKE_FLATPTR(SEG_BDA, 0);
     int hdid = bda->hdcount;
-    dprintf(3, "Mapping hd drive %p to %d\n", drive_g, hdid);
+    dprintf(3, "Mapping hd drive %p to %d: 0x%x\n", drive_g, hdid,
EXTSTART_HD + bda->hdcount);
     add_drive(IDMap[EXTTYPE_HD], &bda->hdcount, drive_g);
 
     // Setup disk geometry translation.
@@ -249,10 +250,22 @@ map_hd_drive(struct drive_s *drive_g)
 void
 map_cd_drive(struct drive_s *drive_g)
 {
-    dprintf(3, "Mapping cd drive %p\n", drive_g);
+    dprintf(3, "Mapping cd drive %p: 0x%x\n", drive_g, EXTSTART_CD +
CDCount);
     add_drive(IDMap[EXTTYPE_CD], &CDCount, drive_g);
 }
 
+// Map a USB drive
+void
+map_usb_drive(struct drive_s *drive_g)
+{
+    dprintf(3, "Mapping usb drive %p: 0x%x\n", drive_g, EXTSTART_USB +
USBCount);
+    add_drive(IDMap[EXTTYPE_USB], &USBCount, drive_g);
+
+    // Setup disk geometry translation.
+    setup_translation(drive_g);
+
+}
+
 // Map a floppy
 void
 map_floppy_drive(struct drive_s *drive_g)
diff --git a/src/blockcmd.c b/src/blockcmd.c
index 2dda04d..8deef81 100644
--- a/src/blockcmd.c
+++ b/src/blockcmd.c
@@ -175,7 +175,13 @@ scsi_init_drive(struct drive_s *drive, const char *s,
int prio)
 
     char *desc = znprintf(MAXDESCSIZE, "%s Drive %s %s %s"
                           , s, vendor, product, rev);
-    boot_add_hd(drive, desc, prio);
+    if (drive->type == DTYPE_USB) {
+        // add USB drive
+        boot_add_usb(drive, desc, prio);
+    } else {
+        // add standard HDD
+        boot_add_hd(drive, desc, prio);
+    }
     return 0;
 }
 
diff --git a/src/boot.c b/src/boot.c
index 3f6375b..a370e95 100644
--- a/src/boot.c
+++ b/src/boot.c
@@ -15,7 +15,6 @@
 #include "pci.h" //pci_bdf_to_*
 #include "usb.h" // struct usbdevice_s
 
-
 /****************************************************************
  * Boot priority ordering
  ****************************************************************/
@@ -229,7 +228,8 @@ static int CheckFloppySig = 1;
 static int DefaultFloppyPrio = 101;
 static int DefaultCDPrio     = 102;
 static int DefaultHDPrio     = 103;
-static int DefaultBEVPrio    = 104;
+static int DefaultUSBPrio    = 104; // insert default USB drive priority
+static int DefaultBEVPrio    = 105;
 
 void
 boot_setup(void)
@@ -282,6 +282,9 @@ static struct bootentry_s *BootList;
 #define IPL_TYPE_FLOPPY      0x01
 #define IPL_TYPE_HARDDISK    0x02
 #define IPL_TYPE_CDROM       0x03
+#define IPL_TYPE_PCMCIA      0x04   // add PCMCIA type for completeness
+#define IPL_TYPE_USB         0x05   // add USB type for our needs
+#define IPL_TYPE_NETWORK     0x06
 #define IPL_TYPE_CBFS        0x20
 #define IPL_TYPE_BEV         0x80
 #define IPL_TYPE_BCV         0x81
@@ -363,6 +366,14 @@ boot_add_hd(struct drive_s *drive_g, const char *desc,
int prio)
                   , (u32)drive_g, desc);
 }
 
+// Add a bootentry for the given USB MSC device
+void
+boot_add_usb(struct drive_s *drive_g, const char *desc, int prio)
+{
+    bootentry_add(IPL_TYPE_USB, defPrio(prio, DefaultUSBPrio)
+                  , (u32)drive_g, desc);
+}
+
 void
 boot_add_cd(struct drive_s *drive_g, const char *desc, int prio)
 {
@@ -498,6 +509,10 @@ boot_prep(void)
             map_hd_drive(pos->drive);
             add_bev(IPL_TYPE_HARDDISK, 0);
             break;
+        case IPL_TYPE_USB:
+            map_usb_drive(pos->drive);
+            add_bev(IPL_TYPE_USB, pos->data);
+            break;
         case IPL_TYPE_CDROM:
             map_cd_drive(pos->drive);
             // NO BREAK
@@ -511,6 +526,7 @@ boot_prep(void)
     // If nothing added a floppy/hd boot - add it manually.
     add_bev(IPL_TYPE_FLOPPY, 0);
     add_bev(IPL_TYPE_HARDDISK, 0);
+
 }
 
 
@@ -636,6 +652,9 @@ boot_fail(void)
     farcall16big(&br);
 }
 
+// track the next USB drive from which to boot
+int USB_Drive_Number VARLOW = 0;
+
 // Determine next boot method and attempt a boot using it.
 static void
 do_boot(int seq_nr)
@@ -655,11 +674,15 @@ do_boot(int seq_nr)
         break;
     case IPL_TYPE_HARDDISK:
         printf("Booting from Hard Disk...\n");
-        boot_disk(0x80, 1);
+        boot_disk(EXTSTART_HD, 1);
         break;
     case IPL_TYPE_CDROM:
         boot_cdrom((void*)ie->vector);
         break;
+    case IPL_TYPE_USB:
+        printf("Booting from USB drive...\n");
+        boot_disk(EXTSTART_USB + USB_Drive_Number++, 1);
+        break;
     case IPL_TYPE_CBFS:
         boot_cbfs((void*)ie->vector);
         break;
diff --git a/src/boot.h b/src/boot.h
index c7c34dc..823bd90 100644
--- a/src/boot.h
+++ b/src/boot.h
@@ -9,6 +9,7 @@ void boot_add_bcv(u16 seg, u16 ip, u16 desc, int prio);
 struct drive_s;
 void boot_add_floppy(struct drive_s *drive_g, const char *desc, int prio);
 void boot_add_hd(struct drive_s *drive_g, const char *desc, int prio);
+void boot_add_usb(struct drive_s *drive_g, const char *desc, int prio);
 void boot_add_cd(struct drive_s *drive_g, const char *desc, int prio);
 void boot_add_cbfs(void *data, const char *desc, int prio);
 void boot_prep(void);
diff --git a/src/disk.c b/src/disk.c
index 3ca5697..23e038c 100644
--- a/src/disk.c
+++ b/src/disk.c
@@ -828,9 +828,11 @@ handle_legacy_disk(struct bregs *regs, u8 extdrive)
     }
 
     struct drive_s *drive_g;
-    if (extdrive >= EXTSTART_CD)
+    if (extdrive >= EXTSTART_CD) // drive is in CD range?
         drive_g = getDrive(EXTTYPE_CD, extdrive - EXTSTART_CD);
-    else
+    else if (extdrive >= EXTSTART_USB) // drive is in USB-to-CD range?
+        drive_g = getDrive(EXTTYPE_USB, extdrive - EXTSTART_USB);
+    else // anything else is HDD
         drive_g = getDrive(EXTTYPE_HD, extdrive - EXTSTART_HD);
     if (!drive_g)
         goto fail;
diff --git a/src/disk.h b/src/disk.h
index 6776ee6..ba6e52a 100644
--- a/src/disk.h
+++ b/src/disk.h
@@ -240,10 +240,13 @@ struct drive_s {
 #define TRANSLATION_RECHS 3
 
 #define EXTTYPE_FLOPPY 0
-#define EXTTYPE_HD 1
-#define EXTTYPE_CD 2
+#define EXTTYPE_HD  1
+#define EXTTYPE_CD  2
+#define EXTTYPE_USB 3
+#define EXTTYPE_MAX 4   // insert new items above; use this for array sizes
 
 #define EXTSTART_HD 0x80
+#define EXTSTART_USB 0xC0
 #define EXTSTART_CD 0xE0
 
 
@@ -252,12 +255,13 @@ struct drive_s {
  ****************************************************************/
 
 // block.c
-extern u8 FloppyCount, CDCount;
+extern u8 FloppyCount, CDCount, USBCount;
 extern u8 *bounce_buf_fl;
 struct drive_s *getDrive(u8 exttype, u8 extdriveoffset);
 int getDriveId(u8 exttype, struct drive_s *drive_g);
 void map_floppy_drive(struct drive_s *drive_g);
 void map_hd_drive(struct drive_s *drive_g);
+void map_usb_drive(struct drive_s *drive_g);
 void map_cd_drive(struct drive_s *drive_g);
 int process_op(struct disk_op_s *op);
 int send_disk_op(struct disk_op_s *op);
-- 
1.7.9


            -- Steve G.

Sage Electronic Engineering
201 Terry St., 2nd Floor
Longmont, CO 80501
(303) 495-5499 x105





More information about the SeaBIOS mailing list