New upstream, generate a full MBR on UEFI images

This commit is contained in:
Matthew Garrett 2012-02-15 12:16:46 -05:00
parent 02d428e33e
commit 433a0ba29b
5 changed files with 135 additions and 765 deletions

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
clog clog
syslinux-4.02.tar.bz2 syslinux-4.02.tar.bz2
/syslinux-4.05.tar.bz2

View File

@ -1 +1 @@
52912c03f5c275d6c0ac09180ebab81f syslinux-4.02.tar.bz2 82299242418385da1274c9479a778cb2 syslinux-4.05.tar.bz2

View File

@ -0,0 +1,124 @@
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]);
}

View File

@ -1,760 +0,0 @@
diff -ur syslinux-4.02.orig/mbr/isohdpfx.S syslinux-4.02/mbr/isohdpfx.S
--- syslinux-4.02.orig/mbr/isohdpfx.S 2010-07-21 15:33:13.000000000 -0400
+++ syslinux-4.02/mbr/isohdpfx.S 2011-08-24 18:21:16.559981607 -0400
@@ -65,7 +65,37 @@
.text
.globl _start
_start:
-
+ .byte 0x33, 0xed /* xorw %bp, %bp */
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
cli
xorw %bp, %bp
movw %bp, %ss
Only in syslinux-4.02/mbr: isohdpfx.S~
Only in syslinux-4.02/mbr: isohdpfx.S.orig
Only in syslinux-4.02/mbr: isohdpfx.S.rej
diff -ur syslinux-4.02.orig/utils/isohybrid.c syslinux-4.02/utils/isohybrid.c
--- syslinux-4.02.orig/utils/isohybrid.c 2010-07-21 15:33:13.000000000 -0400
+++ syslinux-4.02/utils/isohybrid.c 2011-08-24 18:19:55.600980389 -0400
@@ -36,14 +36,19 @@
#include <unistd.h>
#include <sys/stat.h>
#include <inttypes.h>
+#include <uuid/uuid.h>
#include "isohybrid.h"
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 };
+enum { VERBOSE = 1 , EFI = 2 , MAC = 4};
/* user options */
uint16_t head = 64; /* 1 <= head <= 256 */
@@ -61,10 +66,150 @@
uint32_t catoffset = 0;
uint32_t c = 0, cc = 0, cs = 0;
+uint32_t psize = 0, isosize = 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;
+uint8_t efi_boot = 0, efi_media = 0, efi_sys = 0;
+
+int apm_parts = 3;
+
+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 };
+
+uuid_t efi_system_partition = {0xC1, 0x2A, 0x73, 0x28, 0xF8, 0x1F, 0x11, 0xD2, 0xBA, 0x4B, 0x00, 0xA0, 0xC9, 0x3E, 0xC9, 0x3B};
+uuid_t basic_partition = {0xEB,0xD0,0xA0,0xA2,0xB9,0xE5,0x44,0x33,0x87,0xC0,0x68,0xB6,0xB7,0x26,0x99,0xC7};
+uuid_t hfs_partition = {0x48, 0x46, 0x53, 0x00, 0x00, 0x00, 0x11, 0xAA, 0xAA, 0x11, 0x00, 0x30, 0x65, 0x43, 0xEC, 0xAC};
+
+uint32_t crc_tab[256] =
+{
+ 0, 0x77073096, 0xEE0E612C, 0x990951BA,
+ 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
+ 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
+ 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
+ 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
+ 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
+ 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
+ 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
+ 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
+ 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
+ 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
+ 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
+ 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
+ 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
+ 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
+ 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
+ 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
+ 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
+ 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
+ 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
+ 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
+ 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
+ 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
+ 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
+ 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
+ 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
+ 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
+ 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
+ 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
+ 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
+ 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
+ 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
+ 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
+ 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
+ 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
+ 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
+ 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
+ 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
+ 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
+ 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
+ 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
+ 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
+ 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
+ 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
+ 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
+ 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
+ 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
+ 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
+ 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
+ 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
+ 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
+ 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
+ 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
+ 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
+ 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
+ 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
+ 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
+ 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
+ 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
+ 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
+ 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
+ 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
+ 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
+ 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
+};
+
+struct iso_primary_descriptor {
+ uint8_t ignore [80];
+ uint32_t size;
+ uint8_t ignore2 [44];
+ uint16_t block_size;
+};
+
+struct gpt_header {
+ uint64_t signature;
+ uint32_t revision;
+ uint32_t headerSize;
+ uint32_t headerCRC;
+ uint32_t reserved;
+ uint64_t currentLBA;
+ uint64_t backupLBA;
+ uint64_t firstUsableLBA;
+ uint64_t lastUsableLBA;
+ uuid_t diskGUID;
+ uint64_t partitionEntriesLBA;
+ uint32_t numParts;
+ uint32_t sizeOfPartitionEntries;
+ uint32_t partitionEntriesCRC;
+ uint8_t reserved2[420];
+};
+
+struct gpt_part_header {
+ uuid_t partTypeGUID;
+ uuid_t partGUID;
+ uint64_t firstLBA;
+ uint64_t lastLBA;
+ uint64_t attributes;
+ uint16_t name[36];
+};
+
+#define APM_OFFSET 2048
+
+struct apple_part_header {
+ uint16_t signature; /* expected to be MAC_PARTITION_MAGIC */
+ uint16_t res1;
+ uint32_t map_count; /* # blocks in partition map */
+ uint32_t start_block; /* absolute starting block # of partition */
+ uint32_t block_count; /* number of blocks in partition */
+ char name[32]; /* partition name */
+ char type[32]; /* string type description */
+ uint32_t data_start; /* rel block # of first data block */
+ uint32_t data_count; /* number of data blocks */
+ uint32_t status; /* partition status bits */
+ uint32_t boot_start;
+ uint32_t boot_count;
+ uint32_t boot_load;
+ uint32_t boot_load2;
+ uint32_t boot_entry;
+ uint32_t boot_entry2;
+ uint32_t boot_cksum;
+ char processor[16]; /* Contains 680x0, x=0,2,3,4; or empty */
+ uint32_t driver_sig;
+ char _padding[372];
+};
void
@@ -89,6 +234,8 @@
printf(FMT, " -o --offset", "Specify partition offset (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("\n");
printf(FMT, " --forcehd0", "Assume we are loaded as disk ID 0");
@@ -121,6 +268,8 @@
{ "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'},
{ "help", no_argument, NULL, '?' },
{ "verbose", no_argument, NULL, 'v' },
@@ -176,6 +325,14 @@
partok = 1;
break;
+ case 'u':
+ mode |= EFI;
+ break;
+
+ case 'm':
+ mode |= MAC;
+ break;
+
case 'v':
mode |= VERBOSE;
break;
@@ -200,6 +357,33 @@
return optind;
}
+uint16_t
+bendian_short(const uint16_t s)
+{
+ uint16_t r = 1;
+
+ if (!*(uint8_t *)&r)
+ return s;
+
+ r = (s & 0x00FF) << 8 | (s & 0xFF00) >> 8;
+
+ return r;
+}
+
+
+uint32_t
+bendian_int(const uint32_t s)
+{
+ uint32_t r = 1;
+
+ if (!*(uint8_t *)&r)
+ return s;
+
+ r = (s & 0x000000FF) << 24 | (s & 0xFF000000) >> 24
+ | (s & 0x0000FF00) << 8 | (s & 0x00FF0000) >> 8;
+
+ return r;
+}
uint16_t
lendian_short(const uint16_t s)
@@ -229,6 +413,22 @@
return r;
}
+uint64_t
+lendian_64(const uint64_t s)
+{
+ uint64_t r = 1;
+
+ if (*(uint8_t *)&r)
+ return s;
+
+ r = (s & 0x00000000000000FF) << 56 | (s & 0xFF00000000000000) >> 56
+ | (s & 0x000000000000FF00) << 40 | (s & 0x00FF000000000000) >> 40
+ | (s & 0x0000000000FF0000) << 24 | (s & 0x0000FF0000000000) >> 24
+ | (s & 0x00000000FF000000) << 8 | (s & 0x000000FF00000000) >> 8;
+
+ return r;
+}
+
int
check_banner(const uint8_t *buf)
@@ -307,6 +507,43 @@
}
+int
+read_efi_section(const uint8_t *buf)
+{
+ unsigned char header_indicator;
+ unsigned char platform_id;
+ short count;
+
+ memcpy(&header_indicator, buf++, 1);
+ memcpy(&platform_id, buf++, 1);
+
+ memcpy(&count, buf, 2);
+ count = lendian_short(count);
+ buf += 2;
+
+ if (platform_id == 0xef)
+ return 0;
+
+ return 1;
+}
+
+int
+read_efi_catalogue(const uint8_t *buf, uint16_t *count, uint32_t *lba)
+{
+ buf += 6;
+
+ memcpy(count, buf, 2);
+ *count = lendian_short(*count);
+ buf += 2;
+
+ memcpy(lba, buf, 4);
+ *lba = lendian_int(*lba);
+ buf += 6;
+
+ return 0;
+}
+
+
void
display_catalogue(void)
{
@@ -320,12 +557,11 @@
printf("de_mbz2: %hu\n", de_mbz2);
}
-
int
initialise_mbr(uint8_t *mbr)
{
int i = 0;
- uint32_t psize = 0, tmp = 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;
@@ -333,6 +569,11 @@
extern unsigned char isohdpfx[][MBRSIZE];
memcpy(mbr, &isohdpfx[hd0 + 3 * partok], MBRSIZE);
+
+ if (mode & MAC) {
+ memcpy(mbr, afp_header, sizeof(afp_header));
+ }
+
mbr += MBRSIZE; /* offset 432 */
tmp = lendian_int(de_lba * 4);
@@ -394,7 +635,6 @@
return mbr - rbm;
}
-
void
display_mbr(const uint8_t *mbr, size_t len)
{
@@ -424,14 +664,179 @@
}
+uint32_t chksum_crc32 (unsigned char *block, unsigned int length)
+{
+ register unsigned long crc;
+ unsigned long i;
+
+ crc = 0xFFFFFFFF;
+ for (i = 0; i < length; i++)
+ {
+ crc = ((crc >> 8) & 0x00FFFFFF) ^ crc_tab[(crc ^ *block++) & 0xFF];
+ }
+ return (crc ^ 0xFFFFFFFF);
+}
+
+void
+reverse_uuid(uuid_t uuid)
+{
+ uint8_t t, *p = (uint8_t *)uuid;
+
+ t = p[0]; p[0] = p[3]; p[3] = t;
+ t = p[1]; p[1] = p[2]; p[2] = t;
+ t = p[4]; p[4] = p[5]; p[5] = t;
+ t = p[6]; p[6] = p[7]; p[7] = t;
+}
+
+void
+initialise_gpt(uint8_t *gpt, uint32_t current, uint32_t alternate, int primary)
+{
+ struct gpt_header *header = (struct gpt_header *)gpt;
+ struct gpt_part_header *part;
+ int hole = 0;
+ int gptsize = 128 / 4 + 2;
+
+ if (mac_lba) {
+ /* 2048 bytes per partition, plus round to 2048 boundary */
+ hole = (apm_parts * 4) + 2;
+ }
+
+ if (primary) {
+ uuid_generate(disk_uuid);
+ reverse_uuid(disk_uuid);
+ }
+
+ header->signature = lendian_64(0x5452415020494645);
+ header->revision = lendian_int(0x010000);
+ header->headerSize = lendian_int(0x5c);
+ 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);
+ if (primary)
+ header->partitionEntriesLBA = lendian_64(0x02 + hole);
+ else
+ header->partitionEntriesLBA = lendian_64(current - (128 / 4));
+ header->numParts = lendian_int(0x80);
+ header->sizeOfPartitionEntries = lendian_int(0x80);
+ memcpy(header->diskGUID, disk_uuid, sizeof(uuid_t));
+
+ if (primary)
+ gpt += sizeof(struct gpt_header) + hole * 512;
+ else
+ gpt -= header->sizeOfPartitionEntries * header->numParts;
+
+ part = (struct gpt_part_header *)gpt;
+ if (primary) {
+ uuid_generate(part_uuid);
+ uuid_generate(iso_uuid);
+ reverse_uuid(part_uuid);
+ 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);
+ memcpy(part->name, "ISOHybrid ISO", 28);
+
+ 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);
+ memcpy(part->name, "ISOHybrid", 20);
+
+ gpt += sizeof(struct gpt_part_header);
+
+ if (mac_lba) {
+ gpt += sizeof(struct gpt_part_header);
+
+ part++;
+
+ 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);
+ memcpy(part->name, "ISOHybrid", 20);
+
+ part--;
+ }
+
+ part--;
+
+ header->partitionEntriesCRC = lendian_int (chksum_crc32((uint8_t *)part,
+ header->numParts * header->sizeOfPartitionEntries));
+
+ header->headerCRC = lendian_int(chksum_crc32((uint8_t *)header,
+ header->headerSize));
+}
+
+void
+initialise_apm(uint8_t *gpt, uint32_t start)
+{
+ struct apple_part_header *part = (struct apple_part_header *)gpt;
+
+ part->signature = bendian_short(0x504d);
+ part->map_count = bendian_int(apm_parts);
+ part->start_block = bendian_int(1);
+ part->block_count = bendian_int(0x10);
+ strcpy(part->name, "Apple");
+ strcpy(part->type, "Apple_partition_map");
+ part->data_start = bendian_int(0);
+ part->data_count = bendian_int(10);
+ part->status = bendian_int(0x03);
+
+ part = (struct apple_part_header *)(gpt + 2048);
+
+ 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);
+ strcpy(part->name, "EFI");
+ strcpy(part->type, "Apple_HFS");
+ part->data_start = bendian_int(0);
+ part->data_count = bendian_int(efi_count);
+ part->status = bendian_int(0x33);
+
+ part = (struct apple_part_header *)(gpt + 4096);
+
+ if (mac_lba)
+ {
+ 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);
+ strcpy(part->name, "EFI");
+ strcpy(part->type, "Apple_HFS");
+ part->data_start = bendian_int(0);
+ part->data_count = bendian_int(mac_count);
+ part->status = bendian_int(0x33);
+ } else {
+ part->signature = bendian_short(0x504d);
+ part->map_count = bendian_int(3);
+ part->start_block = bendian_int((start/2048) + 10);
+ part->block_count = bendian_int(efi_lba - start/2048 - 10);
+ strcpy(part->name, "ISO");
+ strcpy(part->type, "Apple_Free");
+ part->data_start = bendian_int(0);
+ part->data_count = bendian_int(efi_lba - start/2048 - 10);
+ part->status = bendian_int(0x01);
+ }
+}
+
int
main(int argc, char *argv[])
{
int i = 0;
FILE *fp = NULL;
- struct stat isostat;
uint8_t *buf = NULL, *bufz = NULL;
- int cylsize = 0, frac = 0, padding = 0;
+ int cylsize = 0, frac = 0;
+ size_t orig_gpt_size, free_space, gpt_size;
+ struct iso_primary_descriptor descriptor;
prog = strcpy(alloca(strlen(argv[0]) + 1), argv[0]);
i = check_option(argc, argv);
@@ -443,10 +848,21 @@
usage();
return 1;
}
+
+ if ((mode & EFI) && offset)
+ errx(1, "%s: --offset is invalid with UEFI images\n", argv[0]);
+
srand(time(NULL) << (getppid() << getpid()));
if (!(fp = fopen(argv[0], "r+")))
err(1, "could not open file `%s'", argv[0]);
+
+ if (fseek(fp, (16 << 11), SEEK_SET))
+ err(1, "%s: seek error - 0", argv[0]);
+
+ if (fread(&descriptor, sizeof(char), sizeof(descriptor), fp) != sizeof(descriptor))
+ err(1, "%s: read error - 0", argv[0]);
+
if (fseek(fp, 17 * 2048, SEEK_SET))
err(1, "%s: seek error - 1", argv[0]);
@@ -478,6 +894,40 @@
if (mode & VERBOSE)
display_catalogue();
+ buf += 32;
+
+ if (mode & EFI)
+ {
+ if (!read_efi_section(buf)) {
+ buf += 32;
+ if (!read_efi_catalogue(buf, &efi_count, &efi_lba) && efi_lba) {
+ offset = 1;
+ type = 0xee;
+ } else {
+ errx(1, "%s: invalid efi catalogue", argv[0]);
+ }
+ } else {
+ errx(1, "%s: unable to find efi image", argv[0]);
+ }
+ }
+
+ buf += 32;
+
+ if (mode & MAC)
+ {
+ if (!read_efi_section(buf)) {
+ buf += 32;
+ if (!read_efi_catalogue(buf, &mac_count, &mac_lba) && mac_lba) {
+ offset = 1;
+ type = 0xee;
+ } else {
+ errx(1, "%s: invalid efi catalogue", argv[0]);
+ }
+ } else {
+ errx(1, "%s: unable to find mac efi image", argv[0]);
+ }
+ }
+
if (fseek(fp, (de_lba * 2048 + 0x40), SEEK_SET))
err(1, "%s: seek error - 3", argv[0]);
@@ -494,6 +944,9 @@
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;
+
cylsize = head * sector * 512;
frac = isostat.st_size % cylsize;
padding = (frac > 0) ? cylsize - frac : 0;
@@ -501,7 +954,7 @@
if (mode & VERBOSE)
printf("imgsize: %zu, padding: %d\n", (size_t)isostat.st_size, padding);
- cc = c = (isostat.st_size + padding) / cylsize;
+ cc = c = ( isostat.st_size + padding) / cylsize;
if (c > 1024)
{
warnx("Warning: more than 1024 cylinders: %d", c);
@@ -541,6 +994,62 @@
if (fwrite(buf, sizeof(char), i, fp) != (size_t)i)
err(1, "%s: write error - 1", argv[0]);
+ if (efi_lba) {
+ 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 - 1024) / 512, 1);
+
+ if (fseek(fp, 512, SEEK_SET))
+ err(1, "%s: seek error - 6", argv[0]);
+
+ if (fwrite(buf, sizeof(char), gpt_size, fp) != (size_t)gpt_size)
+ err(1, "%s: write error - 2", argv[0]);
+ }
+
+ if (mac_lba)
+ {
+ /* Apple partition entries filling 2048 bytes each */
+ int apm_size = apm_parts * 2048;
+
+ buf = realloc(buf, apm_size);
+ memset(buf, 0, apm_size);
+
+ initialise_apm(buf, APM_OFFSET);
+
+ fseek(fp, APM_OFFSET, SEEK_SET);
+ fwrite(buf, sizeof(char), apm_size, fp);
+ }
+
if (padding)
{
if (!(buf = realloc(buf, padding)))
@@ -554,6 +1063,30 @@
err(1, "%s: write error - 2", argv[0]);
}
+ if (efi_lba) {
+ 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 - 1024) / 512, 1, 0);
+
+ /* Shift back far enough to write the 128 GPT entries */
+ buf -= 128 * sizeof(struct gpt_part_header);
+
+ /*
+ * Seek far enough back that the gpt header is 512 bytes before the
+ * end of the image
+ */
+
+ if (fseek(fp, (isostat.st_size + padding) - orig_gpt_size - 512,
+ SEEK_SET))
+ err(1, "%s: seek error - 8", argv[0]);
+
+ if (fwrite(buf, sizeof(char), orig_gpt_size, fp) != orig_gpt_size)
+ err(1, "%s: write error - 4", argv[0]);
+ }
+
free(buf);
fclose(fp);
Only in syslinux-4.02/utils: isohybrid.c.orig
diff -ur syslinux-4.02.orig/utils/Makefile syslinux-4.02/utils/Makefile
--- syslinux-4.02.orig/utils/Makefile 2010-07-21 15:33:13.000000000 -0400
+++ syslinux-4.02/utils/Makefile 2011-08-24 18:19:55.597980389 -0400
@@ -47,7 +47,7 @@
$(PERL) isohdpfxarray.pl $(ISOHDPFX) > $@
isohybrid: isohybrid.o isohdpfx.o
- $(CC) $(LDFLAGS) -o $@ $^
+ $(CC) $(LDFLAGS) -luuid -o $@ $^
gethostip: gethostip.o
$(CC) $(LDFLAGS) -o $@ $^
Only in syslinux-4.02/utils: Makefile.orig

View File

@ -1,8 +1,8 @@
Summary: Simple kernel loader which boots from a FAT filesystem Summary: Simple kernel loader which boots from a FAT filesystem
Name: syslinux Name: syslinux
Version: 4.02 Version: 4.05
%define tarball_version 4.02 %define tarball_version 4.05
Release: 6%{?dist} Release: 1%{?dist}
License: GPLv2+ License: GPLv2+
Group: Applications/System Group: Applications/System
URL: http://syslinux.zytor.com/wiki/index.php/The_Syslinux_Project URL: http://syslinux.zytor.com/wiki/index.php/The_Syslinux_Project
@ -21,7 +21,7 @@ Requires: mtools, libc.so.6()(64bit)
Obsoletes: syslinux-devel < %{version}-%{release} Obsoletes: syslinux-devel < %{version}-%{release}
Provides: syslinux-devel Provides: syslinux-devel
Patch1: syslinux-isohybrid-gpt.patch Patch1: syslinux-isohybrid-fix-mbr.patch
# NOTE: extlinux belongs in /sbin, not in /usr/sbin, since it is typically # NOTE: extlinux belongs in /sbin, not in /usr/sbin, since it is typically
# a system bootloader, and may be necessary for system recovery. # a system bootloader, and may be necessary for system recovery.
@ -124,6 +124,7 @@ rm -rf %{buildroot}
%{_datadir}/syslinux/memdisk %{_datadir}/syslinux/memdisk
%dir %{_datadir}/syslinux/dosutil %dir %{_datadir}/syslinux/dosutil
%{_datadir}/syslinux/dosutil/* %{_datadir}/syslinux/dosutil/*
%{_datadir}/syslinux/diag/*
%files perl %files perl
%defattr(-,root,root) %defattr(-,root,root)
@ -165,6 +166,10 @@ elif [ -f /boot/extlinux.conf ]; then \
fi fi
%changelog %changelog
* Wed Feb 15 2012 Matthew Garrett <mjg@redhat.com> - 4.05-1
- New upstream release
- syslinux-isohybrid-fix-mbr.patch: generate a full MBR for UEFI images
* Sat Jan 14 2012 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 4.02-6 * Sat Jan 14 2012 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 4.02-6
- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild - Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild