Blob Blame History Raw
commit 4816be5c3bf49ae235baa71c512b4a1705a980f8
Author: Matthew Garrett <mjg@redhat.com>
Date:   Wed Feb 15 12:05:29 2012 -0500

    isohybrid: Generate MBR even when in EFI mode
    
    Various EFI systems insist that there be no active flag in the pMBR in
    order to parse the GPT. The only way around this is to also generate a
    valid MBR - the firmware will then pick that up and use the system
    partition provided there. In order to deal with other EFI "sanity" checks,
    the partition type for the non-EFI partitions is set to 0 to skip the
    firmware bailing because of overlapping partitions.

diff --git a/utils/isohybrid.c b/utils/isohybrid.c
index 1dcbaa1..ac04bfd 100644
--- a/utils/isohybrid.c
+++ b/utils/isohybrid.c
@@ -54,7 +54,7 @@ enum { VERBOSE = 1 , EFI = 2 , MAC = 4};
 uint16_t head = 64;             /* 1 <= head <= 256 */
 uint8_t sector = 32;            /* 1 <= sector <= 63  */
 
-uint8_t entry = 1;              /* partition number: 1 <= entry <= 4 */
+uint8_t entry = 0;              /* partition number: 1 <= entry <= 4 */
 uint8_t offset = 0;             /* partition offset: 0 <= offset <= 64 */
 uint16_t type = 0x17;           /* partition type: 0 <= type <= 255 */
 uint32_t id = 0;                /* MBR: 0 <= id <= 0xFFFFFFFF(4294967296) */
@@ -300,6 +300,8 @@ check_option(int argc, char *argv[])
             entry = strtoul(optarg, &err, 0);
             if (entry < 1 || entry > 4)
                 errx(1, "invalid entry: `%s', 1 <= entry <= 4", optarg);
+	    if (mode & MAC || mode & EFI)
+		errx(1, "setting an entry is unsupported with EFI or Mac");
             break;
 
         case 'o':
@@ -334,10 +336,14 @@ check_option(int argc, char *argv[])
 
 	case 'u':
 	    mode |= EFI;
+	    if (entry)
+		errx(1, "setting an entry is unsupported with EFI or Mac");
 	    break;
 
 	case 'm':
 	    mode |= MAC;
+	    if (entry)
+		errx(1, "setting an entry is unsupported with EFI or Mac");
 	    break;
 
         case 'v':
@@ -581,6 +587,12 @@ initialise_mbr(uint8_t *mbr)
 	memcpy(mbr, afp_header, sizeof(afp_header));
     }
 
+    if (!entry)
+	entry = 1;
+
+    if (mode & EFI)
+	type = 0;
+
     mbr += MBRSIZE;                                 /* offset 432 */
 
     tmp = lendian_int(de_lba * 4);
@@ -633,6 +645,40 @@ initialise_mbr(uint8_t *mbr)
             tmp = lendian_int(psize);
             memcpy(&mbr[12], &tmp, sizeof(tmp));
         }
+        if (i == 2 && (mode & EFI))
+        {
+            mbr[0] = 0x0;
+            mbr[1] = 0xfe;
+            mbr[2] = 0xff;
+            mbr[3] = 0xff;
+            mbr[4] = 0xef;
+            mbr[5] = 0xfe;
+            mbr[6] = 0xff;
+            mbr[7] = 0xff;
+
+            tmp = lendian_int(efi_lba * 4);
+            memcpy(&mbr[8], &tmp, sizeof(tmp));
+
+            tmp = lendian_int(efi_count);
+            memcpy(&mbr[12], &tmp, sizeof(tmp));
+        }
+        if (i == 3 && (mode & MAC))
+        {
+            mbr[0] = 0x0;
+            mbr[1] = 0xfe;
+            mbr[2] = 0xff;
+            mbr[3] = 0xff;
+            mbr[4] = 0x0;
+            mbr[5] = 0xfe;
+            mbr[6] = 0xff;
+            mbr[7] = 0xff;
+
+            tmp = lendian_int(mac_lba * 4);
+            memcpy(&mbr[8], &tmp, sizeof(tmp));
+
+            tmp = lendian_int(mac_count);
+            memcpy(&mbr[12], &tmp, sizeof(tmp));
+        }
         mbr += 16;
     }
     mbr[0] = 0x55;
@@ -908,8 +954,7 @@ main(int argc, char *argv[])
 	if (!read_efi_section(buf)) {
 	    buf += 32;
 	    if (!read_efi_catalogue(buf, &efi_count, &efi_lba) && efi_lba) {
-		offset = 1;
-		type = 0xee;
+		offset = 0;
 	    } else {
 		errx(1, "%s: invalid efi catalogue", argv[0]);
 	    }
@@ -925,8 +970,7 @@ main(int argc, char *argv[])
 	if (!read_efi_section(buf)) {
 	    buf += 32;
 	    if (!read_efi_catalogue(buf, &mac_count, &mac_lba) && mac_lba) {
-		offset = 1;
-		type = 0xee;
+		offset = 0;
 	    } else {
 		errx(1, "%s: invalid efi catalogue", argv[0]);
 	    }