File 0005-Fix-gpt-code-in-isohybrid-and-adjust-to-create-a-val.patch of Package syslinux

From 342c931c6dc3e1f94895066698b2ee89c0fd44f6 Mon Sep 17 00:00:00 2001
From: Steffen Winterfeldt <snwint@suse.de>
Date: Mon, 4 Feb 2013 14:29:58 +0100
Subject: [PATCH 05/22] Fix gpt code in isohybrid and adjust to create a valid
 partition table for our new media layout

---
 utils/isohybrid.c | 391 +++++++++++++++++++++++++---------------------
 utils/isohybrid.h |   2 +-
 2 files changed, 211 insertions(+), 182 deletions(-)

diff --git a/utils/isohybrid.c b/utils/isohybrid.c
index a9e38d4d..2d2133e4 100644
--- a/utils/isohybrid.c
+++ b/utils/isohybrid.c
@@ -43,40 +43,42 @@
 
 char *prog = NULL;
 extern int opterr, optind;
-struct stat isostat;
-unsigned int padding = 0;
 
 uuid_t disk_uuid, part_uuid, iso_uuid;
 
 uint8_t mode = 0;
-enum { VERBOSE = 1 , EFI = 2 , MAC = 4};
+enum { VERBOSE = 1 , EFI = 2 , MAC = 4 , MODE_GPT = 8 , MODE_MBR = 0x10 };
+
+/* partition numbers (1 based) */
+int part_data = 0;
+int part_efi = 0;
+int part_mac = 0;
 
 /* user options */
 uint16_t head = 64;             /* 1 <= head <= 256 */
 uint8_t sector = 32;            /* 1 <= sector <= 63  */
 
 uint8_t entry = 0;              /* partition number: 1 <= entry <= 4 */
-uint8_t offset = 0;             /* partition offset: 0 <= offset <= 64 */
+uint32_t offset = 0;            /* partition offset: 0 <= offset <= 0xFFFFFFFF(4294967296) */
 uint16_t type = 0x17;           /* partition type: 0 <= type <= 255 */
 uint32_t id = 0;                /* MBR: 0 <= id <= 0xFFFFFFFF(4294967296) */
 
 uint8_t hd0 = 0;                /* 0 <= hd0 <= 2 */
 uint8_t partok = 0;             /* 0 <= partok <= 1 */
 
-char mbr_template_path[1024] = {0};   /* Path to MBR template */
-
 uint16_t ve[16];
 uint32_t catoffset = 0;
-uint32_t c = 0, cc = 0, cs = 0;
+uint32_t c = 0;
 
-uint32_t psize = 0, isosize = 0;
+off_t iso_size = 0;
+off_t iso_filesize = 0;
 
 /* boot catalogue parameters */
 uint32_t de_lba = 0;
 uint16_t de_seg = 0, de_count = 0, de_mbz2 = 0;
 uint8_t de_boot = 0, de_media = 0, de_sys = 0, de_mbz1 = 0;
 uint32_t efi_lba = 0, mac_lba = 0;
-uint16_t efi_count = 0, mac_count = 0;
+uint32_t efi_count = 0, mac_count = 0;
 uint8_t efi_boot = 0, efi_media = 0, efi_sys = 0;
 
 int apm_parts = 3;
@@ -225,21 +227,22 @@ usage(void)
 void
 printh(void)
 {
-#define FMT "%-20s %s\n"
+#define FMT "%-18s %s\n"
 
     usage();
 
     printf("\n");
     printf("Options:\n");
-    printf(FMT, "   -h <X>", "Number of geometry heads (default 64)");
-    printf(FMT, "   -s <X>", "Number of geometry sectors (default 32)");
+    printf(FMT, "   -h <X>", "Number of default geometry heads");
+    printf(FMT, "   -s <X>", "Number of default geometry sectors");
     printf(FMT, "   -e --entry", "Specify partition entry number (1-4)");
-    printf(FMT, "   -o --offset", "Specify partition offset (default 0)");
+    printf(FMT, "   -o --offset", "Specify partition offset (in 512 byte units, default 0)");
     printf(FMT, "   -t --type", "Specify partition type (default 0x17)");
     printf(FMT, "   -i --id", "Specify MBR ID (default random)");
     printf(FMT, "   -u --uefi", "Build EFI bootable image");
     printf(FMT, "   -m --mac", "Add AFP table support");
-    printf(FMT, "   -b --mbr <PATH>", "Load MBR from PATH");
+    printf(FMT, "   --gpt", "Force GPT");
+    printf(FMT, "   --mbr", "Force MBR");
 
     printf("\n");
     printf(FMT, "   --forcehd0", "Assume we are loaded as disk ID 0");
@@ -262,20 +265,21 @@ check_option(int argc, char *argv[])
     char *err = NULL;
     int n = 0, ind = 0;
 
-    const char optstr[] = ":h:s:e:o:t:i:b:umfcp?vV";
+    const char optstr[] = ":h:s:e:o:t:i:fcp?vV";
     struct option lopt[] = \
     {
         { "entry", required_argument, NULL, 'e' },
         { "offset", required_argument, NULL, 'o' },
         { "type", required_argument, NULL, 't' },
         { "id", required_argument, NULL, 'i' },
+        { "gpt", no_argument, NULL, 1001 },
+        { "mbr", no_argument, NULL, 1002 },
 
         { "forcehd0", no_argument, NULL, 'f' },
         { "ctrlhd0", no_argument, NULL, 'c' },
         { "partok", no_argument, NULL, 'p'},
 	{ "uefi", no_argument, NULL, 'u'},
 	{ "mac", no_argument, NULL, 'm'},
-        { "mbr", required_argument, NULL, 'b' },
 
         { "help", no_argument, NULL, '?' },
         { "verbose", no_argument, NULL, 'v' },
@@ -305,14 +309,12 @@ 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':
             offset = strtoul(optarg, &err, 0);
-            if (*err || offset > 64)
-                errx(1, "invalid offset: `%s', 0 <= offset <= 64", optarg);
+            if (*err)
+                errx(1, "invalid offset: `%s', 0 <= offset <= 0xFFFFFFFF", optarg);
             break;
 
         case 't':
@@ -341,26 +343,24 @@ 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 'b':
-            if (strlen(optarg) >= sizeof(mbr_template_path))
-                errx(1, "--mbr : Path too long");
-            strcpy(mbr_template_path, optarg);
-            break;
-
         case 'v':
             mode |= VERBOSE;
             break;
 
+        case 1001:
+            mode |= MODE_GPT;
+            break;
+
+        case 1002:
+            mode |= MODE_MBR;
+            break;
+
         case 'V':
             printf("%s version %s\n", prog, VERSION);
             exit(0);
@@ -476,7 +476,7 @@ check_banner(const uint8_t *buf)
 int
 check_catalogue(const uint8_t *buf)
 {
-    int i = 0;
+    int i, cs;
 
     for (i = 0, cs = 0; i < 16; i++)
     {
@@ -552,7 +552,7 @@ read_efi_section(const uint8_t *buf)
 }
 
 int
-read_efi_catalogue(const uint8_t *buf, uint16_t *count, uint32_t *lba)
+read_efi_catalogue(const uint8_t *buf, uint32_t *count, uint32_t *lba)
 {
     buf += 6;
 
@@ -582,62 +582,33 @@ display_catalogue(void)
 }
 
 
-void
-read_mbr_template(char *path, uint8_t *mbr)
+uint32_t ofs2chs(uint32_t ofs)
 {
-    FILE *fp;
-    int ret;
-
-    fp = fopen(path, "rb");
-    if (fp == NULL)
-        err(1, "could not open MBR template file `%s'", path);
-    clearerr(fp);
-    ret = fread(mbr, 1, MBRSIZE, fp);
-    if (ferror(fp) || ret != MBRSIZE)
-        err(1, "error while reading MBR template file `%s'", path);
-    fclose(fp);
-}
+  unsigned c, h, s;
 
+  s = (ofs % sector) + 1;
+  h = (ofs / sector) % head;
+  c = ofs / (sector * head);
+  if(c > 1023) c = 1023;
+
+  return ((c & 0xff) << 24) + ((s + ((c >> 8) << 6)) << 16) + (h << 8);
+}
 
 int
 initialise_mbr(uint8_t *mbr)
 {
     int i = 0;
-    uint32_t tmp = 0;
-    uint8_t ptype = 0, *rbm = mbr;
-    uint8_t bhead = 0, bsect = 0, bcyle = 0;
-    uint8_t ehead = 0, esect = 0, ecyle = 0;
+    uint32_t tmp = 0, chs;
+    uint8_t *rbm = mbr;
 
-#ifndef ISOHYBRID_C_STANDALONE
     extern unsigned char isohdpfx[][MBRSIZE];
-#endif
-
-    if (mbr_template_path[0]) {
-        read_mbr_template(mbr_template_path, mbr);
-    } else {
-
-#ifdef ISOHYBRID_C_STANDALONE
-
-        err(1, "This is a standalone binary. You must specify --mbr. E.g with /usr/lib/syslinux/isohdpfx.bin");
-
-#else
-
-        memcpy(mbr, &isohdpfx[hd0 + 3 * partok], MBRSIZE);
 
-#endif /* ! ISOHYBRID_C_STANDALONE */
-
-    }
+    memcpy(mbr, &isohdpfx[hd0 + 3 * partok], MBRSIZE);
 
     if (mode & MAC) {
-	memcpy(mbr, afp_header, sizeof(afp_header));
+        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);
@@ -656,50 +627,66 @@ initialise_mbr(uint8_t *mbr)
     mbr[1] = '\0';
     mbr += 2;                                       /* offset 446 */
 
-    ptype = type;
-    psize = c * head * sector - offset;
+    for (i = 1; i <= 4; i++, mbr += 16)
+    {
+        memset(mbr, 0, 16);
 
-    bhead = (offset / sector) % head;
-    bsect = (offset % sector) + 1;
-    bcyle = offset / (head * sector);
+        if (!(mode & MODE_MBR)) {
+          /* write protective mbr */
+          if(i == 1 && (mode & MODE_GPT)) {
+            chs = ofs2chs(1);
+            mbr[1] = chs >> 8;
+            mbr[2] = chs >> 16;
+            mbr[3] = chs >> 24;
+            mbr[4] = 0xee;
+            chs = ofs2chs(iso_filesize/512 - 1);
+            mbr[5] = chs >> 8;
+            mbr[6] = chs >> 16;
+            mbr[7] = chs >> 24;
+
+            tmp = lendian_int(1);
+            memcpy(&mbr[8], &tmp, sizeof(tmp));
 
-    bsect += (bcyle & 0x300) >> 2;
-    bcyle  &= 0xFF;
+            tmp = lendian_int(iso_filesize/512 - 1);
+            memcpy(&mbr[12], &tmp, sizeof(tmp));
+          }
 
-    ehead = head - 1;
-    esect = sector + (((cc - 1) & 0x300) >> 2);
-    ecyle = (cc - 1) & 0xFF;
+          continue;
+        }
 
-    for (i = 1; i <= 4; i++)
-    {
-        memset(mbr, 0, 16);
-        if (i == entry)
-        {
+        if (i == 1)
             mbr[0] = 0x80;
-            mbr[1] = bhead;
-            mbr[2] = bsect;
-            mbr[3] = bcyle;
-            mbr[4] = ptype;
-            mbr[5] = ehead;
-            mbr[6] = esect;
-            mbr[7] = ecyle;
+
+        if (i == part_data)
+        {
+            chs = ofs2chs(offset);
+            mbr[1] = chs >> 8;
+            mbr[2] = chs >> 16;
+            mbr[3] = chs >> 24;
+            chs = ofs2chs(c * head * sector - 1);
+            mbr[4] = type;
+            mbr[5] = chs >> 8;
+            mbr[6] = chs >> 16;
+            mbr[7] = chs >> 24;
 
             tmp = lendian_int(offset);
             memcpy(&mbr[8], &tmp, sizeof(tmp));
 
-            tmp = lendian_int(psize);
+            tmp = lendian_int(c * head * sector - offset);
             memcpy(&mbr[12], &tmp, sizeof(tmp));
         }
-        if (i == 2 && (mode & EFI))
+
+        if (i == part_efi)
         {
-            mbr[0] = 0x0;
-            mbr[1] = 0xfe;
-            mbr[2] = 0xff;
-            mbr[3] = 0xff;
+            chs = ofs2chs(efi_lba * 4);
+            mbr[1] = chs >> 8;
+            mbr[2] = chs >> 16;
+            mbr[3] = chs >> 24;
+            chs = ofs2chs(efi_lba * 4 + efi_count - 1);
             mbr[4] = 0xef;
-            mbr[5] = 0xfe;
-            mbr[6] = 0xff;
-            mbr[7] = 0xff;
+            mbr[5] = chs >> 8;
+            mbr[6] = chs >> 16;
+            mbr[7] = chs >> 24;
 
             tmp = lendian_int(efi_lba * 4);
             memcpy(&mbr[8], &tmp, sizeof(tmp));
@@ -707,9 +694,9 @@ initialise_mbr(uint8_t *mbr)
             tmp = lendian_int(efi_count);
             memcpy(&mbr[12], &tmp, sizeof(tmp));
         }
-        if (i == 3 && (mode & MAC))
+
+        if (i == part_mac)
         {
-            mbr[0] = 0x0;
             mbr[1] = 0xfe;
             mbr[2] = 0xff;
             mbr[3] = 0xff;
@@ -724,8 +711,8 @@ initialise_mbr(uint8_t *mbr)
             tmp = lendian_int(mac_count);
             memcpy(&mbr[12], &tmp, sizeof(tmp));
         }
-        mbr += 16;
     }
+
     mbr[0] = 0x55;
     mbr[1] = 0xAA;
     mbr += 2;
@@ -808,6 +795,9 @@ initialise_gpt(uint8_t *gpt, uint32_t current, uint32_t alternate, int primary)
     struct gpt_part_header *part;
     int hole = 0;
     int gptsize = 128 / 4 + 2;
+    int i;
+
+    if(!(mode & MODE_GPT)) return;
 
     if (mac_lba) {
 	/* 2048 bytes per partition, plus round to 2048 boundary */
@@ -825,8 +815,7 @@ initialise_gpt(uint8_t *gpt, uint32_t current, uint32_t alternate, int primary)
     header->currentLBA = lendian_64(current);
     header->backupLBA = lendian_64(alternate);
     header->firstUsableLBA = lendian_64(gptsize + hole);
-    header->lastUsableLBA = lendian_64((isostat.st_size + padding)/512 -
-				       gptsize);
+    header->lastUsableLBA = lendian_64(iso_filesize/512 - gptsize);
     if (primary)
 	header->partitionEntriesLBA = lendian_64(0x02 + hole);
     else
@@ -848,40 +837,34 @@ initialise_gpt(uint8_t *gpt, uint32_t current, uint32_t alternate, int primary)
 	reverse_uuid(iso_uuid);
     }
 
-    memcpy(part->partGUID, iso_uuid, sizeof(uuid_t));
-    memcpy(part->partTypeGUID, basic_partition, sizeof(uuid_t));
-    part->firstLBA = lendian_64(0);
-    part->lastLBA = lendian_64(psize - 1);
-    ascii_to_utf16le(part->name, "ISOHybrid ISO");
-
-    gpt += sizeof(struct gpt_part_header);
-    part++;
-
-    memcpy(part->partGUID, part_uuid, sizeof(uuid_t));
-    memcpy(part->partTypeGUID, basic_partition, sizeof(uuid_t));
-    part->firstLBA = lendian_64(efi_lba * 4);
-    part->lastLBA = lendian_64(part->firstLBA + efi_count - 1);
-    ascii_to_utf16le(part->name, "ISOHybrid");
-
-    gpt += sizeof(struct gpt_part_header);
-
-    if (mac_lba) {
-	gpt += sizeof(struct gpt_part_header);
-
-	part++;
+    for(i = 1; i <= 4; i++, part++) {
+        if(i == part_data) {
+            memcpy(part->partGUID, iso_uuid, sizeof(uuid_t));
+            memcpy(part->partTypeGUID, basic_partition, sizeof(uuid_t));
+            part->firstLBA = lendian_64(offset);
+            part->lastLBA = lendian_64(iso_size/512 - 1);
+            ascii_to_utf16le(part->name, "ISOHybrid ISO");
+        }
 
-	memcpy(part->partGUID, part_uuid, sizeof(uuid_t));
-	memcpy(part->partTypeGUID, hfs_partition, sizeof(uuid_t));
-	part->firstLBA = lendian_64(mac_lba * 4);
-	part->lastLBA = lendian_64(part->firstLBA + mac_count - 1);
-	ascii_to_utf16le(part->name, "ISOHybrid");
+        if(i == part_efi) {
+            memcpy(part->partGUID, part_uuid, sizeof(uuid_t));
+            memcpy(part->partTypeGUID, efi_system_partition, sizeof(uuid_t));
+            part->firstLBA = lendian_64(efi_lba * 4);
+            part->lastLBA = lendian_64(part->firstLBA + efi_count - 1);
+            ascii_to_utf16le(part->name, "ISOHybrid");
+        }
 
-	part--;
+        if (i == part_mac) {
+            memcpy(part->partGUID, part_uuid, sizeof(uuid_t));
+            memcpy(part->partTypeGUID, hfs_partition, sizeof(uuid_t));
+            part->firstLBA = lendian_64(mac_lba * 4);
+            part->lastLBA = lendian_64(part->firstLBA + mac_count - 1);
+            ascii_to_utf16le(part->name, "ISOHybrid");
+        }
     }
 
-    part--;
 
-    header->partitionEntriesCRC = lendian_int (chksum_crc32((uint8_t *)part,
+    header->partitionEntriesCRC = lendian_int (chksum_crc32(gpt,
 			   header->numParts * header->sizeOfPartitionEntries));
 
     header->headerCRC = lendian_int(chksum_crc32((uint8_t *)header,
@@ -896,7 +879,7 @@ initialise_apm(uint8_t *gpt, uint32_t start)
     part->signature = bendian_short(0x504d);
     part->map_count = bendian_int(apm_parts);
     part->start_block = bendian_int(1);
-    part->block_count = bendian_int(4);
+    part->block_count = bendian_int(0x10);
     strcpy(part->name, "Apple");
     strcpy(part->type, "Apple_partition_map");
     part->data_start = bendian_int(0);
@@ -908,11 +891,11 @@ initialise_apm(uint8_t *gpt, uint32_t start)
     part->signature = bendian_short(0x504d);
     part->map_count = bendian_int(3);
     part->start_block = bendian_int(efi_lba);
-    part->block_count = bendian_int(efi_count / 4);
+    part->block_count = bendian_int(efi_count);
     strcpy(part->name, "EFI");
     strcpy(part->type, "Apple_HFS");
     part->data_start = bendian_int(0);
-    part->data_count = bendian_int(efi_count / 4);
+    part->data_count = bendian_int(efi_count);
     part->status = bendian_int(0x33);
 
     part = (struct apple_part_header *)(gpt + 4096);
@@ -922,11 +905,11 @@ initialise_apm(uint8_t *gpt, uint32_t start)
 	part->signature = bendian_short(0x504d);
 	part->map_count = bendian_int(3);
 	part->start_block = bendian_int(mac_lba);
-	part->block_count = bendian_int(mac_count / 4);
+	part->block_count = bendian_int(mac_count);
 	strcpy(part->name, "EFI");
 	strcpy(part->type, "Apple_HFS");
 	part->data_start = bendian_int(0);
-	part->data_count = bendian_int(mac_count / 4);
+	part->data_count = bendian_int(mac_count);
 	part->status = bendian_int(0x33);
     } else {
 	part->signature = bendian_short(0x504d);
@@ -948,8 +931,10 @@ main(int argc, char *argv[])
     FILE *fp = NULL;
     uint8_t *buf = NULL, *bufz = NULL;
     int cylsize = 0, frac = 0;
+    unsigned padding = 0;
     size_t orig_gpt_size, free_space, gpt_size;
     struct iso_primary_descriptor descriptor;
+    struct stat isostat;
 
     prog = strcpy(alloca(strlen(argv[0]) + 1), argv[0]);
     i = check_option(argc, argv);
@@ -962,8 +947,19 @@ main(int argc, char *argv[])
         return 1;
     }
 
-    if ((mode & EFI) && offset)
-	errx(1, "%s: --offset is invalid with UEFI images\n", argv[0]);
+    if (!(mode & (MODE_MBR | MODE_GPT))) {
+        mode |= (mode & EFI) ? MODE_GPT : MODE_MBR;
+    }
+
+    if ((mode & EFI) && !offset) type = 0;
+
+    part_data = 1;
+    if(mode & EFI) part_efi = 2;
+    if(mode & MAC) part_mac = 3;
+
+    if(entry) {
+      if(entry != part_efi && entry != part_mac) part_data = entry;
+    }
 
     srand(time(NULL) << (getppid() << getpid()));
 
@@ -1014,7 +1010,23 @@ main(int argc, char *argv[])
 	if (!read_efi_section(buf)) {
 	    buf += 32;
 	    if (!read_efi_catalogue(buf, &efi_count, &efi_lba) && efi_lba) {
-		offset = 0;
+              if(efi_count < 2) {
+                unsigned char bpb[512];
+
+                if (fseeko(fp, ((off_t)efi_lba * 2048), SEEK_SET)) {
+                  err(1, "%s: seek error - 3", argv[0]);
+                }
+
+                if (fread(bpb, 1, sizeof bpb, fp) != sizeof bpb) {
+                  err(1, "%s", argv[0]);
+                }
+
+                if((bpb[511] << 8) + bpb[510] == 0xaa55) {
+                  unsigned s = bpb[19] + (bpb[20] << 8);
+                  if(!s) s = bpb[32] + (bpb[33] << 8) + (bpb[34] << 16) + (bpb[35] << 24);
+                  if(s) efi_count = s;
+                }
+              }
 	    } else {
 		errx(1, "%s: invalid efi catalogue", argv[0]);
 	    }
@@ -1030,7 +1042,6 @@ main(int argc, char *argv[])
 	if (!read_efi_section(buf)) {
 	    buf += 32;
 	    if (!read_efi_catalogue(buf, &mac_count, &mac_lba) && mac_lba) {
-		offset = 0;
 	    } else {
 		errx(1, "%s: invalid efi catalogue", argv[0]);
 	    }
@@ -1052,27 +1063,55 @@ main(int argc, char *argv[])
                  "signature. Note that isolinux-debug.bin does not support " \
                  "hybrid booting", argv[0]);
 
+    if (offset && efi_lba && offset > efi_lba * 4)
+    {
+        part_efi = 1;
+        part_data = 2;
+        if (part_mac)
+        {
+            part_mac = 2;
+            part_data = 3;
+        }
+    }
+
     if (stat(argv[0], &isostat))
         err(1, "%s", argv[0]);
 
-    isosize = lendian_int(descriptor.size) * lendian_short(descriptor.block_size);
-    free_space = isostat.st_size - isosize;
+    iso_size = (off_t) lendian_int(descriptor.size) * lendian_short(descriptor.block_size);
+    free_space = isostat.st_size - iso_size;
 
     cylsize = head * sector * 512;
     frac = isostat.st_size % cylsize;
     padding = (frac > 0) ? cylsize - frac : 0;
 
     if (mode & VERBOSE)
-        printf("imgsize: %zu, padding: %d\n", (size_t)isostat.st_size, padding);
+        printf("imgsize: %zu, padding: %d\n", (size_t)iso_filesize, padding);
 
-    cc = c = ( isostat.st_size + padding) / cylsize;
+    c = (isostat.st_size + padding) / cylsize;
     if (c > 1024)
     {
         warnx("Warning: more than 1024 cylinders: %d", c);
         warnx("Not all BIOSes will be able to boot this device");
-        cc = 1024;
     }
 
+    /* 512 byte header, 128 entries of 128 bytes */
+    orig_gpt_size = gpt_size = 512 + (128 * 128);
+
+    /* Leave space for the APM if necessary */
+    if (mac_lba)
+        gpt_size += (4 * 2048);
+
+    /*
+     * We need to ensure that we have enough space for the secondary GPT.
+     * Unlike the primary, this doesn't need a hole for the APM. We still
+     * want to be 1MB aligned so just bump the padding by a megabyte.
+     */
+    if ((mode & MODE_GPT) && free_space < orig_gpt_size && padding < orig_gpt_size) {
+        padding += 1024 * 1024;
+    }
+
+    iso_filesize = isostat.st_size + padding;
+
     if (!id)
     {
         if (fseeko(fp, (off_t) 440, SEEK_SET))
@@ -1094,6 +1133,16 @@ main(int argc, char *argv[])
 
     buf = bufz;
     memset(buf, 0, BUFSIZE);
+
+    if (fseeko(fp, 0, SEEK_SET))
+        err(1, "%s: seek error - 5", argv[0]);
+
+    /* clean up first 16 blocks */
+    for (i = 0; i < 16; i++) {
+        if (fwrite(buf, sizeof(char), BUFSIZE, fp) != BUFSIZE)
+            err(1, "%s: write error - 1", argv[0]);
+    }
+
     i = initialise_mbr(buf);
 
     if (mode & VERBOSE)
@@ -1105,40 +1154,20 @@ main(int argc, char *argv[])
     if (fwrite(buf, sizeof(char), i, fp) != (size_t)i)
         err(1, "%s: write error - 1", argv[0]);
 
-    if (efi_lba) {
+    if (mode & MODE_GPT) {
+        /* always write primary gpt, if only to cleanup old data */
+	reverse_uuid(efi_system_partition);
 	reverse_uuid(basic_partition);
 	reverse_uuid(hfs_partition);
 
-	/* 512 byte header, 128 entries of 128 bytes */
-	orig_gpt_size = gpt_size = 512 + (128 * 128);
-
-	/* Leave space for the APM if necessary */
-	if (mac_lba)
-	    gpt_size += (4 * 2048);
-
 	buf = calloc(gpt_size, sizeof(char));
 	memset(buf, 0, gpt_size);
 
-	/*
-	 * We need to ensure that we have enough space for the secondary GPT.
-	 * Unlike the primary, this doesn't need a hole for the APM. We still
-	 * want to be 1MB aligned so just bump the padding by a megabyte.
-	 */
-	if (free_space < orig_gpt_size && padding < orig_gpt_size) {
-	    padding += 1024 * 1024;
-	}
-
-	/*
-	 * Determine the size of the ISO filesystem. This will define the size
-	 * of the partition that covers it.
-	 */
-	psize = isosize / 512;
-
 	/*
 	 * Primary GPT starts at sector 1, secondary GPT starts at 1 sector
 	 * before the end of the image
 	 */
-	initialise_gpt(buf, 1, (isostat.st_size + padding - 512) / 512, 1);
+	initialise_gpt(buf, 1, iso_filesize / 512 - 1, 1);
 
 	if (fseeko(fp, (off_t) 512, SEEK_SET))
 	    err(1, "%s: seek error - 6", argv[0]);
@@ -1166,17 +1195,17 @@ main(int argc, char *argv[])
         if (fsync(fileno(fp)))
             err(1, "%s: could not synchronise", argv[0]);
 
-        if (ftruncate(fileno(fp), isostat.st_size + padding))
+        if (ftruncate(fileno(fp), iso_filesize))
             err(1, "%s: could not add padding bytes", argv[0]);
     }
 
-    if (efi_lba) {
+    if (mode & MODE_GPT) {
 	buf = realloc(buf, orig_gpt_size);
 	memset(buf, 0, orig_gpt_size);
 
 	buf += orig_gpt_size - sizeof(struct gpt_header);
 
-	initialise_gpt(buf, (isostat.st_size + padding - 512) / 512, 1, 0);
+	initialise_gpt(buf, iso_filesize / 512 - 1, 1, 0);
 
 	/* Shift back far enough to write the 128 GPT entries */
 	buf -= 128 * sizeof(struct gpt_part_header);
@@ -1186,7 +1215,7 @@ main(int argc, char *argv[])
 	 * end of the image
 	 */
 
-	if (fseeko(fp, (isostat.st_size + padding) - orig_gpt_size, SEEK_SET))
+	if (fseeko(fp, iso_filesize - orig_gpt_size, SEEK_SET))
 	    err(1, "%s: seek error - 8", argv[0]);
 
 	if (fwrite(buf, sizeof(char), orig_gpt_size, fp) != orig_gpt_size)
diff --git a/utils/isohybrid.h b/utils/isohybrid.h
index eecf1caa..157f6e1d 100644
--- a/utils/isohybrid.h
+++ b/utils/isohybrid.h
@@ -20,7 +20,7 @@
  *
  */
 
-#define VERSION     "0.12"
+#define VERSION     "0.12.1"
 #define BUFSIZE     2048
 #define MBRSIZE      432
 
-- 
2.42.0

openSUSE Build Service is sponsored by