| From 5a2d571f3687910260c45841725f2deb84c8f12e Mon Sep 17 00:00:00 2001 |
| From: Hongxu Jia <hongxu.jia@windriver.com> |
| Date: Mon, 25 Apr 2022 18:18:00 +0800 |
| Subject: [PATCH] add new option -eltorito-platform |
| |
| Mkisofs now correctly supports El Torito multi boot entries by introducing |
| a Boot Dection Header before a list of alternate boot entries. |
| |
| New option -eltorito-platform allows to set the El Torito platform id |
| for a boot entry or for a list of boot entries. Supported values for |
| the parameter are: |
| - x86 the standard value vor x86 based PCs |
| - PPC the Power PC platform |
| - Mac The Apple Mac platform |
| - efi EFI based boot for PCs |
| - # an arbitrary numerical value |
| |
| Upstream-Status: Inappropriate [port from cdrtools] |
| https://github.com/jobermayr/cdrtools/commit/a50804fd61d75eb689a515dbfca6968ca2296fd7 |
| |
| Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com> |
| --- |
| genisoimage/eltorito.c | 73 +++++++++++++++++++++++++++++++++++++-- |
| genisoimage/genisoimage.c | 47 +++++++++++++++++++++++++ |
| genisoimage/genisoimage.h | 8 +++++ |
| genisoimage/iso9660.h | 33 ++++++++++++++++-- |
| 4 files changed, 157 insertions(+), 4 deletions(-) |
| |
| diff --git a/genisoimage/eltorito.c b/genisoimage/eltorito.c |
| index d52e17e..a804988 100644 |
| --- a/genisoimage/eltorito.c |
| +++ b/genisoimage/eltorito.c |
| @@ -56,6 +56,7 @@ static unsigned int bcat_de_flags; |
| void init_boot_catalog(const char *path); |
| void insert_boot_cat(void); |
| static void get_torito_desc(struct eltorito_boot_descriptor *boot_desc); |
| +static void fill_boot_shdr(struct eltorito_sectionheader_entry *boot_shdr_entry, int arch); |
| static void fill_boot_desc(struct eltorito_defaultboot_entry *boot_desc_entry, |
| struct eltorito_boot_entry_info *boot_entry); |
| void get_boot_entry(void); |
| @@ -282,7 +283,14 @@ get_torito_desc(struct eltorito_boot_descriptor *boot_desc) |
| struct directory_entry *de2; /* Boot catalog */ |
| int i; |
| int offset; |
| + int arch = 0; |
| + int nentries = 0; |
| struct eltorito_defaultboot_entry boot_desc_record; |
| + struct eltorito_sectionheader_entry boot_shdr_record; |
| +#ifdef __needed__ |
| + struct eltorito_section_entry boot_section_record; |
| +#endif |
| + struct eltorito_sectionheader_entry *last_section_header = 0; |
| |
| memset(boot_desc, 0, sizeof (*boot_desc)); |
| boot_desc->type[0] = 0; |
| @@ -311,13 +319,22 @@ get_torito_desc(struct eltorito_boot_descriptor *boot_desc) |
| set_731(boot_desc->bootcat_ptr, |
| (unsigned int) get_733(de2->isorec.extent)); |
| |
| + /* |
| + * If the platform id for the first (default) boot entry has not been |
| + * explicitly set, we default to EL_TORITO_ARCH_x86 |
| + */ |
| + if ((first_boot_entry->type & ELTORITO_BOOT_ID) == 0) { |
| + first_boot_entry->boot_platform = EL_TORITO_ARCH_x86; |
| + } |
| + arch = first_boot_entry->boot_platform; |
| + |
| /* |
| * we have the boot image, so write boot catalog information |
| * Next we write out the primary descriptor for the disc |
| */ |
| memset(&valid_desc, 0, sizeof (valid_desc)); |
| valid_desc.headerid[0] = 1; |
| - valid_desc.arch[0] = EL_TORITO_ARCH_x86; |
| + valid_desc.arch[0] = arch; /* Platform id for the default boot */ |
| |
| /* |
| * we'll shove start of publisher id into id field, |
| @@ -351,8 +368,17 @@ get_torito_desc(struct eltorito_boot_descriptor *boot_desc) |
| current_boot_entry != NULL; |
| current_boot_entry = current_boot_entry->next, |
| offset += sizeof (boot_desc_record)) { |
| + int newarch = arch; |
| |
| - if (offset >= SECTOR_SIZE) { |
| + if (current_boot_entry->type & ELTORITO_BOOT_ID) |
| + newarch = current_boot_entry->boot_platform; |
| + else |
| + current_boot_entry->boot_platform = arch; |
| + |
| + /* |
| + * El Torito has no such limitation but we currently have... |
| + */ |
| + if (offset >= (SECTOR_SIZE - sizeof (boot_desc_record))) { |
| #ifdef USE_LIBSCHILY |
| comerrno(EX_BAD, |
| "Too many El Torito boot entries\n"); |
| @@ -362,12 +388,53 @@ get_torito_desc(struct eltorito_boot_descriptor *boot_desc) |
| exit(1); |
| #endif |
| } |
| + |
| + if (current_boot_entry == first_boot_entry) { |
| + ; |
| + /* EMPTY */ |
| + } else if ((current_boot_entry == first_boot_entry->next) || |
| + (arch != newarch) || |
| + (current_boot_entry->type & ELTORITO_SECTION_HEADER)) { |
| + if (last_section_header) |
| + set_721(&last_section_header->entry_count, nentries); |
| + nentries = 1; |
| + last_section_header = (struct eltorito_sectionheader_entry *) |
| + (de2->table + offset); |
| + fill_boot_shdr(&boot_shdr_record, newarch); |
| + memcpy(de2->table + offset, &boot_shdr_record, |
| + sizeof (boot_shdr_record)); |
| + offset += sizeof (boot_desc_record); |
| + } else { |
| + nentries++; /* Add entry to this section header */ |
| + } |
| + /* |
| + * This works because a section entry has the same essential |
| + * layout as a default entry (and we do not populate the |
| + * selection criteria fields). |
| + */ |
| + |
| fill_boot_desc(&boot_desc_record, current_boot_entry); |
| memcpy(de2->table + offset, &boot_desc_record, |
| sizeof (boot_desc_record)); |
| } |
| + |
| + if (last_section_header) { |
| + set_721(&last_section_header->entry_count, nentries); |
| + last_section_header->header_id[0] = EL_TORITO_SHDR_ID_LAST_SHDR; |
| + } |
| + |
| }/* get_torito_desc(... */ |
| |
| +static void |
| +fill_boot_shdr(boot_shdr_entry, arch) |
| + struct eltorito_sectionheader_entry *boot_shdr_entry; |
| + int arch; |
| +{ |
| + memset(boot_shdr_entry, 0, sizeof(struct eltorito_sectionheader_entry)); |
| + boot_shdr_entry->header_id[0] = EL_TORITO_SHDR_ID_SHDR; |
| + boot_shdr_entry->platform_id[0] = arch; |
| +} |
| + |
| static void |
| fill_boot_desc(struct eltorito_defaultboot_entry *boot_desc_entry, |
| struct eltorito_boot_entry_info *boot_entry) |
| @@ -678,7 +745,9 @@ get_boot_entry() |
| if (!first_boot_entry) { |
| first_boot_entry = current_boot_entry; |
| last_boot_entry = current_boot_entry; |
| + current_boot_entry->boot_platform = EL_TORITO_ARCH_x86; |
| } else { |
| + current_boot_entry->boot_platform = last_boot_entry->boot_platform; |
| last_boot_entry->next = current_boot_entry; |
| last_boot_entry = current_boot_entry; |
| } |
| diff --git a/genisoimage/genisoimage.c b/genisoimage/genisoimage.c |
| index 9089081..84ac3c2 100644 |
| --- a/genisoimage/genisoimage.c |
| +++ b/genisoimage/genisoimage.c |
| @@ -271,6 +271,8 @@ struct rcopts { |
| char **variable; |
| }; |
| |
| +static int get_boot_platid(char *opt_arg); |
| + |
| struct rcopts rcopt[] = { |
| {"PREP", &preparer}, |
| {"PUBL", &publisher}, |
| @@ -404,6 +406,7 @@ struct ld_option { |
| |
| #define OPTION_ALLOW_LEADING_DOTS 1070 |
| #define OPTION_PUBLISHER 1071 |
| +#define OPTION_PLATFORM 1072 |
| |
| #ifdef JIGDO_TEMPLATE |
| #define OPTION_JTT_OUTPUT 1101 |
| @@ -528,6 +531,8 @@ static const struct ld_option ld_options[] = |
| 'b', "FILE", "Set El Torito boot image name", ONE_DASH}, |
| {{"eltorito-alt-boot", no_argument, NULL, OPTION_ALT_BOOT}, |
| '\0', NULL, "Start specifying alternative El Torito boot parameters", ONE_DASH}, |
| + {{"eltorito-platform", required_argument, NULL, OPTION_PLATFORM}, |
| + '\0', "ID", "Set El Torito platform id for the next boot entry", ONE_DASH}, |
| {{"sparc-boot", required_argument, NULL, 'B'}, |
| 'B', "FILES", "Set sparc boot image names", ONE_DASH}, |
| {{"sunx86-boot", required_argument, NULL, OPTION_SUNX86BOOT}, |
| @@ -1558,6 +1563,9 @@ int main(int argc, char *argv[]) |
| */ |
| new_boot_entry(); |
| break; |
| + case OPTION_PLATFORM: |
| + get_boot_platid(optarg); |
| + break; |
| case OPTION_BOOTALPHA: |
| use_alphaboot++; |
| /* list of pathnames of boot images */ |
| @@ -3829,3 +3837,42 @@ e_malloc(size_t size) |
| memset(pt, 0, size); |
| return (pt); |
| } |
| + |
| +static int |
| +get_boot_platid(char *opt_arg) |
| +{ |
| + long val; |
| + char *ptr; |
| + |
| + use_eltorito++; |
| + if (streql(opt_arg, "x86")) { |
| + val = EL_TORITO_ARCH_x86; |
| + } else if (streql(opt_arg, "PPC")) { |
| + val = EL_TORITO_ARCH_PPC; |
| + } else if (streql(opt_arg, "Mac")) { |
| + val = EL_TORITO_ARCH_PPC; |
| + } else if (streql(opt_arg, "efi")) { |
| + val = EL_TORITO_ARCH_EFI; |
| + } else { |
| + val = strtol(opt_arg, &ptr, 0); |
| + if (*ptr || val < 0 || val >= 0x100) { |
| + comerrno(EX_BAD, "Bad boot system ID.\n"); |
| + } |
| + } |
| + |
| + /* |
| + * If there is already a boot entry and the boot file name has been set |
| + * for this boot entry and the new platform id differs from the |
| + * previous value, we start a new boot section. |
| + */ |
| + if (current_boot_entry && |
| + current_boot_entry->boot_image != NULL && |
| + current_boot_entry->boot_platform != val) { |
| + new_boot_entry(); |
| + } |
| + get_boot_entry(); |
| + current_boot_entry->type |= ELTORITO_BOOT_ID; |
| + current_boot_entry->boot_platform = val; |
| + return (1); |
| +} |
| + |
| diff --git a/genisoimage/genisoimage.h b/genisoimage/genisoimage.h |
| index 82c859b..1170d89 100644 |
| --- a/genisoimage/genisoimage.h |
| +++ b/genisoimage/genisoimage.h |
| @@ -299,6 +299,14 @@ struct eltorito_boot_entry_info { |
| int boot_info_table; |
| int load_size; |
| int load_addr; |
| + |
| +#define ELTORITO_BOOT_ID 1 |
| +#define ELTORITO_SECTION_HEADER 2 |
| + int type; |
| + /* |
| + * Valid if (type & ELTORITO_BOOT_ID) != 0 |
| + */ |
| + int boot_platform; |
| }; |
| |
| extern int goof; |
| diff --git a/genisoimage/iso9660.h b/genisoimage/iso9660.h |
| index c74c2a9..61b6fc0 100644 |
| --- a/genisoimage/iso9660.h |
| +++ b/genisoimage/iso9660.h |
| @@ -62,6 +62,7 @@ struct iso_volume_descriptor { |
| #define EL_TORITO_ARCH_x86 0 |
| #define EL_TORITO_ARCH_PPC 1 |
| #define EL_TORITO_ARCH_MAC 2 |
| +#define EL_TORITO_ARCH_EFI 0xEF |
| |
| #define EL_TORITO_BOOTABLE 0x88 |
| #define EL_TORITO_NOT_BOOTABLE 0 |
| @@ -159,10 +160,15 @@ struct eltorito_boot_descriptor { |
| }; |
| |
| /* Validation entry for El Torito */ |
| +/* |
| + * headerid must be 1 |
| + * id is the manufacturer ID |
| + * cksum to make the sum of all shorts in this record 0 |
| + */ |
| struct eltorito_validation_entry { |
| char headerid [ISODCL(1, 1)]; /* 711 */ |
| char arch [ISODCL(2, 2)]; |
| - char pad1 [ISODCL(3, 4)]; /* 711 */ |
| + char pad1 [ISODCL(3, 4)]; /* 721 */ |
| char id [ISODCL(5, 28)]; /* CD devel/man*/ |
| char cksum [ISODCL(29, 30)]; |
| char key1 [ISODCL(31, 31)]; |
| @@ -173,7 +179,7 @@ struct eltorito_validation_entry { |
| struct eltorito_defaultboot_entry { |
| char boot_id [ISODCL(1, 1)]; /* 711 */ |
| char boot_media [ISODCL(2, 2)]; |
| - char loadseg [ISODCL(3, 4)]; /* 711 */ |
| + char loadseg [ISODCL(3, 4)]; /* 721 */ |
| char sys_type [ISODCL(5, 5)]; |
| char pad1 [ISODCL(6, 6)]; |
| char nsect [ISODCL(7, 8)]; |
| @@ -181,6 +187,29 @@ struct eltorito_defaultboot_entry { |
| char pad2 [ISODCL(13, 32)]; |
| }; |
| |
| +/* El Torito section header entry in boot catalog */ |
| +struct eltorito_sectionheader_entry { |
| +#define EL_TORITO_SHDR_ID_SHDR 0x90 |
| +#define EL_TORITO_SHDR_ID_LAST_SHDR 0x91 |
| + char header_id [ISODCL(1, 1)]; /* 711 */ |
| + char platform_id [ISODCL(2, 2)]; |
| + char entry_count [ISODCL(3, 4)]; /* 721 */ |
| + char id [ISODCL(5, 32)]; |
| +}; |
| + |
| +/* El Torito section entry in boot catalog */ |
| +struct eltorito_section_entry { |
| + char boot_id [ISODCL(1, 1)]; /* 711 */ |
| + char boot_media [ISODCL(2, 2)]; |
| + char loadseg [ISODCL(3, 4)]; /* 721 */ |
| + char sys_type [ISODCL(5, 5)]; |
| + char pad1 [ISODCL(6, 6)]; |
| + char nsect [ISODCL(7, 8)]; |
| + char bootoff [ISODCL(9, 12)]; |
| + char sel_criteria [ISODCL(13, 13)]; |
| + char vendor_sel_criteria [ISODCL(14, 32)]; |
| +}; |
| + |
| /* |
| * XXX JS: The next two structures have odd lengths! |
| * Some compilers (e.g. on Sun3/mc68020) padd the structures to even length. |
| -- |
| 2.27.0 |
| |