Show
Ignore:
Timestamp:
08/24/11 22:37:28 (9 months ago)
Author:
H. Peter Anvin <hpa@…>
Children:
dadc0999025959b1bb99846cf576ca8e10a15c72
Parents:
c210e571f61eeb898fadbb6f47d4a2c82e5bfbfd
git-author:
Matthew Garrett <mjg59@srcf.ucam.org> / 2011-08-11T19:58:09Z+0100
git-committer:
H. Peter Anvin <hpa@linux.intel.com> / 2011-08-24T15:37:28Z-0700
Message:

isohybrid: Generate GPT and Mac bootable images

EFI systems typically don't support booting off ISO 9660 filesystems,
even if written to USB sticks. This patch adds support for generating a
GPT that covers the stick as well, with an additional partition entry
pointing purely at the secondary El Torito image. When burned to CD the
secondary El Torito will be used as an EFI boot image, and when written
to a USB stick the GPT partition will be found and may be booted from.

However, some earlier EFI Macs don't support booting from El Torito
images via EFI. To cater for them this also supports generating an Apple
partition table, allowing a third El Torito image in HFS+ format to be
made available to the firmware. This requires padding the MBR images
slightly in order to leave space for the Apple header, but should have
no functional impact.

Sadly, this breaks the workaround for Acer BIOSes (magic xor
instruction) when Mac support is enabled via -m... not much that can
be done about that.

Signed-off-by: Matthew Garrett <mjg@…>
Signed-off-by: H. Peter Anvin <hpa@…>

Location:
utils
Files:
2 modified

Legend:

Unmodified
Added
Removed
  • utils/Makefile

    r261317 r2c3a24  
    5252 
    5353isohybrid: isohybrid.o isohdpfx.o 
    54         $(CC) $(LDFLAGS) -o $@ $^ 
     54        $(CC) $(LDFLAGS) -luuid -o $@ $^ 
    5555 
    5656gethostip: gethostip.o 
  • utils/isohybrid.c

    r79363f r2c3a24  
    3737#include <sys/stat.h> 
    3838#include <inttypes.h> 
     39#include <uuid/uuid.h> 
    3940 
    4041#include "isohybrid.h" 
     
    4243char *prog = NULL; 
    4344extern int opterr, optind; 
     45struct stat isostat; 
     46unsigned int padding = 0; 
     47 
     48uuid_t disk_uuid, part_uuid, iso_uuid; 
    4449 
    4550uint8_t mode = 0; 
    46 enum { VERBOSE = 1 }; 
     51enum { VERBOSE = 1 , EFI = 2 , MAC = 4}; 
    4752 
    4853/* user options */ 
     
    6267uint32_t c = 0, cc = 0, cs = 0; 
    6368 
     69uint32_t psize = 0, isosize = 0; 
     70 
    6471/* boot catalogue parameters */ 
    6572uint32_t de_lba = 0; 
    6673uint16_t de_seg = 0, de_count = 0, de_mbz2 = 0; 
    6774uint8_t de_boot = 0, de_media = 0, de_sys = 0, de_mbz1 = 0; 
     75uint32_t efi_lba = 0, mac_lba = 0; 
     76uint16_t efi_count = 0, mac_count = 0; 
     77uint8_t efi_boot = 0, efi_media = 0, efi_sys = 0; 
     78 
     79int apm_parts = 3; 
     80 
     81uint8_t afp_header[] = { 0x45, 0x52, 0x08, 0x00, 0x00, 0x00, 0x90, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 
     82 
     83uuid_t efi_system_partition = {0xC1, 0x2A, 0x73, 0x28, 0xF8, 0x1F, 0x11, 0xD2, 0xBA, 0x4B, 0x00, 0xA0, 0xC9, 0x3E, 0xC9, 0x3B}; 
     84uuid_t basic_partition = {0xEB,0xD0,0xA0,0xA2,0xB9,0xE5,0x44,0x33,0x87,0xC0,0x68,0xB6,0xB7,0x26,0x99,0xC7}; 
     85uuid_t hfs_partition = {0x48, 0x46, 0x53, 0x00, 0x00, 0x00, 0x11, 0xAA, 0xAA, 0x11, 0x00, 0x30, 0x65, 0x43, 0xEC, 0xAC}; 
     86 
     87uint32_t crc_tab[256] = 
     88{ 
     89    0, 0x77073096, 0xEE0E612C, 0x990951BA, 
     90    0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 
     91    0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 
     92    0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 
     93    0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 
     94    0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 
     95    0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 
     96    0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 
     97    0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 
     98    0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 
     99    0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 
     100    0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 
     101    0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 
     102    0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, 
     103    0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 
     104    0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 
     105    0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 
     106    0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, 
     107    0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 
     108    0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 
     109    0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 
     110    0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 
     111    0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 
     112    0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 
     113    0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 
     114    0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 
     115    0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 
     116    0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 
     117    0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 
     118    0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, 
     119    0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 
     120    0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, 
     121    0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 
     122    0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 
     123    0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 
     124    0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 
     125    0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 
     126    0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 
     127    0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 
     128    0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 
     129    0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 
     130    0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 
     131    0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 
     132    0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 
     133    0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 
     134    0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 
     135    0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 
     136    0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 
     137    0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 
     138    0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 
     139    0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 
     140    0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 
     141    0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 
     142    0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 
     143    0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 
     144    0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 
     145    0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 
     146    0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 
     147    0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 
     148    0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 
     149    0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 
     150    0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 
     151    0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 
     152    0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D 
     153}; 
     154 
     155struct iso_primary_descriptor { 
     156    uint8_t ignore [80]; 
     157    uint32_t size; 
     158    uint8_t ignore2 [44]; 
     159    uint16_t block_size; 
     160}; 
     161 
     162struct gpt_header { 
     163    uint64_t signature; 
     164    uint32_t revision; 
     165    uint32_t headerSize; 
     166    uint32_t headerCRC; 
     167    uint32_t reserved; 
     168    uint64_t currentLBA; 
     169    uint64_t backupLBA; 
     170    uint64_t firstUsableLBA; 
     171    uint64_t lastUsableLBA; 
     172    uuid_t diskGUID; 
     173    uint64_t partitionEntriesLBA; 
     174    uint32_t numParts; 
     175    uint32_t sizeOfPartitionEntries; 
     176    uint32_t partitionEntriesCRC; 
     177    uint8_t reserved2[420]; 
     178}; 
     179 
     180struct gpt_part_header { 
     181    uuid_t partTypeGUID; 
     182    uuid_t partGUID; 
     183    uint64_t firstLBA; 
     184    uint64_t lastLBA; 
     185    uint64_t attributes; 
     186    uint16_t name[36]; 
     187}; 
     188 
     189#define APM_OFFSET 2048 
     190 
     191struct apple_part_header { 
     192    uint16_t        signature;      /* expected to be MAC_PARTITION_MAGIC */ 
     193    uint16_t        res1; 
     194    uint32_t        map_count;      /* # blocks in partition map */ 
     195    uint32_t        start_block;    /* absolute starting block # of partition */ 
     196    uint32_t        block_count;    /* number of blocks in partition */ 
     197    char            name[32];       /* partition name */ 
     198    char            type[32];       /* string type description */ 
     199    uint32_t        data_start;     /* rel block # of first data block */ 
     200    uint32_t        data_count;     /* number of data blocks */ 
     201    uint32_t        status;         /* partition status bits */ 
     202    uint32_t        boot_start; 
     203    uint32_t        boot_count; 
     204    uint32_t        boot_load; 
     205    uint32_t        boot_load2; 
     206    uint32_t        boot_entry; 
     207    uint32_t        boot_entry2; 
     208    uint32_t        boot_cksum; 
     209    char            processor[16];  /* Contains 680x0, x=0,2,3,4; or empty */ 
     210    uint32_t        driver_sig; 
     211    char            _padding[372]; 
     212}; 
    68213 
    69214 
     
    90235    printf(FMT, "   -t --type", "Specify partition type (default 0x17)"); 
    91236    printf(FMT, "   -i --id", "Specify MBR ID (default random)"); 
     237    printf(FMT, "   -u --uefi", "Build EFI bootable image"); 
     238    printf(FMT, "   -m --mac", "Add AFP table support"); 
    92239 
    93240    printf("\n"); 
     
    123270        { "ctrlhd0", no_argument, NULL, 'c' }, 
    124271        { "partok", no_argument, NULL, 'p'}, 
     272        { "uefi", no_argument, NULL, 'u'}, 
     273        { "mac", no_argument, NULL, 'm'}, 
    125274 
    126275        { "help", no_argument, NULL, '?' }, 
     
    184333            break; 
    185334 
     335        case 'u': 
     336            mode |= EFI; 
     337            break; 
     338 
     339        case 'm': 
     340            mode |= MAC; 
     341            break; 
     342 
    186343        case 'v': 
    187344            mode |= VERBOSE; 
     
    208365} 
    209366 
     367uint16_t 
     368bendian_short(const uint16_t s) 
     369{ 
     370    uint16_t r = 1; 
     371 
     372    if (!*(uint8_t *)&r) 
     373        return s; 
     374 
     375    r = (s & 0x00FF) << 8 | (s & 0xFF00) >> 8; 
     376 
     377    return r; 
     378} 
     379 
     380 
     381uint32_t 
     382bendian_int(const uint32_t s) 
     383{ 
     384    uint32_t r = 1; 
     385 
     386    if (!*(uint8_t *)&r) 
     387        return s; 
     388 
     389    r = (s & 0x000000FF) << 24 | (s & 0xFF000000) >> 24 
     390        | (s & 0x0000FF00) << 8 | (s & 0x00FF0000) >> 8; 
     391 
     392    return r; 
     393} 
    210394 
    211395uint16_t 
     
    235419 
    236420    return r; 
     421} 
     422 
     423uint64_t 
     424lendian_64(const uint64_t s) 
     425{ 
     426        uint64_t r = 1; 
     427 
     428        if (*(uint8_t *)&r) 
     429                return s; 
     430 
     431        r = (s & 0x00000000000000FF) << 56 | (s & 0xFF00000000000000) >> 56 
     432             | (s & 0x000000000000FF00) << 40 | (s & 0x00FF000000000000) >> 40 
     433             | (s & 0x0000000000FF0000) << 24 | (s & 0x0000FF0000000000) >> 24 
     434             | (s & 0x00000000FF000000) << 8 | (s & 0x000000FF00000000) >> 8; 
     435 
     436        return r; 
    237437} 
    238438 
     
    310510        || (de_seg != 0 && de_seg != 0x7C0) || de_count != 4) 
    311511        return 1; 
     512 
     513    return 0; 
     514} 
     515 
     516 
     517int 
     518read_efi_section(const uint8_t *buf) 
     519{ 
     520        unsigned char header_indicator; 
     521        unsigned char platform_id; 
     522        short count; 
     523 
     524        memcpy(&header_indicator, buf++, 1); 
     525        memcpy(&platform_id, buf++, 1); 
     526 
     527        memcpy(&count, buf, 2); 
     528        count = lendian_short(count); 
     529        buf += 2; 
     530 
     531        if (platform_id == 0xef) 
     532                return 0; 
     533 
     534        return 1; 
     535} 
     536 
     537int 
     538read_efi_catalogue(const uint8_t *buf, uint16_t *count, uint32_t *lba) 
     539{ 
     540    buf += 6; 
     541 
     542    memcpy(count, buf, 2); 
     543    *count = lendian_short(*count); 
     544    buf += 2; 
     545 
     546    memcpy(lba, buf, 4); 
     547    *lba = lendian_int(*lba); 
     548    buf += 6; 
    312549 
    313550    return 0; 
     
    328565} 
    329566 
    330  
    331567int 
    332568initialise_mbr(uint8_t *mbr) 
    333569{ 
    334570    int i = 0; 
    335     uint32_t psize = 0, tmp = 0; 
     571    uint32_t tmp = 0; 
    336572    uint8_t ptype = 0, *rbm = mbr; 
    337573    uint8_t bhead = 0, bsect = 0, bcyle = 0; 
     
    341577 
    342578    memcpy(mbr, &isohdpfx[hd0 + 3 * partok], MBRSIZE); 
     579 
     580    if (mode & MAC) { 
     581        memcpy(mbr, afp_header, sizeof(afp_header)); 
     582    } 
     583 
    343584    mbr += MBRSIZE;                                 /* offset 432 */ 
    344585 
     
    402643} 
    403644 
    404  
    405645void 
    406646display_mbr(const uint8_t *mbr, size_t len) 
     
    432672 
    433673 
     674uint32_t chksum_crc32 (unsigned char *block, unsigned int length) 
     675{ 
     676        register unsigned long crc; 
     677        unsigned long i; 
     678 
     679        crc = 0xFFFFFFFF; 
     680        for (i = 0; i < length; i++) 
     681        { 
     682                crc = ((crc >> 8) & 0x00FFFFFF) ^ crc_tab[(crc ^ *block++) & 0xFF]; 
     683        } 
     684        return (crc ^ 0xFFFFFFFF); 
     685} 
     686 
     687void 
     688reverse_uuid(uuid_t uuid) 
     689{ 
     690        uint8_t t, *p = (uint8_t *)uuid; 
     691 
     692        t = p[0]; p[0] = p[3]; p[3] = t; 
     693        t = p[1]; p[1] = p[2]; p[2] = t; 
     694        t = p[4]; p[4] = p[5]; p[5] = t; 
     695        t = p[6]; p[6] = p[7]; p[7] = t; 
     696} 
     697 
     698void 
     699initialise_gpt(uint8_t *gpt, uint32_t current, uint32_t alternate, int primary) 
     700{ 
     701    struct gpt_header *header = (struct gpt_header *)gpt; 
     702    struct gpt_part_header *part; 
     703    int hole = 0; 
     704    int gptsize = 128 / 4 + 2; 
     705 
     706    if (mac_lba) { 
     707        /* 2048 bytes per partition, plus round to 2048 boundary */ 
     708        hole = (apm_parts * 4) + 2; 
     709    } 
     710 
     711    if (primary) { 
     712        uuid_generate(disk_uuid); 
     713        reverse_uuid(disk_uuid); 
     714    } 
     715 
     716    header->signature = lendian_64(0x5452415020494645); 
     717    header->revision = lendian_int(0x010000); 
     718    header->headerSize = lendian_int(0x5c); 
     719    header->currentLBA = lendian_64(current); 
     720    header->backupLBA = lendian_64(alternate); 
     721    header->firstUsableLBA = lendian_64(gptsize + hole); 
     722    header->lastUsableLBA = lendian_64((isostat.st_size + padding)/512 - 
     723                                       gptsize); 
     724    if (primary) 
     725        header->partitionEntriesLBA = lendian_64(0x02 + hole); 
     726    else 
     727        header->partitionEntriesLBA = lendian_64(current - (128 / 4)); 
     728    header->numParts = lendian_int(0x80); 
     729    header->sizeOfPartitionEntries = lendian_int(0x80); 
     730    memcpy(header->diskGUID, disk_uuid, sizeof(uuid_t)); 
     731 
     732    if (primary) 
     733        gpt += sizeof(struct gpt_header) + hole * 512; 
     734    else 
     735        gpt -= header->sizeOfPartitionEntries * header->numParts; 
     736 
     737    part = (struct gpt_part_header *)gpt; 
     738    if (primary) { 
     739        uuid_generate(part_uuid); 
     740        uuid_generate(iso_uuid); 
     741        reverse_uuid(part_uuid); 
     742        reverse_uuid(iso_uuid); 
     743    } 
     744 
     745    memcpy(part->partGUID, iso_uuid, sizeof(uuid_t)); 
     746    memcpy(part->partTypeGUID, basic_partition, sizeof(uuid_t)); 
     747    part->firstLBA = lendian_64(0); 
     748    part->lastLBA = lendian_64(psize); 
     749    memcpy(part->name, "ISOHybrid ISO", 28); 
     750 
     751    gpt += sizeof(struct gpt_part_header); 
     752    part++; 
     753 
     754    memcpy(part->partGUID, part_uuid, sizeof(uuid_t)); 
     755    memcpy(part->partTypeGUID, basic_partition, sizeof(uuid_t)); 
     756    part->firstLBA = lendian_64(efi_lba * 4); 
     757    part->lastLBA = lendian_64(part->firstLBA + efi_count - 1); 
     758    memcpy(part->name, "ISOHybrid", 20); 
     759 
     760    gpt += sizeof(struct gpt_part_header); 
     761 
     762    if (mac_lba) { 
     763        gpt += sizeof(struct gpt_part_header); 
     764 
     765        part++; 
     766 
     767        memcpy(part->partGUID, part_uuid, sizeof(uuid_t)); 
     768        memcpy(part->partTypeGUID, hfs_partition, sizeof(uuid_t)); 
     769        part->firstLBA = lendian_64(mac_lba * 4); 
     770        part->lastLBA = lendian_64(part->firstLBA + mac_count - 1); 
     771        memcpy(part->name, "ISOHybrid", 20); 
     772 
     773        part--; 
     774    } 
     775 
     776    part--; 
     777 
     778    header->partitionEntriesCRC = lendian_int (chksum_crc32((uint8_t *)part, 
     779                           header->numParts * header->sizeOfPartitionEntries)); 
     780 
     781    header->headerCRC = lendian_int(chksum_crc32((uint8_t *)header, 
     782                                                 header->headerSize)); 
     783} 
     784 
     785void 
     786initialise_apm(uint8_t *gpt, uint32_t start) 
     787{ 
     788    struct apple_part_header *part = (struct apple_part_header *)gpt; 
     789 
     790    part->signature = bendian_short(0x504d); 
     791    part->map_count = bendian_int(apm_parts); 
     792    part->start_block = bendian_int(1); 
     793    part->block_count = bendian_int(0x10); 
     794    strcpy(part->name, "Apple"); 
     795    strcpy(part->type, "Apple_partition_map"); 
     796    part->data_start = bendian_int(0); 
     797    part->data_count = bendian_int(10); 
     798    part->status = bendian_int(0x03); 
     799 
     800    part = (struct apple_part_header *)(gpt + 2048); 
     801 
     802    part->signature = bendian_short(0x504d); 
     803    part->map_count = bendian_int(3); 
     804    part->start_block = bendian_int(efi_lba); 
     805    part->block_count = bendian_int(efi_count); 
     806    strcpy(part->name, "EFI"); 
     807    strcpy(part->type, "Apple_HFS"); 
     808    part->data_start = bendian_int(0); 
     809    part->data_count = bendian_int(efi_count); 
     810    part->status = bendian_int(0x33); 
     811 
     812    part = (struct apple_part_header *)(gpt + 4096); 
     813 
     814    if (mac_lba) 
     815    { 
     816        part->signature = bendian_short(0x504d); 
     817        part->map_count = bendian_int(3); 
     818        part->start_block = bendian_int(mac_lba); 
     819        part->block_count = bendian_int(mac_count); 
     820        strcpy(part->name, "EFI"); 
     821        strcpy(part->type, "Apple_HFS"); 
     822        part->data_start = bendian_int(0); 
     823        part->data_count = bendian_int(mac_count); 
     824        part->status = bendian_int(0x33); 
     825    } else { 
     826        part->signature = bendian_short(0x504d); 
     827        part->map_count = bendian_int(3); 
     828        part->start_block = bendian_int((start/2048) + 10); 
     829        part->block_count = bendian_int(efi_lba - start/2048 - 10); 
     830        strcpy(part->name, "ISO"); 
     831        strcpy(part->type, "Apple_Free"); 
     832        part->data_start = bendian_int(0); 
     833        part->data_count = bendian_int(efi_lba - start/2048 - 10); 
     834        part->status = bendian_int(0x01); 
     835    } 
     836} 
     837 
    434838int 
    435839main(int argc, char *argv[]) 
     
    437841    int i = 0; 
    438842    FILE *fp = NULL; 
    439     struct stat isostat; 
    440843    uint8_t *buf = NULL, *bufz = NULL; 
    441     int cylsize = 0, frac = 0, padding = 0; 
     844    int cylsize = 0, frac = 0; 
     845    size_t orig_gpt_size, free_space, gpt_size; 
     846    struct iso_primary_descriptor descriptor; 
    442847 
    443848    prog = strcpy(alloca(strlen(argv[0]) + 1), argv[0]); 
     
    451856        return 1; 
    452857    } 
     858 
     859    if ((mode & EFI) && offset) 
     860        errx(1, "%s: --offset is invalid with UEFI images\n", argv[0]); 
     861 
    453862    srand(time(NULL) << (getppid() << getpid())); 
    454863 
    455864    if (!(fp = fopen(argv[0], "r+"))) 
    456865        err(1, "could not open file `%s'", argv[0]); 
     866 
     867    if (fseek(fp, (16 << 11), SEEK_SET)) 
     868        err(1, "%s: seek error - 0", argv[0]); 
     869 
     870    if (fread(&descriptor, sizeof(char), sizeof(descriptor), fp) != sizeof(descriptor)) 
     871        err(1, "%s: read error - 0", argv[0]); 
     872 
    457873    if (fseek(fp, 17 * 2048, SEEK_SET)) 
    458874        err(1, "%s: seek error - 1", argv[0]); 
     
    486902        display_catalogue(); 
    487903 
     904    buf += 32; 
     905 
     906    if (mode & EFI) 
     907    { 
     908        if (!read_efi_section(buf)) { 
     909            buf += 32; 
     910            if (!read_efi_catalogue(buf, &efi_count, &efi_lba) && efi_lba) { 
     911                offset = 1; 
     912                type = 0xee; 
     913            } else { 
     914                errx(1, "%s: invalid efi catalogue", argv[0]); 
     915            } 
     916        } else { 
     917            errx(1, "%s: unable to find efi image", argv[0]); 
     918        } 
     919    } 
     920 
     921    buf += 32; 
     922 
     923    if (mode & MAC) 
     924    { 
     925        if (!read_efi_section(buf)) { 
     926            buf += 32; 
     927            if (!read_efi_catalogue(buf, &mac_count, &mac_lba) && mac_lba) { 
     928                offset = 1; 
     929                type = 0xee; 
     930            } else { 
     931                errx(1, "%s: invalid efi catalogue", argv[0]); 
     932            } 
     933        } else { 
     934            errx(1, "%s: unable to find mac efi image", argv[0]); 
     935        } 
     936    } 
     937 
    488938    if (fseek(fp, (de_lba * 2048 + 0x40), SEEK_SET)) 
    489939        err(1, "%s: seek error - 3", argv[0]); 
     
    502952        err(1, "%s", argv[0]); 
    503953 
     954    isosize = lendian_int(descriptor.size) * lendian_short(descriptor.block_size); 
     955    free_space = isostat.st_size - isosize; 
     956 
    504957    cylsize = head * sector * 512; 
    505958    frac = isostat.st_size % cylsize; 
     
    509962        printf("imgsize: %zu, padding: %d\n", (size_t)isostat.st_size, padding); 
    510963 
    511     cc = c = (isostat.st_size + padding) / cylsize; 
     964    cc = c = ( isostat.st_size + padding) / cylsize; 
    512965    if (c > 1024) 
    513966    { 
     
    5491002        err(1, "%s: write error - 1", argv[0]); 
    5501003 
     1004    if (efi_lba) { 
     1005        reverse_uuid(basic_partition); 
     1006        reverse_uuid(hfs_partition); 
     1007 
     1008        /* 512 byte header, 128 entries of 128 bytes */ 
     1009        orig_gpt_size = gpt_size = 512 + (128 * 128); 
     1010 
     1011        /* Leave space for the APM if necessary */ 
     1012        if (mac_lba) 
     1013            gpt_size += (4 * 2048); 
     1014 
     1015        buf = calloc(gpt_size, sizeof(char)); 
     1016        memset(buf, 0, gpt_size); 
     1017 
     1018        /* 
     1019         * We need to ensure that we have enough space for the secondary GPT. 
     1020         * Unlike the primary, this doesn't need a hole for the APM. We still 
     1021         * want to be 1MB aligned so just bump the padding by a megabyte. 
     1022         */ 
     1023        if (free_space < orig_gpt_size && padding < orig_gpt_size) { 
     1024            padding += 1024 * 1024; 
     1025        } 
     1026 
     1027        /* 
     1028         * Determine the size of the ISO filesystem. This will define the size 
     1029         * of the partition that covers it. 
     1030         */ 
     1031        psize = isosize / 512; 
     1032 
     1033        /* 
     1034         * Primary GPT starts at sector 1, secondary GPT starts at 1 sector 
     1035         * before the end of the image 
     1036         */ 
     1037        initialise_gpt(buf, 1, (isostat.st_size + padding - 1024) / 512, 1); 
     1038 
     1039        if (fseek(fp, 512, SEEK_SET)) 
     1040            err(1, "%s: seek error - 6", argv[0]); 
     1041 
     1042        if (fwrite(buf, sizeof(char), gpt_size, fp) != (size_t)gpt_size) 
     1043            err(1, "%s: write error - 2", argv[0]); 
     1044    } 
     1045 
     1046    if (mac_lba) 
     1047    { 
     1048        /* Apple partition entries filling 2048 bytes each */ 
     1049        int apm_size = apm_parts * 2048; 
     1050 
     1051        buf = realloc(buf, apm_size); 
     1052        memset(buf, 0, apm_size); 
     1053 
     1054        initialise_apm(buf, APM_OFFSET); 
     1055 
     1056        fseek(fp, APM_OFFSET, SEEK_SET); 
     1057        fwrite(buf, sizeof(char), apm_size, fp); 
     1058    } 
     1059 
    5511060    if (padding) 
    5521061    { 
     
    5581067    } 
    5591068 
     1069    if (efi_lba) { 
     1070        buf = realloc(buf, orig_gpt_size); 
     1071        memset(buf, 0, orig_gpt_size); 
     1072 
     1073        buf += orig_gpt_size - sizeof(struct gpt_header); 
     1074 
     1075        initialise_gpt(buf, (isostat.st_size + padding - 1024) / 512, 1, 0); 
     1076 
     1077        /* Shift back far enough to write the 128 GPT entries */ 
     1078        buf -= 128 * sizeof(struct gpt_part_header); 
     1079 
     1080        /* 
     1081         * Seek far enough back that the gpt header is 512 bytes before the 
     1082         * end of the image 
     1083         */ 
     1084 
     1085        if (fseek(fp, (isostat.st_size + padding) - orig_gpt_size - 512, 
     1086                  SEEK_SET)) 
     1087            err(1, "%s: seek error - 8", argv[0]); 
     1088 
     1089        if (fwrite(buf, sizeof(char), orig_gpt_size, fp) != orig_gpt_size) 
     1090            err(1, "%s: write error - 4", argv[0]); 
     1091    } 
     1092 
    5601093    free(buf); 
    5611094    fclose(fp);