1e69ac
From: Matthew Garrett <mjg@redhat.com>
25255a
Date:   Wed Feb 15 12:05:29 2012 -0500
1e69ac
Subject: isohybrid: Generate MBR even when in EFI mode
25255a
1e69ac
Various EFI systems insist that there be no active flag in the pMBR in
1e69ac
order to parse the GPT. The only way around this is to also generate a
1e69ac
valid MBR - the firmware will then pick that up and use the system
1e69ac
partition provided there. In order to deal with other EFI "sanity" checks,
1e69ac
the partition type for the non-EFI partitions is set to 0 to skip the
1e69ac
firmware bailing because of overlapping partitions.
25255a
25255a
diff --git a/utils/isohybrid.c b/utils/isohybrid.c
25255a
index 1dcbaa1..ac04bfd 100644
25255a
--- a/utils/isohybrid.c
25255a
+++ b/utils/isohybrid.c
25255a
@@ -54,7 +54,7 @@ enum { VERBOSE = 1 , EFI = 2 , MAC = 4};
25255a
 uint16_t head = 64;             /* 1 <= head <= 256 */
25255a
 uint8_t sector = 32;            /* 1 <= sector <= 63  */
25255a
 
25255a
-uint8_t entry = 1;              /* partition number: 1 <= entry <= 4 */
25255a
+uint8_t entry = 0;              /* partition number: 1 <= entry <= 4 */
25255a
 uint8_t offset = 0;             /* partition offset: 0 <= offset <= 64 */
25255a
 uint16_t type = 0x17;           /* partition type: 0 <= type <= 255 */
25255a
 uint32_t id = 0;                /* MBR: 0 <= id <= 0xFFFFFFFF(4294967296) */
25255a
@@ -300,6 +300,8 @@ check_option(int argc, char *argv[])
25255a
             entry = strtoul(optarg, &err, 0);
25255a
             if (entry < 1 || entry > 4)
25255a
                 errx(1, "invalid entry: `%s', 1 <= entry <= 4", optarg);
25255a
+	    if (mode & MAC || mode & EFI)
25255a
+		errx(1, "setting an entry is unsupported with EFI or Mac");
25255a
             break;
25255a
 
25255a
         case 'o':
25255a
@@ -334,10 +336,14 @@ check_option(int argc, char *argv[])
25255a
 
25255a
 	case 'u':
25255a
 	    mode |= EFI;
25255a
+	    if (entry)
25255a
+		errx(1, "setting an entry is unsupported with EFI or Mac");
25255a
 	    break;
25255a
 
25255a
 	case 'm':
25255a
 	    mode |= MAC;
25255a
+	    if (entry)
25255a
+		errx(1, "setting an entry is unsupported with EFI or Mac");
25255a
 	    break;
25255a
 
25255a
         case 'v':
25255a
@@ -581,6 +587,12 @@ initialise_mbr(uint8_t *mbr)
25255a
 	memcpy(mbr, afp_header, sizeof(afp_header));
25255a
     }
25255a
 
25255a
+    if (!entry)
25255a
+	entry = 1;
25255a
+
25255a
+    if (mode & EFI)
25255a
+	type = 0;
25255a
+
25255a
     mbr += MBRSIZE;                                 /* offset 432 */
25255a
 
25255a
     tmp = lendian_int(de_lba * 4);
25255a
@@ -633,6 +645,40 @@ initialise_mbr(uint8_t *mbr)
25255a
             tmp = lendian_int(psize);
25255a
             memcpy(&mbr[12], &tmp, sizeof(tmp));
25255a
         }
25255a
+        if (i == 2 && (mode & EFI))
25255a
+        {
25255a
+            mbr[0] = 0x0;
25255a
+            mbr[1] = 0xfe;
25255a
+            mbr[2] = 0xff;
25255a
+            mbr[3] = 0xff;
25255a
+            mbr[4] = 0xef;
25255a
+            mbr[5] = 0xfe;
25255a
+            mbr[6] = 0xff;
25255a
+            mbr[7] = 0xff;
25255a
+
25255a
+            tmp = lendian_int(efi_lba * 4);
25255a
+            memcpy(&mbr[8], &tmp, sizeof(tmp));
25255a
+
25255a
+            tmp = lendian_int(efi_count);
25255a
+            memcpy(&mbr[12], &tmp, sizeof(tmp));
25255a
+        }
25255a
+        if (i == 3 && (mode & MAC))
25255a
+        {
25255a
+            mbr[0] = 0x0;
25255a
+            mbr[1] = 0xfe;
25255a
+            mbr[2] = 0xff;
25255a
+            mbr[3] = 0xff;
25255a
+            mbr[4] = 0x0;
25255a
+            mbr[5] = 0xfe;
25255a
+            mbr[6] = 0xff;
25255a
+            mbr[7] = 0xff;
25255a
+
25255a
+            tmp = lendian_int(mac_lba * 4);
25255a
+            memcpy(&mbr[8], &tmp, sizeof(tmp));
25255a
+
25255a
+            tmp = lendian_int(mac_count);
25255a
+            memcpy(&mbr[12], &tmp, sizeof(tmp));
25255a
+        }
25255a
         mbr += 16;
25255a
     }
25255a
     mbr[0] = 0x55;
25255a
@@ -908,8 +954,7 @@ main(int argc, char *argv[])
25255a
 	if (!read_efi_section(buf)) {
25255a
 	    buf += 32;
25255a
 	    if (!read_efi_catalogue(buf, &efi_count, &efi_lba) && efi_lba) {
25255a
-		offset = 1;
25255a
-		type = 0xee;
25255a
+		offset = 0;
25255a
 	    } else {
25255a
 		errx(1, "%s: invalid efi catalogue", argv[0]);
25255a
 	    }
25255a
@@ -925,8 +970,7 @@ main(int argc, char *argv[])
25255a
 	if (!read_efi_section(buf)) {
25255a
 	    buf += 32;
25255a
 	    if (!read_efi_catalogue(buf, &mac_count, &mac_lba) && mac_lba) {
25255a
-		offset = 1;
25255a
-		type = 0xee;
25255a
+		offset = 0;
25255a
 	    } else {
25255a
 		errx(1, "%s: invalid efi catalogue", argv[0]);
25255a
 	    }