Create separate IPL entry for each CD/DVD
authorGleb Natapov <gleb@redhat.com>
Tue, 7 Dec 2010 11:50:54 +0000 (13:50 +0200)
committerKevin O'Connor <kevin@koconnor.net>
Sun, 12 Dec 2010 19:12:59 +0000 (14:12 -0500)
Current code creates only one IPL entry of type IPL_TYPE_CDROM even if
there are more then one CDROM drive present. If CDROM that the entry
refers to is not bootable there is no way to retry boot from another
CDROM. Fix this by creating IPL entry for each CDROM drive found. First
CDROM will always be placed in IPL entry 3 for backwards compatibility.

Signed-off-by: Gleb Natapov <gleb@redhat.com>
src/ata.c
src/block.c
src/boot.c
src/boot.h
src/cdrom.c
src/disk.h

index e5331084e2e0630132871f06fd41c5dabf285b78..d9714800ea933d644b29f6090ec58a0d3f595f07 100644 (file)
--- a/src/ata.c
+++ b/src/ata.c
@@ -782,8 +782,10 @@ init_drive_atapi(struct atadrive_s *dummy, u16 *buffer)
     dprintf(1, "%s\n", adrive_g->drive.desc);
 
     // fill cdidmap
-    if (iscd)
+    if (iscd) {
         map_cd_drive(&adrive_g->drive);
+        add_baid_cdrom(&adrive_g->drive);
+    }
 
     return adrive_g;
 }
index 818c9f9dc3b54c23114f19ca6ece1968a828cfbf..cab503c12d3323dfa26c5d59940b0b1c94d226cf 100644 (file)
@@ -27,6 +27,16 @@ getDrive(u8 exttype, u8 extdriveoffset)
     return GLOBALFLAT2GLOBAL(drive_gf);
 }
 
+int getDriveId(u8 exttype, struct drive_s *drive_g)
+{
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(Drives.idmap[0]); i++)
+        if (getDrive(exttype, i) == drive_g)
+            return i;
+
+    return -1;
+}
 
 /****************************************************************
  * Disk geometry translation
index 021b8ac070170be378c558f8d0f76e436a44ad3a..9c94439605a54579ecaec8e5de8d5b2c1b2136fd 100644 (file)
@@ -87,6 +87,25 @@ add_bev(u16 seg, u16 bev, u16 desc)
     ie->description = d;
 }
 
+// Add a IPL entry for BAID cdrom.
+void
+add_baid_cdrom(struct drive_s *drive_g)
+{
+    if (! CONFIG_CDROM_BOOT)
+        return;
+
+    /* put first cdrom into ipl 3 for compatability with qemu */
+    struct ipl_entry_s *ie = &IPL.bev[2];
+    if (IPL.bevcount >= ARRAY_SIZE(IPL.bev) && ie->vector)
+        return;
+
+    if (ie->vector)
+        ie = &IPL.bev[IPL.bevcount++];
+    ie->type = IPL_TYPE_CDROM;
+    ie->vector = (u32)drive_g;
+    ie->description = "DVD/CD";
+}
+
 // Add a bcv entry for an expansion card harddrive or legacy option rom
 void
 add_bcv(u16 seg, u16 ip, u16 desc)
@@ -188,12 +207,11 @@ menu_show_harddisk(struct ipl_entry_s *ie, int menupos)
 static int
 menu_show_cdrom(struct ipl_entry_s *ie, int menupos)
 {
-    int i;
-    for (i = 0; i < Drives.cdcount; i++) {
-        struct drive_s *drive_g = getDrive(EXTTYPE_CD, i);
-        printf("%d. DVD/CD [%s]\n", menupos + i, drive_g->desc);
-    }
-    return Drives.cdcount;
+    struct drive_s *drive_g = (void*)ie->vector;
+    if (!ie->vector)
+        return 0;
+    printf("%d. DVD/CD [%s]\n", menupos, drive_g->desc);
+    return 1;
 }
 
 // Show coreboot-fs menu item.
@@ -399,9 +417,14 @@ boot_cdrom(struct ipl_entry_s *ie)
 {
     if (! CONFIG_CDROM_BOOT)
         return;
-    int status = cdrom_boot(ie->subchoice);
+
+    if (!ie->vector)
+        return;
+
+    struct drive_s *drive_g = (void*)ie->vector;
+    int status = cdrom_boot(drive_g);
     if (status) {
-        printf("Boot failed: Could not read from CDROM (code %04x)\n", status);
+        printf("Boot failed: Could not read from CDROM %s (code %04x)\n", drive_g->desc, status);
         return;
     }
 
index db046e3571cefaf98ddffc23be54c179a9819ad2..f751d719dd277dac1601adca18407bb361f46cd9 100644 (file)
@@ -43,6 +43,8 @@ void add_bev(u16 seg, u16 bev, u16 desc);
 void add_bcv(u16 seg, u16 ip, u16 desc);
 struct drive_s;
 void add_bcv_internal(struct drive_s *drive_g);
+void add_baid_cdrom(struct drive_s *drive_g);
+
 void boot_prep(void);
 
 #endif // __BOOT_H
index 349e401bbd65346bcc3a3291906df47477f7fcdb..31ceaaaa86fb3ee7f8f5ae4f217a0c54e4b5d9c9 100644 (file)
@@ -241,12 +241,13 @@ atapi_is_ready(struct disk_op_s *op)
 }
 
 int
-cdrom_boot(int cdid)
+cdrom_boot(struct drive_s *drive_g)
 {
     struct disk_op_s dop;
+    int cdid = getDriveId(EXTTYPE_CD, drive_g);
     memset(&dop, 0, sizeof(dop));
-    dop.drive_g = getDrive(EXTTYPE_CD, cdid);
-    if (!dop.drive_g)
+    dop.drive_g = drive_g;
+    if (!dop.drive_g || cdid < 0)
         return 1;
 
     int ret = atapi_is_ready(&dop);
index c1ba6ae44c0ad468fbd4c618865da83e8c661722..a598bb4ffd95a7cfda4fa49f2262c97faf315913 100644 (file)
@@ -229,6 +229,7 @@ struct drives_s {
 // block.c
 extern struct drives_s Drives;
 struct drive_s *getDrive(u8 exttype, u8 extdriveoffset);
+int getDriveId(u8 exttype, struct drive_s *drive_g);
 void setup_translation(struct drive_s *drive_g);
 void map_floppy_drive(struct drive_s *drive_g);
 void map_hd_drive(struct drive_s *drive_g);
@@ -249,7 +250,7 @@ extern struct drive_s *cdemu_drive_gf;
 int process_cdemu_op(struct disk_op_s *op);
 void cdemu_setup(void);
 void cdemu_134b(struct bregs *regs);
-int cdrom_boot(int cdid);
+int cdrom_boot(struct drive_s *drive_g);
 
 // ramdisk.c
 void ramdisk_setup(void);