Add support for selecting harddrive order in boot menu.

Save ATA harddrive model name so that it can be shown from menu.
Minor - use "ata0-1" not "ata0 slave".
Fill fdpt info based on BIOS drive id - not the controller id.
Add BCV support to IPL code.
Use "BCV" system to set harddrive order (for both ata and option roms).
Also, don't show floppy/cdrom in boot menu if no drives found.
diff --git a/src/ata.c b/src/ata.c
index 3318305..659de20 100644
--- a/src/ata.c
+++ b/src/ata.c
@@ -14,6 +14,7 @@
 #include "pci.h" // pci_find_class
 #include "pci_ids.h" // PCI_CLASS_STORAGE_OTHER
 #include "pci_regs.h" // PCI_INTERRUPT_LINE
+#include "boot.h" // add_bcv_hd
 #include "disk.h" // struct ata_s
 #include "atabits.h" // ATA_CB_STAT
 
@@ -504,129 +505,9 @@
 
 
 /****************************************************************
- * ATA detect and init
+ * Disk geometry translation
  ****************************************************************/
 
-static void
-report_model(int driveid, u8 *buffer)
-{
-    u8 model[41];
-
-    // Read model name
-    int i;
-    for (i=0; i<40; i+=2) {
-        model[i] = buffer[i+54+1];
-        model[i+1] = buffer[i+54];
-    }
-
-    // Reformat
-    model[40] = 0x00;
-    for (i=39; i>0; i--) {
-        if (model[i] != 0x20)
-            break;
-        model[i] = 0x00;
-    }
-
-    u8 channel = driveid / 2;
-    u8 slave = driveid % 2;
-    // XXX - model on stack not %cs
-    printf("ata%d %s: %s", channel, slave ? " slave" : "master", model);
-}
-
-static u8
-get_ata_version(u8 *buffer)
-{
-    u16 ataversion = *(u16*)&buffer[160];
-    u8 version;
-    for (version=15; version>0; version--)
-        if (ataversion & (1<<version))
-            break;
-    return version;
-}
-
-static int
-init_drive_atapi(int driveid)
-{
-    // Send an IDENTIFY_DEVICE_PACKET command to device
-    u8 buffer[0x0200];
-    memset(buffer, 0, sizeof(buffer));
-    struct disk_op_s dop;
-    dop.driveid = driveid;
-    dop.command = ATA_CMD_IDENTIFY_DEVICE_PACKET;
-    dop.count = 1;
-    dop.lba = 1;
-    dop.buf_fl = MAKE_FLATPTR(GET_SEG(SS), buffer);
-    int ret = ata_cmd_data(&dop);
-    if (ret)
-        return ret;
-
-    // Success - setup as ATAPI.
-    SET_GLOBAL(ATA.devices[driveid].type, ATA_TYPE_ATAPI);
-
-    u8 type      = buffer[1] & 0x1f;
-    u8 removable = (buffer[0] & 0x80) ? 1 : 0;
-    u8 mode      = buffer[96] ? ATA_MODE_PIO32 : ATA_MODE_PIO16;
-    u16 blksize  = CDROM_SECTOR_SIZE;
-
-    SET_GLOBAL(ATA.devices[driveid].device, type);
-    SET_GLOBAL(ATA.devices[driveid].removable, removable);
-    SET_GLOBAL(ATA.devices[driveid].mode, mode);
-    SET_GLOBAL(ATA.devices[driveid].blksize, blksize);
-
-    // fill cdidmap
-    u8 cdcount = GET_GLOBAL(ATA.cdcount);
-    SET_GLOBAL(ATA.idmap[1][cdcount], driveid);
-    SET_GLOBAL(ATA.cdcount, ++cdcount);
-
-    report_model(driveid, buffer);
-    u8 version = get_ata_version(buffer);
-    if (GET_GLOBAL(ATA.devices[driveid].device)==ATA_DEVICE_CDROM)
-        printf(" ATAPI-%d CD-Rom/DVD-Rom\n", version);
-    else
-        printf(" ATAPI-%d Device\n", version);
-
-    return 0;
-}
-
-static void
-fill_fdpt(int driveid)
-{
-    if (driveid > 1)
-        return;
-
-    u16 nlc   = GET_GLOBAL(ATA.devices[driveid].lchs.cylinders);
-    u16 nlh   = GET_GLOBAL(ATA.devices[driveid].lchs.heads);
-    u16 nlspt = GET_GLOBAL(ATA.devices[driveid].lchs.spt);
-
-    u16 npc   = GET_GLOBAL(ATA.devices[driveid].pchs.cylinders);
-    u16 nph   = GET_GLOBAL(ATA.devices[driveid].pchs.heads);
-    u16 npspt = GET_GLOBAL(ATA.devices[driveid].pchs.spt);
-
-    struct extended_bios_data_area_s *ebda = get_ebda_ptr();
-    ebda->fdpt[driveid].precompensation = 0xffff;
-    ebda->fdpt[driveid].drive_control_byte = 0xc0 | ((nph > 8) << 3);
-    ebda->fdpt[driveid].landing_zone = npc;
-    ebda->fdpt[driveid].cylinders = nlc;
-    ebda->fdpt[driveid].heads = nlh;
-    ebda->fdpt[driveid].sectors = nlspt;
-
-    if (nlc == npc && nlh == nph && nlspt == npspt)
-        // no logical CHS mapping used, just physical CHS
-        // use Standard Fixed Disk Parameter Table (FDPT)
-        return;
-
-    // complies with Phoenix style Translated Fixed Disk Parameter
-    // Table (FDPT)
-    ebda->fdpt[driveid].phys_cylinders = npc;
-    ebda->fdpt[driveid].phys_heads = nph;
-    ebda->fdpt[driveid].phys_sectors = npspt;
-    ebda->fdpt[driveid].a0h_signature = 0xa0;
-
-    // Checksum structure.
-    u8 sum = checksum((u8*)&ebda->fdpt[driveid], sizeof(ebda->fdpt[driveid])-1);
-    ebda->fdpt[driveid].checksum = -sum;
-}
-
 static u8
 get_translation(int driveid)
 {
@@ -725,6 +606,87 @@
     SET_GLOBAL(ATA.devices[driveid].lchs.spt, spt);
 }
 
+
+/****************************************************************
+ * ATA detect and init
+ ****************************************************************/
+
+static void
+extract_model(int driveid, u8 *buffer)
+{
+    char *model = ATA.devices[driveid].model;
+    int maxsize = ARRAY_SIZE(ATA.devices[driveid].model);
+
+    // Read model name
+    int i;
+    for (i=0; i<maxsize; i+=2) {
+        model[i] = buffer[i+54+1];
+        model[i+1] = buffer[i+54];
+    }
+    model[maxsize-1] = 0x00;
+
+    // Trim trailing spaces
+    for (i=maxsize-2; i>0 && model[i] == 0x20; i--)
+        model[i] = 0x00;
+}
+
+static u8
+get_ata_version(u8 *buffer)
+{
+    u16 ataversion = *(u16*)&buffer[160];
+    u8 version;
+    for (version=15; version>0; version--)
+        if (ataversion & (1<<version))
+            break;
+    return version;
+}
+
+static int
+init_drive_atapi(int driveid)
+{
+    // Send an IDENTIFY_DEVICE_PACKET command to device
+    u8 buffer[0x0200];
+    memset(buffer, 0, sizeof(buffer));
+    struct disk_op_s dop;
+    dop.driveid = driveid;
+    dop.command = ATA_CMD_IDENTIFY_DEVICE_PACKET;
+    dop.count = 1;
+    dop.lba = 1;
+    dop.buf_fl = MAKE_FLATPTR(GET_SEG(SS), buffer);
+    int ret = ata_cmd_data(&dop);
+    if (ret)
+        return ret;
+
+    // Success - setup as ATAPI.
+    SET_GLOBAL(ATA.devices[driveid].type, ATA_TYPE_ATAPI);
+
+    u8 type      = buffer[1] & 0x1f;
+    u8 removable = (buffer[0] & 0x80) ? 1 : 0;
+    u8 mode      = buffer[96] ? ATA_MODE_PIO32 : ATA_MODE_PIO16;
+    u16 blksize  = CDROM_SECTOR_SIZE;
+
+    SET_GLOBAL(ATA.devices[driveid].device, type);
+    SET_GLOBAL(ATA.devices[driveid].removable, removable);
+    SET_GLOBAL(ATA.devices[driveid].mode, mode);
+    SET_GLOBAL(ATA.devices[driveid].blksize, blksize);
+
+    // fill cdidmap
+    u8 cdcount = GET_GLOBAL(ATA.cdcount);
+    SET_GLOBAL(ATA.idmap[1][cdcount], driveid);
+    SET_GLOBAL(ATA.cdcount, cdcount+1);
+
+    // Report drive info to user.
+    u8 channel = driveid / 2;
+    u8 slave = driveid % 2;
+    u8 version = get_ata_version(buffer);
+    extract_model(driveid, buffer);
+    printf("ata%d-%d: %s ATAPI-%d %s\n", channel, slave
+           , ATA.devices[driveid].model, version
+           , type == ATA_DEVICE_CDROM ? "CD-Rom/DVD-Rom" : "Device");
+
+    return 0;
+}
+
 static int
 init_drive_ata(int driveid)
 {
@@ -770,23 +732,21 @@
     // Setup disk geometry translation.
     setup_translation(driveid);
 
-    // fill hdidmap
-    u8 hdcount = GET_BDA(hdcount);
-    SET_GLOBAL(ATA.idmap[0][hdcount], driveid);
-    SET_BDA(hdcount, ++hdcount);
-
-    // Fill "fdpt" structure.
-    fill_fdpt(driveid);
-
     // Report drive info to user.
-    u64 sizeinmb = GET_GLOBAL(ATA.devices[driveid].sectors) >> 11;
-    report_model(driveid, buffer);
+    u8 channel = driveid / 2;
+    u8 slave = driveid % 2;
     u8 version = get_ata_version(buffer);
+    extract_model(driveid, buffer);
+    char *model = ATA.devices[driveid].model;
+    printf("ata%d-%d: %s ATA-%d Hard-Disk ", channel, slave, model, version);
+    u64 sizeinmb = sectors >> 11;
     if (sizeinmb < (1 << 16))
-        printf(" ATA-%d Hard-Disk (%u MiBytes)\n", version, (u32)sizeinmb);
+        printf("(%u MiBytes)\n", (u32)sizeinmb);
     else
-        printf(" ATA-%d Hard-Disk (%u GiBytes)\n", version
-               , (u32)(sizeinmb >> 10));
+        printf("(%u GiBytes)\n", (u32)(sizeinmb >> 10));
+
+    // Register with bcv system.
+    add_bcv_hd(driveid, model);
 
     return 0;
 }
@@ -919,3 +879,62 @@
 
     enable_hwirq(14, entry_76);
 }
+
+
+/****************************************************************
+ * Drive mapping
+ ****************************************************************/
+
+// Fill in Fixed Disk Parameter Table (located in ebda).
+static void
+fill_fdpt(int driveid)
+{
+    if (driveid > 1)
+        return;
+
+    u16 nlc   = GET_GLOBAL(ATA.devices[driveid].lchs.cylinders);
+    u16 nlh   = GET_GLOBAL(ATA.devices[driveid].lchs.heads);
+    u16 nlspt = GET_GLOBAL(ATA.devices[driveid].lchs.spt);
+
+    u16 npc   = GET_GLOBAL(ATA.devices[driveid].pchs.cylinders);
+    u16 nph   = GET_GLOBAL(ATA.devices[driveid].pchs.heads);
+    u16 npspt = GET_GLOBAL(ATA.devices[driveid].pchs.spt);
+
+    struct fdpt_s *fdpt = &get_ebda_ptr()->fdpt[driveid];
+    fdpt->precompensation = 0xffff;
+    fdpt->drive_control_byte = 0xc0 | ((nph > 8) << 3);
+    fdpt->landing_zone = npc;
+    fdpt->cylinders = nlc;
+    fdpt->heads = nlh;
+    fdpt->sectors = nlspt;
+
+    if (nlc == npc && nlh == nph && nlspt == npspt)
+        // no logical CHS mapping used, just physical CHS
+        // use Standard Fixed Disk Parameter Table (FDPT)
+        return;
+
+    // complies with Phoenix style Translated Fixed Disk Parameter
+    // Table (FDPT)
+    fdpt->phys_cylinders = npc;
+    fdpt->phys_heads = nph;
+    fdpt->phys_sectors = npspt;
+    fdpt->a0h_signature = 0xa0;
+
+    // Checksum structure.
+    u8 sum = checksum((u8*)fdpt, sizeof(*fdpt)-1);
+    fdpt->checksum = -sum;
+}
+
+// Map a drive (that was registered via add_bcv_hd)
+void
+map_drive(int driveid)
+{
+    // fill hdidmap
+    u8 hdcount = GET_BDA(hdcount);
+    dprintf(1, "Mapping driveid %d to %d\n", driveid, hdcount);
+    SET_GLOBAL(ATA.idmap[0][hdcount], driveid);
+    SET_BDA(hdcount, hdcount + 1);
+
+    // Fill "fdpt" structure.
+    fill_fdpt(hdcount);
+}
diff --git a/src/boot.c b/src/boot.c
index fc81ed6..80e74ca 100644
--- a/src/boot.c
+++ b/src/boot.c
@@ -17,7 +17,7 @@
 
 
 /****************************************************************
- * IPL handlers
+ * IPL and BCV handlers
  ****************************************************************/
 
 void
@@ -30,7 +30,7 @@
     memset(&IPL, 0, sizeof(IPL));
 
     // Floppy drive
-    struct ipl_entry_s *ie = &IPL.table[0];
+    struct ipl_entry_s *ie = &IPL.bev[0];
     ie->type = IPL_TYPE_FLOPPY;
     ie->description = "Floppy";
     ie++;
@@ -47,7 +47,8 @@
         ie++;
     }
 
-    IPL.count = ie - IPL.table;
+    IPL.bevcount = ie - IPL.bev;
+    IPL.bcv_override = -1;
     SET_EBDA(boot_sequence, 0xffff);
     if (CONFIG_COREBOOT) {
         // XXX - hardcode defaults for coreboot.
@@ -66,30 +67,108 @@
 void
 add_bev(u16 seg, u16 bev, u16 desc)
 {
-    // Found a device that thinks it can boot the system.  Record
-    // its BEV and product name string.
-
     if (! CONFIG_BOOT)
         return;
-
-    if (IPL.count >= ARRAY_SIZE(IPL.table))
+    if (IPL.bevcount >= ARRAY_SIZE(IPL.bev))
         return;
 
-    struct ipl_entry_s *ie = &IPL.table[IPL.count];
+    struct ipl_entry_s *ie = &IPL.bev[IPL.bevcount++];
     ie->type = IPL_TYPE_BEV;
     ie->vector = (seg << 16) | bev;
+    const char *d = "Unknown";
     if (desc)
-        ie->description = MAKE_FLATPTR(seg, desc);
+        d = MAKE_FLATPTR(seg, desc);
+    ie->description = d;
+}
 
-    IPL.count++;
+// Add a bcv entry for an expansion card harddrive or legacy option rom
+void
+add_bcv(u16 seg, u16 ip, u16 desc)
+{
+    if (! CONFIG_BOOT)
+        return;
+    if (IPL.bcvcount >= ARRAY_SIZE(IPL.bcv))
+        return;
+
+    struct ipl_entry_s *ie = &IPL.bcv[IPL.bcvcount++];
+    ie->type = IPL_TYPE_BEV;
+    ie->vector = (seg << 16) | ip;
+    const char *d = "Legacy option rom";
+    if (desc)
+        d = MAKE_FLATPTR(seg, desc);
+    ie->description = d;
+}
+
+// Add a bcv entry for an ata harddrive
+void
+add_bcv_hd(int driveid, const char *desc)
+{
+    if (! CONFIG_BOOT)
+        return;
+    if (IPL.bcvcount >= ARRAY_SIZE(IPL.bcv))
+        return;
+
+    struct ipl_entry_s *ie = &IPL.bcv[IPL.bcvcount++];
+    ie->type = IPL_TYPE_HARDDISK;
+    ie->vector = driveid;
+    ie->description = desc;
 }
 
 
 /****************************************************************
- * Boot menu
+ * Boot menu and BCV execution
  ****************************************************************/
 
-void
+// Show a generic menu item
+static int
+menu_show_default(struct ipl_entry_s *ie, int menupos)
+{
+    char desc[33];
+    printf("%d. %s\n", menupos
+           , strtcpy(desc, ie->description, ARRAY_SIZE(desc)));
+    return 1;
+}
+
+// Show floppy menu item - but only if there exists a floppy drive.
+static int
+menu_show_floppy(struct ipl_entry_s *ie, int menupos)
+{
+    if (!FloppyCount)
+        return 0;
+    return menu_show_default(ie, menupos);
+}
+
+// Show menu items from BCV list.
+static int
+menu_show_harddisk(struct ipl_entry_s *ie, int menupos)
+{
+    int i;
+    for (i = 0; i < IPL.bcvcount; i++) {
+        struct ipl_entry_s *ie = &IPL.bcv[i];
+        switch (ie->type) {
+        case IPL_TYPE_HARDDISK:
+            printf("%d. ata%d-%d %s\n", menupos + i
+                   , ie->vector / 2, ie->vector %2, ie->description);
+            break;
+        default:
+            menu_show_default(ie, menupos+i);
+            break;
+        }
+    }
+    return IPL.bcvcount;
+}
+
+// Show cdrom menu item - but only if there exists a cdrom drive.
+static int
+menu_show_cdrom(struct ipl_entry_s *ie, int menupos)
+{
+    if (!ATA.cdcount)
+        return 0;
+    return menu_show_default(ie, menupos);
+}
+
+// Show IPL option menu.
+static void
 interactive_bootmenu()
 {
     if (! CONFIG_BOOTMENU)
@@ -110,13 +189,28 @@
 
     printf("Select boot device:\n\n");
 
-    int count = IPL.count;
+    int subcount[ARRAY_SIZE(IPL.bev)];
+    int menupos = 1;
     int i;
-    for (i = 0; i < count; i++) {
-        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 (i = 0; i < IPL.bevcount; i++) {
+        struct ipl_entry_s *ie = &IPL.bev[i];
+        int sc = 1;
+        switch (ie->type) {
+        case IPL_TYPE_FLOPPY:
+            sc = menu_show_floppy(ie, menupos);
+            break;
+        case IPL_TYPE_HARDDISK:
+            sc = menu_show_harddisk(ie, menupos);
+            break;
+        case IPL_TYPE_CDROM:
+            sc = menu_show_cdrom(ie, menupos);
+            break;
+        default:
+            sc = menu_show_default(ie, menupos);
+            break;
+        }
+        subcount[i] = sc;
+        menupos += sc;
     }
 
     for (;;) {
@@ -124,22 +218,68 @@
         if (scan_code == 0x01)
             // ESC
             break;
-        if (scan_code >= 0 && scan_code <= count + 1) {
-            // Add user choice to the boot order.
-            u16 choice = scan_code - 1;
-            u32 bootorder = IPL.bootorder;
-            IPL.bootorder = (bootorder << 4) | choice;
-            break;
+        if (scan_code < 1 || scan_code > menupos)
+            continue;
+        int choice = scan_code - 1;
+
+        // Find out which IPL this was for.
+        int bev = 0;
+        while (choice > subcount[bev]) {
+            choice -= subcount[bev];
+            bev++;
         }
+
+        // A harddrive request enables a BCV order.
+        if (IPL.bev[bev].type == IPL_TYPE_HARDDISK)
+            IPL.bcv_override = choice-1;
+
+        // Add user choice to the boot order.
+        IPL.bootorder = (IPL.bootorder << 4) | (bev+1);
+        break;
     }
     printf("\n");
 }
 
+// Run the specified bcv.
+static void
+run_bcv(struct ipl_entry_s *ie)
+{
+    switch (ie->type) {
+    case IPL_TYPE_HARDDISK:
+        map_drive(ie->vector);
+        break;
+    case IPL_TYPE_BEV:
+        call_bcv(ie->vector >> 16, ie->vector & 0xffff);
+        break;
+    }
+}
+
+// Prepare for boot - show menu and run bcvs.
+void
+boot_prep()
+{
+    if (! CONFIG_BOOT)
+        return;
+
+    // Allow user to modify BCV/IPL order.
+    interactive_bootmenu();
+
+    // Run BCVs
+    int override = IPL.bcv_override;
+    if (override >= 0)
+        run_bcv(&IPL.bcv[override]);
+    int i;
+    for (i=0; i<IPL.bcvcount; i++)
+        if (i != override)
+            run_bcv(&IPL.bcv[i]);
+}
+
 
 /****************************************************************
  * Boot code (int 18/19)
  ****************************************************************/
 
+// Jump to a bootup entry point.
 static void
 call_boot_entry(u16 bootseg, u16 bootip, u8 bootdrv)
 {
@@ -229,14 +369,14 @@
     /* Translate bootdev to an IPL table offset by subtracting 1 */
     bootdev -= 1;
 
-    if (bootdev >= IPL.count) {
+    if (bootdev >= IPL.bevcount) {
         dprintf(1, "Invalid boot device (0x%x)\n", bootdev);
         goto fail;
     }
 
     /* Do the loading, and set up vector as a far pointer to the boot
      * address, and bootdrv as the boot drive */
-    struct ipl_entry_s *ie = &IPL.table[bootdev];
+    struct ipl_entry_s *ie = &IPL.bev[bootdev];
     char desc[33];
     printf("Booting from %s...\n"
            , strtcpy(desc, ie->description, ARRAY_SIZE(desc)));
diff --git a/src/boot.h b/src/boot.h
index d6cddcb..a63e09b 100644
--- a/src/boot.h
+++ b/src/boot.h
@@ -11,14 +11,16 @@
     u16 type;
     u16 flags;
     u32 vector;
-    char *description;
+    const char *description;
 };
 
 struct ipl_s {
-    struct ipl_entry_s table[8];
-    u16 count;
+    struct ipl_entry_s bev[8];
+    struct ipl_entry_s bcv[8];
+    int bevcount, bcvcount;
+    int bcv_override;
     u32 bootorder;
-    u8 checkfloppysig;
+    int checkfloppysig;
 };
 
 #define IPL_TYPE_FLOPPY      0x01
@@ -35,6 +37,8 @@
 extern struct ipl_s IPL;
 void boot_setup();
 void add_bev(u16 seg, u16 bev, u16 desc);
-void interactive_bootmenu();
+void add_bcv(u16 seg, u16 ip, u16 desc);
+void add_bcv_hd(int driveid, const char *desc);
+void boot_prep();
 
 #endif // __BOOT_H
diff --git a/src/disk.h b/src/disk.h
index 9a4bf37..a857497 100644
--- a/src/disk.h
+++ b/src/disk.h
@@ -177,6 +177,8 @@
     u8  mode;         // transfer mode : PIO 16/32 bits - IRQ - ISADMA - PCIDMA
     u16 blksize;      // block size
 
+    char model[41];
+
     u8  translation;  // type of translation
     struct chs_s  lchs;         // Logical CHS
     struct chs_s  pchs;         // Physical CHS
@@ -210,8 +212,10 @@
                    , u32 length, void *buf_fl);
 void ata_reset(int driveid);
 void hard_drive_setup();
+void map_drive(int driveid);
 
 // floppy.c
+extern u8 FloppyCount;
 extern struct floppy_ext_dbt_s diskette_param_table2;
 void floppy_drive_setup();
 void floppy_13(struct bregs *regs, u8 drive);
diff --git a/src/optionroms.c b/src/optionroms.c
index d9c4e0e..14d84d2 100644
--- a/src/optionroms.c
+++ b/src/optionroms.c
@@ -100,6 +100,13 @@
     debug_serial_setup();
 }
 
+// Execute a BCV option rom registered via add_bcv().
+void
+call_bcv(u16 seg, u16 ip)
+{
+    callrom(MAKE_FLATPTR(seg, 0), ip, 0);
+}
+
 // Verify that an option rom looks valid
 static int
 is_valid_rom(struct rom_header *rom)
@@ -318,8 +325,8 @@
         pos += ALIGN(rom->size * 512, OPTION_ROM_ALIGN);
         struct pnp_data *pnp = get_pnp_rom(rom);
         if (! pnp) {
-            // Legacy rom - run init vector now.
-            callrom(rom, OPTION_ROM_INITVECTOR, 0);
+            // Legacy rom.
+            add_bcv(FLATPTR_TO_SEG(rom), OPTION_ROM_INITVECTOR, 0);
             continue;
         }
         // PnP rom.
@@ -329,8 +336,7 @@
         else
             // Check for BCV (there may be multiple).
             while (pnp && pnp->bcv) {
-                // Has BCV - run it now.
-                callrom(rom, pnp->bcv, 0);
+                add_bcv(FLATPTR_TO_SEG(rom), pnp->bcv, pnp->productname);
                 pnp = get_pnp_next(rom, pnp);
             }
     }
diff --git a/src/post.c b/src/post.c
index 5985a57..4d86b92 100644
--- a/src/post.c
+++ b/src/post.c
@@ -203,8 +203,8 @@
     // Perform main setup code.
     post();
 
-    // Present the user with a bootup menu.
-    interactive_bootmenu();
+    // Run BCVs
+    boot_prep();
 
     // Setup bios checksum.
     BiosChecksum = -checksum((u8*)BUILD_BIOS_ADDR, BUILD_BIOS_SIZE - 1);
diff --git a/src/util.h b/src/util.h
index b7fbf2e..82560fc 100644
--- a/src/util.h
+++ b/src/util.h
@@ -171,6 +171,7 @@
 void handle_155f();
 
 // optionroms.c
+void call_bcv(u16 seg, u16 ip);
 void vga_setup();
 void optionrom_setup();