2 * isohybrid.c: Post process an ISO 9660 image generated with mkisofs or
3 * genisoimage to allow - hybrid booting - as a CD-ROM or as a hard
6 * This is based on the original Perl script written by H. Peter Anvin. The
7 * rewrite in C is to avoid dependency on Perl on a system under installation.
9 * Copyright (C) 2010 P J P <pj.pandit@yahoo.co.in>
11 * isohybrid is a free software; you can redistribute it and/or modify it
12 * under the terms of GNU General Public License as published by Free Software
13 * Foundation; either version 2 of the license, or (at your option) any later
16 * isohybrid is distributed in the hope that it will be useful, but WITHOUT
17 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
21 * You should have received a copy of the GNU General Public License along
22 * with isohybrid; if not, see: <http://www.gnu.org/licenses>.
26 #define _FILE_OFFSET_BITS 64
40 #ifdef REACTOS_ISOHYBRID_EFI_MAC_SUPPORT
41 #include <uuid/uuid.h>
44 #include "isohybrid.h"
45 #include "reactos_support_code.h"
48 extern int opterr
, optind
;
50 unsigned int padding
= 0;
52 #ifdef REACTOS_ISOHYBRID_EFI_MAC_SUPPORT
53 uuid_t disk_uuid
, part_uuid
, iso_uuid
;
57 enum { VERBOSE
= 1 , EFI
= 2 , MAC
= 4};
60 uint16_t head
= 64; /* 1 <= head <= 256 */
61 uint8_t sector
= 32; /* 1 <= sector <= 63 */
63 uint8_t entry
= 0; /* partition number: 1 <= entry <= 4 */
64 uint8_t offset
= 0; /* partition offset: 0 <= offset <= 64 */
65 uint16_t type
= 0x17; /* partition type: 0 <= type <= 255 */
66 uint32_t id
= 0; /* MBR: 0 <= id <= 0xFFFFFFFF(4294967296) */
68 uint8_t hd0
= 0; /* 0 <= hd0 <= 2 */
69 uint8_t partok
= 0; /* 0 <= partok <= 1 */
71 char mbr_template_path
[1024] = {0}; /* Path to MBR template */
74 uint32_t catoffset
= 0;
75 uint32_t c
= 0, cc
= 0, cs
= 0;
77 uint32_t psize
= 0, isosize
= 0;
79 /* boot catalogue parameters */
81 uint16_t de_seg
= 0, de_count
= 0, de_mbz2
= 0;
82 uint8_t de_boot
= 0, de_media
= 0, de_sys
= 0, de_mbz1
= 0;
83 uint32_t efi_lba
= 0, mac_lba
= 0;
84 uint16_t efi_count
= 0, mac_count
= 0;
85 uint8_t efi_boot
= 0, efi_media
= 0, efi_sys
= 0;
89 #ifdef REACTOS_ISOHYBRID_EFI_MAC_SUPPORT
90 uint8_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 };
92 uuid_t efi_system_partition
= {0xC1, 0x2A, 0x73, 0x28, 0xF8, 0x1F, 0x11, 0xD2, 0xBA, 0x4B, 0x00, 0xA0, 0xC9, 0x3E, 0xC9, 0x3B};
93 uuid_t basic_partition
= {0xEB,0xD0,0xA0,0xA2,0xB9,0xE5,0x44,0x33,0x87,0xC0,0x68,0xB6,0xB7,0x26,0x99,0xC7};
94 uuid_t hfs_partition
= {0x48, 0x46, 0x53, 0x00, 0x00, 0x00, 0x11, 0xAA, 0xAA, 0x11, 0x00, 0x30, 0x65, 0x43, 0xEC, 0xAC};
97 uint32_t crc_tab
[256] =
99 0, 0x77073096, 0xEE0E612C, 0x990951BA,
100 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
101 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
102 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
103 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
104 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
105 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
106 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
107 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
108 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
109 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
110 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
111 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
112 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
113 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
114 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
115 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
116 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
117 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
118 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
119 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
120 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
121 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
122 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
123 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
124 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
125 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
126 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
127 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
128 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
129 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
130 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
131 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
132 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
133 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
134 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
135 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
136 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
137 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
138 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
139 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
140 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
141 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
142 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
143 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
144 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
145 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
146 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
147 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
148 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
149 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
150 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
151 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
152 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
153 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
154 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
155 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
156 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
157 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
158 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
159 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
160 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
161 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
162 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
165 struct iso_primary_descriptor
{
168 uint8_t ignore2
[44];
172 #ifdef REACTOS_ISOHYBRID_EFI_MAC_SUPPORT
181 uint64_t firstUsableLBA
;
182 uint64_t lastUsableLBA
;
184 uint64_t partitionEntriesLBA
;
186 uint32_t sizeOfPartitionEntries
;
187 uint32_t partitionEntriesCRC
;
188 uint8_t reserved2
[420];
191 struct gpt_part_header
{
200 #define APM_OFFSET 2048
202 struct apple_part_header
{
203 uint16_t signature
; /* expected to be MAC_PARTITION_MAGIC */
205 uint32_t map_count
; /* # blocks in partition map */
206 uint32_t start_block
; /* absolute starting block # of partition */
207 uint32_t block_count
; /* number of blocks in partition */
208 char name
[32]; /* partition name */
209 char type
[32]; /* string type description */
210 uint32_t data_start
; /* rel block # of first data block */
211 uint32_t data_count
; /* number of data blocks */
212 uint32_t status
; /* partition status bits */
218 uint32_t boot_entry2
;
220 char processor
[16]; /* Contains 680x0, x=0,2,3,4; or empty */
230 printf("Usage: %s [OPTIONS] <boot.iso>\n", prog
);
237 #define FMT "%-20s %s\n"
242 printf("Options:\n");
243 printf(FMT
, " -h <X>", "Number of geometry heads (default 64)");
244 printf(FMT
, " -s <X>", "Number of geometry sectors (default 32)");
245 printf(FMT
, " -e --entry", "Specify partition entry number (1-4)");
246 printf(FMT
, " -o --offset", "Specify partition offset (default 0)");
247 printf(FMT
, " -t --type", "Specify partition type (default 0x17)");
248 printf(FMT
, " -i --id", "Specify MBR ID (default random)");
249 #ifdef REACTOS_ISOHYBRID_EFI_MAC_SUPPORT
250 printf(FMT
, " -u --uefi", "Build EFI bootable image");
251 printf(FMT
, " -m --mac", "Add AFP table support");
253 printf(FMT
, " -b --mbr <PATH>", "Load MBR from PATH");
256 printf(FMT
, " --forcehd0", "Assume we are loaded as disk ID 0");
257 printf(FMT
, " --ctrlhd0", "Assume disk ID 0 if the Ctrl key is pressed");
258 printf(FMT
, " --partok", "Allow booting from within a partition");
261 printf(FMT
, " -? --help", "Display this help");
262 printf(FMT
, " -v --verbose", "Display verbose output");
263 printf(FMT
, " -V --version", "Display version information");
266 printf("Report bugs to <pj.pandit@yahoo.co.in>\n");
271 check_option(int argc
, char *argv
[])
276 const char optstr
[] = ":h:s:e:o:t:i:b:umfcp?vV";
277 struct option lopt
[] = \
279 { "entry", required_argument
, NULL
, 'e' },
280 { "offset", required_argument
, NULL
, 'o' },
281 { "type", required_argument
, NULL
, 't' },
282 { "id", required_argument
, NULL
, 'i' },
284 { "forcehd0", no_argument
, NULL
, 'f' },
285 { "ctrlhd0", no_argument
, NULL
, 'c' },
286 { "partok", no_argument
, NULL
, 'p'},
287 #ifdef REACTOS_ISOHYBRID_EFI_MAC_SUPPORT
288 { "uefi", no_argument
, NULL
, 'u'},
289 { "mac", no_argument
, NULL
, 'm'},
291 { "mbr", required_argument
, NULL
, 'b' },
293 { "help", no_argument
, NULL
, '?' },
294 { "verbose", no_argument
, NULL
, 'v' },
295 { "version", no_argument
, NULL
, 'V' },
301 while ((n
= getopt_long_only(argc
, argv
, optstr
, lopt
, &ind
)) != -1)
306 head
= strtoul(optarg
, &err
, 0);
307 if (head
< 1 || head
> 256)
308 errx(1, "invalid head: `%s', 1 <= head <= 256", optarg
);
312 sector
= strtoul(optarg
, &err
, 0);
313 if (sector
< 1 || sector
> 63)
314 errx(1, "invalid sector: `%s', 1 <= sector <= 63", optarg
);
318 entry
= strtoul(optarg
, &err
, 0);
319 if (entry
< 1 || entry
> 4)
320 errx(1, "invalid entry: `%s', 1 <= entry <= 4", optarg
);
321 if (mode
& MAC
|| mode
& EFI
)
322 errx(1, "setting an entry is unsupported with EFI or Mac");
326 offset
= strtoul(optarg
, &err
, 0);
327 if (*err
|| offset
> 64)
328 errx(1, "invalid offset: `%s', 0 <= offset <= 64", optarg
);
332 type
= strtoul(optarg
, &err
, 0);
333 if (*err
|| type
> 255)
334 errx(1, "invalid type: `%s', 0 <= type <= 255", optarg
);
338 id
= strtoul(optarg
, &err
, 0);
340 errx(1, "invalid id: `%s'", optarg
);
355 #ifdef REACTOS_ISOHYBRID_EFI_MAC_SUPPORT
359 errx(1, "setting an entry is unsupported with EFI or Mac");
365 errx(1, "setting an entry is unsupported with EFI or Mac");
370 if (strlen(optarg
) >= sizeof(mbr_template_path
))
371 errx(1, "--mbr : Path too long");
372 strcpy(mbr_template_path
, optarg
);
380 printf("%s version %s\n", prog
, VERSION
);
384 errx(1, "option `-%c' takes an argument", optopt
);
389 errx(1, "invalid option `-%c', see --help", optopt
);
400 bendian_short(const uint16_t s
)
407 r
= (s
& 0x00FF) << 8 | (s
& 0xFF00) >> 8;
414 bendian_int(const uint32_t s
)
421 r
= (s
& 0x000000FF) << 24 | (s
& 0xFF000000) >> 24
422 | (s
& 0x0000FF00) << 8 | (s
& 0x00FF0000) >> 8;
428 lendian_short(const uint16_t s
)
435 r
= (s
& 0x00FF) << 8 | (s
& 0xFF00) >> 8;
442 lendian_int(const uint32_t s
)
449 r
= (s
& 0x000000FF) << 24 | (s
& 0xFF000000) >> 24
450 | (s
& 0x0000FF00) << 8 | (s
& 0x00FF0000) >> 8;
456 lendian_64(const uint64_t s
)
463 r
= (s
& 0x00000000000000FFull
) << 56 | (s
& 0xFF00000000000000ull
) >> 56
464 | (s
& 0x000000000000FF00ull
) << 40 | (s
& 0x00FF000000000000ull
) >> 40
465 | (s
& 0x0000000000FF0000ull
) << 24 | (s
& 0x0000FF0000000000ull
) >> 24
466 | (s
& 0x00000000FF000000ull
) << 8 | (s
& 0x000000FF00000000ull
) >> 8;
473 check_banner(const uint8_t *buf
)
475 static const char banner
[] = "\0CD001\1EL TORITO SPECIFICATION\0\0\0\0" \
476 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" \
479 if (!buf
|| memcmp(buf
, banner
, sizeof(banner
) - 1))
482 buf
+= sizeof(banner
) - 1;
483 memcpy(&catoffset
, buf
, sizeof(catoffset
));
485 catoffset
= lendian_int(catoffset
);
492 check_catalogue(const uint8_t *buf
)
496 for (i
= 0, cs
= 0; i
< 16; i
++)
499 memcpy(&ve
[i
], buf
, sizeof(ve
[i
]));
501 ve
[i
] = lendian_short(ve
[i
]);
507 printf("ve[%d]: %d, cs: %d\n", i
, ve
[i
], cs
);
509 if ((ve
[0] != 0x0001) || (ve
[15] != 0xAA55) || (cs
& 0xFFFF))
517 read_catalogue(const uint8_t *buf
)
519 memcpy(&de_boot
, buf
++, 1);
520 memcpy(&de_media
, buf
++, 1);
522 memcpy(&de_seg
, buf
, 2);
523 de_seg
= lendian_short(de_seg
);
526 memcpy(&de_sys
, buf
++, 1);
527 memcpy(&de_mbz1
, buf
++, 1);
529 memcpy(&de_count
, buf
, 2);
530 de_count
= lendian_short(de_count
);
533 memcpy(&de_lba
, buf
, 4);
534 de_lba
= lendian_int(de_lba
);
537 memcpy(&de_mbz2
, buf
, 2);
538 de_mbz2
= lendian_short(de_mbz2
);
541 if (de_boot
!= 0x88 || de_media
!= 0
542 || (de_seg
!= 0 && de_seg
!= 0x7C0) || de_count
!= 4)
549 #ifdef REACTOS_ISOHYBRID_EFI_MAC_SUPPORT
551 read_efi_section(const uint8_t *buf
)
553 unsigned char header_indicator
;
554 unsigned char platform_id
;
557 memcpy(&header_indicator
, buf
++, 1);
558 memcpy(&platform_id
, buf
++, 1);
560 memcpy(&count
, buf
, 2);
561 count
= lendian_short(count
);
564 if (platform_id
== 0xef)
571 read_efi_catalogue(const uint8_t *buf
, uint16_t *count
, uint32_t *lba
)
575 memcpy(count
, buf
, 2);
576 *count
= lendian_short(*count
);
580 *lba
= lendian_int(*lba
);
589 display_catalogue(void)
591 printf("de_boot: %hhu\n", de_boot
);
592 printf("de_media: %hhu\n", de_media
);
593 printf("de_seg: %hu\n", de_seg
);
594 printf("de_sys: %hhu\n", de_sys
);
595 printf("de_mbz1: %hhu\n", de_mbz1
);
596 printf("de_count: %hu\n", de_count
);
597 printf("de_lba: %u\n", de_lba
);
598 printf("de_mbz2: %hu\n", de_mbz2
);
603 read_mbr_template(char *path
, uint8_t *mbr
)
608 fp
= fopen(path
, "rb");
610 err(1, "could not open MBR template file `%s'", path
);
612 ret
= fread(mbr
, 1, MBRSIZE
, fp
);
613 if (ferror(fp
) || ret
!= MBRSIZE
)
614 err(1, "error while reading MBR template file `%s'", path
);
620 initialise_mbr(uint8_t *mbr
)
624 uint8_t ptype
= 0, *rbm
= mbr
;
625 uint8_t bhead
= 0, bsect
= 0, bcyle
= 0;
626 uint8_t ehead
= 0, esect
= 0, ecyle
= 0;
628 #ifndef ISOHYBRID_C_STANDALONE
629 extern unsigned char isohdpfx
[][MBRSIZE
];
632 if (mbr_template_path
[0]) {
633 read_mbr_template(mbr_template_path
, mbr
);
636 #ifdef ISOHYBRID_C_STANDALONE
638 err(1, "This is a standalone binary. You must specify --mbr. E.g with /usr/lib/syslinux/isohdpfx.bin");
642 memcpy(mbr
, &isohdpfx
[hd0
+ 3 * partok
], MBRSIZE
);
644 #endif /* ! ISOHYBRID_C_STANDALONE */
648 #ifdef REACTOS_ISOHYBRID_EFI_MAC_SUPPORT
650 memcpy(mbr
, afp_header
, sizeof(afp_header
));
657 #ifdef REACTOS_ISOHYBRID_EFI_MAC_SUPPORT
662 mbr
+= MBRSIZE
; /* offset 432 */
664 tmp
= lendian_int(de_lba
* 4);
665 memcpy(mbr
, &tmp
, sizeof(tmp
));
666 mbr
+= sizeof(tmp
); /* offset 436 */
669 memcpy(mbr
, &tmp
, sizeof(tmp
));
670 mbr
+= sizeof(tmp
); /* offset 440 */
672 tmp
= lendian_int(id
);
673 memcpy(mbr
, &tmp
, sizeof(tmp
));
674 mbr
+= sizeof(tmp
); /* offset 444 */
678 mbr
+= 2; /* offset 446 */
681 psize
= c
* head
* sector
- offset
;
683 bhead
= (offset
/ sector
) % head
;
684 bsect
= (offset
% sector
) + 1;
685 bcyle
= offset
/ (head
* sector
);
687 bsect
+= (bcyle
& 0x300) >> 2;
691 esect
= sector
+ (((cc
- 1) & 0x300) >> 2);
692 ecyle
= (cc
- 1) & 0xFF;
694 for (i
= 1; i
<= 4; i
++)
708 tmp
= lendian_int(offset
);
709 memcpy(&mbr
[8], &tmp
, sizeof(tmp
));
711 tmp
= lendian_int(psize
);
712 memcpy(&mbr
[12], &tmp
, sizeof(tmp
));
714 #ifdef REACTOS_ISOHYBRID_EFI_MAC_SUPPORT
715 if (i
== 2 && (mode
& EFI
))
726 tmp
= lendian_int(efi_lba
* 4);
727 memcpy(&mbr
[8], &tmp
, sizeof(tmp
));
729 tmp
= lendian_int(efi_count
);
730 memcpy(&mbr
[12], &tmp
, sizeof(tmp
));
732 if (i
== 3 && (mode
& MAC
))
743 tmp
= lendian_int(mac_lba
* 4);
744 memcpy(&mbr
[8], &tmp
, sizeof(tmp
));
746 tmp
= lendian_int(mac_count
);
747 memcpy(&mbr
[12], &tmp
, sizeof(tmp
));
760 display_mbr(const uint8_t *mbr
, size_t len
)
763 unsigned int i
= 0, j
= 0;
765 printf("sizeof(MBR): %zu bytes\n", len
);
766 for (i
= 0; i
< len
; i
++)
781 printf("%c", isprint(mbr
[j
]) ? mbr
[j
] : '.');
788 uint32_t chksum_crc32 (unsigned char *block
, unsigned int length
)
790 register unsigned long crc
;
794 for (i
= 0; i
< length
; i
++)
796 crc
= ((crc
>> 8) & 0x00FFFFFF) ^ crc_tab
[(crc
^ *block
++) & 0xFF];
798 return (crc
^ 0xFFFFFFFF);
801 #ifdef REACTOS_ISOHYBRID_EFI_MAC_SUPPORT
803 reverse_uuid(uuid_t uuid
)
805 uint8_t t
, *p
= (uint8_t *)uuid
;
807 t
= p
[0]; p
[0] = p
[3]; p
[3] = t
;
808 t
= p
[1]; p
[1] = p
[2]; p
[2] = t
;
809 t
= p
[4]; p
[4] = p
[5]; p
[5] = t
;
810 t
= p
[6]; p
[6] = p
[7]; p
[7] = t
;
815 ascii_to_utf16le(uint16_t *dst
, const char *src
)
817 uint8_t *p
= (uint8_t *)dst
;
826 return (uint16_t *)p
;
829 #ifdef REACTOS_ISOHYBRID_EFI_MAC_SUPPORT
831 initialise_gpt(uint8_t *gpt
, uint32_t current
, uint32_t alternate
, int primary
)
833 struct gpt_header
*header
= (struct gpt_header
*)gpt
;
834 struct gpt_part_header
*part
;
836 int gptsize
= 128 / 4 + 2;
839 /* 2048 bytes per partition, plus round to 2048 boundary */
840 hole
= (apm_parts
* 4) + 2;
844 uuid_generate(disk_uuid
);
845 reverse_uuid(disk_uuid
);
848 header
->signature
= lendian_64(0x5452415020494645ull
);
849 header
->revision
= lendian_int(0x010000);
850 header
->headerSize
= lendian_int(0x5c);
851 header
->currentLBA
= lendian_64(current
);
852 header
->backupLBA
= lendian_64(alternate
);
853 header
->firstUsableLBA
= lendian_64(gptsize
+ hole
);
854 header
->lastUsableLBA
= lendian_64((isostat
.st_size
+ padding
)/512 -
857 header
->partitionEntriesLBA
= lendian_64(0x02 + hole
);
859 header
->partitionEntriesLBA
= lendian_64(current
- (128 / 4));
860 header
->numParts
= lendian_int(0x80);
861 header
->sizeOfPartitionEntries
= lendian_int(0x80);
862 memcpy(header
->diskGUID
, disk_uuid
, sizeof(uuid_t
));
865 gpt
+= sizeof(struct gpt_header
) + hole
* 512;
867 gpt
-= header
->sizeOfPartitionEntries
* header
->numParts
;
869 part
= (struct gpt_part_header
*)gpt
;
871 uuid_generate(part_uuid
);
872 uuid_generate(iso_uuid
);
873 reverse_uuid(part_uuid
);
874 reverse_uuid(iso_uuid
);
877 memcpy(part
->partGUID
, iso_uuid
, sizeof(uuid_t
));
878 memcpy(part
->partTypeGUID
, basic_partition
, sizeof(uuid_t
));
879 part
->firstLBA
= lendian_64(0);
880 part
->lastLBA
= lendian_64(psize
- 1);
881 ascii_to_utf16le(part
->name
, "ISOHybrid ISO");
883 gpt
+= sizeof(struct gpt_part_header
);
886 memcpy(part
->partGUID
, part_uuid
, sizeof(uuid_t
));
887 memcpy(part
->partTypeGUID
, basic_partition
, sizeof(uuid_t
));
888 part
->firstLBA
= lendian_64(efi_lba
* 4);
889 part
->lastLBA
= lendian_64(part
->firstLBA
+ efi_count
- 1);
890 ascii_to_utf16le(part
->name
, "ISOHybrid");
892 gpt
+= sizeof(struct gpt_part_header
);
895 gpt
+= sizeof(struct gpt_part_header
);
899 memcpy(part
->partGUID
, part_uuid
, sizeof(uuid_t
));
900 memcpy(part
->partTypeGUID
, hfs_partition
, sizeof(uuid_t
));
901 part
->firstLBA
= lendian_64(mac_lba
* 4);
902 part
->lastLBA
= lendian_64(part
->firstLBA
+ mac_count
- 1);
903 ascii_to_utf16le(part
->name
, "ISOHybrid");
910 header
->partitionEntriesCRC
= lendian_int (chksum_crc32((uint8_t *)part
,
911 header
->numParts
* header
->sizeOfPartitionEntries
));
913 header
->headerCRC
= lendian_int(chksum_crc32((uint8_t *)header
,
914 header
->headerSize
));
918 initialise_apm(uint8_t *gpt
, uint32_t start
)
920 struct apple_part_header
*part
= (struct apple_part_header
*)gpt
;
922 part
->signature
= bendian_short(0x504d);
923 part
->map_count
= bendian_int(apm_parts
);
924 part
->start_block
= bendian_int(1);
925 part
->block_count
= bendian_int(4);
926 strcpy(part
->name
, "Apple");
927 strcpy(part
->type
, "Apple_partition_map");
928 part
->data_start
= bendian_int(0);
929 part
->data_count
= bendian_int(10);
930 part
->status
= bendian_int(0x03);
932 part
= (struct apple_part_header
*)(gpt
+ 2048);
934 part
->signature
= bendian_short(0x504d);
935 part
->map_count
= bendian_int(3);
936 part
->start_block
= bendian_int(efi_lba
);
937 part
->block_count
= bendian_int(efi_count
/ 4);
938 strcpy(part
->name
, "EFI");
939 strcpy(part
->type
, "Apple_HFS");
940 part
->data_start
= bendian_int(0);
941 part
->data_count
= bendian_int(efi_count
/ 4);
942 part
->status
= bendian_int(0x33);
944 part
= (struct apple_part_header
*)(gpt
+ 4096);
948 part
->signature
= bendian_short(0x504d);
949 part
->map_count
= bendian_int(3);
950 part
->start_block
= bendian_int(mac_lba
);
951 part
->block_count
= bendian_int(mac_count
/ 4);
952 strcpy(part
->name
, "EFI");
953 strcpy(part
->type
, "Apple_HFS");
954 part
->data_start
= bendian_int(0);
955 part
->data_count
= bendian_int(mac_count
/ 4);
956 part
->status
= bendian_int(0x33);
958 part
->signature
= bendian_short(0x504d);
959 part
->map_count
= bendian_int(3);
960 part
->start_block
= bendian_int((start
/2048) + 10);
961 part
->block_count
= bendian_int(efi_lba
- start
/2048 - 10);
962 strcpy(part
->name
, "ISO");
963 strcpy(part
->type
, "Apple_Free");
964 part
->data_start
= bendian_int(0);
965 part
->data_count
= bendian_int(efi_lba
- start
/2048 - 10);
966 part
->status
= bendian_int(0x01);
972 main(int argc
, char *argv
[])
976 uint8_t *buf
= NULL
, *bufz
= NULL
;
977 int cylsize
= 0, frac
= 0;
978 size_t orig_gpt_size
, free_space
, gpt_size
;
979 struct iso_primary_descriptor descriptor
;
981 prog
= strcpy(alloca(strlen(argv
[0]) + 1), argv
[0]);
982 i
= check_option(argc
, argv
);
992 #ifdef REACTOS_ISOHYBRID_EFI_MAC_SUPPORT
993 if ((mode
& EFI
) && offset
)
994 errx(1, "%s: --offset is invalid with UEFI images\n", argv
[0]);
997 srand(time(NULL
) << (getppid() << getpid()));
999 if (!(fp
= fopen(argv
[0], "rb+")))
1000 err(1, "could not open file `%s'", argv
[0]);
1002 if (fseeko(fp
, (off_t
) (16 << 11), SEEK_SET
))
1003 err(1, "%s: seek error - 0", argv
[0]);
1005 if (fread(&descriptor
, sizeof(char), sizeof(descriptor
), fp
) != sizeof(descriptor
))
1006 err(1, "%s: read error - 0", argv
[0]);
1008 if (fseeko(fp
, (off_t
) 17 * 2048, SEEK_SET
))
1009 err(1, "%s: seek error - 1", argv
[0]);
1011 bufz
= buf
= calloc(BUFSIZE
, sizeof(char));
1012 if (fread(buf
, sizeof(char), BUFSIZE
, fp
) != BUFSIZE
)
1013 err(1, "%s", argv
[0]);
1015 if (check_banner(buf
))
1016 errx(1, "%s: could not find boot record", argv
[0]);
1019 printf("catalogue offset: %d\n", catoffset
);
1021 if (fseeko(fp
, ((off_t
) catoffset
) * 2048, SEEK_SET
))
1022 err(1, "%s: seek error - 2", argv
[0]);
1025 memset(buf
, 0, BUFSIZE
);
1026 if (fread(buf
, sizeof(char), BUFSIZE
, fp
) != BUFSIZE
)
1027 err(1, "%s", argv
[0]);
1029 if (check_catalogue(buf
))
1030 errx(1, "%s: invalid boot catalogue", argv
[0]);
1033 if (read_catalogue(buf
))
1034 errx(1, "%s: unexpected boot catalogue parameters", argv
[0]);
1037 display_catalogue();
1041 #ifdef REACTOS_ISOHYBRID_EFI_MAC_SUPPORT
1044 if (!read_efi_section(buf
)) {
1046 if (!read_efi_catalogue(buf
, &efi_count
, &efi_lba
) && efi_lba
) {
1049 errx(1, "%s: invalid efi catalogue", argv
[0]);
1052 errx(1, "%s: unable to find efi image", argv
[0]);
1059 #ifdef REACTOS_ISOHYBRID_EFI_MAC_SUPPORT
1062 if (!read_efi_section(buf
)) {
1064 if (!read_efi_catalogue(buf
, &mac_count
, &mac_lba
) && mac_lba
) {
1067 errx(1, "%s: invalid efi catalogue", argv
[0]);
1070 errx(1, "%s: unable to find mac efi image", argv
[0]);
1075 if (fseeko(fp
, (((off_t
) de_lba
) * 2048 + 0x40), SEEK_SET
))
1076 err(1, "%s: seek error - 3", argv
[0]);
1079 memset(buf
, 0, BUFSIZE
);
1080 if (fread(buf
, sizeof(char), 4, fp
) != 4)
1081 err(1, "%s", argv
[0]);
1083 if (memcmp(buf
, "\xFB\xC0\x78\x70", 4))
1084 errx(1, "%s: boot loader does not have an isolinux.bin hybrid " \
1085 "signature. Note that isolinux-debug.bin does not support " \
1086 "hybrid booting", argv
[0]);
1088 if (stat(argv
[0], &isostat
))
1089 err(1, "%s", argv
[0]);
1091 isosize
= lendian_int(descriptor
.size
) * lendian_short(descriptor
.block_size
);
1092 free_space
= isostat
.st_size
- isosize
;
1094 cylsize
= head
* sector
* 512;
1095 frac
= isostat
.st_size
% cylsize
;
1096 padding
= (frac
> 0) ? cylsize
- frac
: 0;
1099 printf("imgsize: %zu, padding: %d\n", (size_t)isostat
.st_size
, padding
);
1101 cc
= c
= ( isostat
.st_size
+ padding
) / cylsize
;
1104 warnx("Warning: more than 1024 cylinders: %d", c
);
1105 warnx("Not all BIOSes will be able to boot this device");
1111 if (fseeko(fp
, (off_t
) 440, SEEK_SET
))
1112 err(1, "%s: seek error - 4", argv
[0]);
1114 if (fread(&id
, 1, 4, fp
) != 4)
1115 err(1, "%s: read error", argv
[0]);
1117 id
= lendian_int(id
);
1126 printf("id: %u\n", id
);
1129 memset(buf
, 0, BUFSIZE
);
1130 i
= initialise_mbr(buf
);
1133 display_mbr(buf
, i
);
1135 if (fseeko(fp
, (off_t
) 0, SEEK_SET
))
1136 err(1, "%s: seek error - 5", argv
[0]);
1138 if (fwrite(buf
, sizeof(char), i
, fp
) != (size_t)i
)
1139 err(1, "%s: write error - 1", argv
[0]);
1141 #ifdef REACTOS_ISOHYBRID_EFI_MAC_SUPPORT
1143 reverse_uuid(basic_partition
);
1144 reverse_uuid(hfs_partition
);
1146 /* 512 byte header, 128 entries of 128 bytes */
1147 orig_gpt_size
= gpt_size
= 512 + (128 * 128);
1149 /* Leave space for the APM if necessary */
1151 gpt_size
+= (4 * 2048);
1153 buf
= calloc(gpt_size
, sizeof(char));
1154 memset(buf
, 0, gpt_size
);
1157 * We need to ensure that we have enough space for the secondary GPT.
1158 * Unlike the primary, this doesn't need a hole for the APM. We still
1159 * want to be 1MB aligned so just bump the padding by a megabyte.
1161 if (free_space
< orig_gpt_size
&& padding
< orig_gpt_size
) {
1162 padding
+= 1024 * 1024;
1166 * Determine the size of the ISO filesystem. This will define the size
1167 * of the partition that covers it.
1169 psize
= isosize
/ 512;
1172 * Primary GPT starts at sector 1, secondary GPT starts at 1 sector
1173 * before the end of the image
1175 initialise_gpt(buf
, 1, (isostat
.st_size
+ padding
- 512) / 512, 1);
1177 if (fseeko(fp
, (off_t
) 512, SEEK_SET
))
1178 err(1, "%s: seek error - 6", argv
[0]);
1180 if (fwrite(buf
, sizeof(char), gpt_size
, fp
) != (size_t)gpt_size
)
1181 err(1, "%s: write error - 2", argv
[0]);
1186 /* Apple partition entries filling 2048 bytes each */
1187 int apm_size
= apm_parts
* 2048;
1189 buf
= realloc(buf
, apm_size
);
1190 memset(buf
, 0, apm_size
);
1192 initialise_apm(buf
, APM_OFFSET
);
1194 fseeko(fp
, (off_t
) APM_OFFSET
, SEEK_SET
);
1195 fwrite(buf
, sizeof(char), apm_size
, fp
);
1201 if (fsync(fileno(fp
)))
1202 err(1, "%s: could not synchronise", argv
[0]);
1204 if (ftruncate(fileno(fp
), isostat
.st_size
+ padding
))
1205 err(1, "%s: could not add padding bytes", argv
[0]);
1208 #ifdef REACTOS_ISOHYBRID_EFI_MAC_SUPPORT
1210 buf
= realloc(buf
, orig_gpt_size
);
1211 memset(buf
, 0, orig_gpt_size
);
1213 buf
+= orig_gpt_size
- sizeof(struct gpt_header
);
1215 initialise_gpt(buf
, (isostat
.st_size
+ padding
- 512) / 512, 1, 0);
1217 /* Shift back far enough to write the 128 GPT entries */
1218 buf
-= 128 * sizeof(struct gpt_part_header
);
1221 * Seek far enough back that the gpt header is 512 bytes before the
1225 if (fseeko(fp
, (isostat
.st_size
+ padding
) - orig_gpt_size
, SEEK_SET
))
1226 err(1, "%s: seek error - 8", argv
[0]);
1228 if (fwrite(buf
, sizeof(char), orig_gpt_size
, fp
) != orig_gpt_size
)
1229 err(1, "%s: write error - 4", argv
[0]);