[meta-oe,V2] cdrkit: add new option -eltorito-platform for genimageiso

Message ID 20220426074207.451383-1-hongxu.jia@windriver.com
State New
Headers show
Series [meta-oe,V2] cdrkit: add new option -eltorito-platform for genimageiso | expand

Commit Message

Hongxu Jia April 26, 2022, 7:42 a.m. UTC
Mkisofs/genimageiso 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

Port implement from cdrtools:
https://github.com/jobermayr/cdrtools/commit/a50804fd61d75eb689a515dbfca6968ca2296fd7

Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
---
 .../cdrkit/cdrkit_1.1.11.bb                   |   1 +
 ...001-add-new-option-eltorito-platform.patch | 335 ++++++++++++++++++
 2 files changed, 336 insertions(+)
 create mode 100644 meta-oe/recipes-multimedia/cdrkit/files/0001-add-new-option-eltorito-platform.patch

Comments

Ross Burton April 26, 2022, 8:27 a.m. UTC | #1
Have you carefully examined the license of the files that you’re copying from mkisofs: the cdrkit fork exists specifically because cdrtools relicensed to CDDL[1] which is GPL-incompatible.

Also, are we going to be carrying this forever, or is upstream cdrkit going to merge the same code?

Ross
[1] https://lwn.net/Articles/195167/

From: openembedded-devel@lists.openembedded.org <openembedded-devel@lists.openembedded.org> on behalf of hongxu via lists.openembedded.org <hongxu.jia=windriver.com@lists.openembedded.org>
Date: Tuesday, 26 April 2022 at 08:42
To: raj.khem@gmail.com <raj.khem@gmail.com>
Cc: openembedded-devel@lists.openembedded.org <openembedded-devel@lists.openembedded.org>
Subject: [oe] [meta-oe][PATCH V2] cdrkit: add new option -eltorito-platform for genimageiso
Mkisofs/genimageiso 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

Port implement from cdrtools:
https://github.com/jobermayr/cdrtools/commit/a50804fd61d75eb689a515dbfca6968ca2296fd7

Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
---
 .../cdrkit/cdrkit_1.1.11.bb                   |   1 +
 ...001-add-new-option-eltorito-platform.patch | 335 ++++++++++++++++++
 2 files changed, 336 insertions(+)
 create mode 100644 meta-oe/recipes-multimedia/cdrkit/files/0001-add-new-option-eltorito-platform.patch

diff --git a/meta-oe/recipes-multimedia/cdrkit/cdrkit_1.1.11.bb b/meta-oe/recipes-multimedia/cdrkit/cdrkit_1.1.11.bb
index dd0405c95..757f99d1f 100644
--- a/meta-oe/recipes-multimedia/cdrkit/cdrkit_1.1.11.bb
+++ b/meta-oe/recipes-multimedia/cdrkit/cdrkit_1.1.11.bb
@@ -11,6 +11,7 @@ SRC_URI = "${DEBIAN_MIRROR}/main/c/${BPN}/${BPN}_${PV}.orig.tar.gz \
            file://0001-define-__THROW-to-avoid-build-issue-with-musl.patch<file:///0001-define-__THROW-to-avoid-build-issue-with-musl.patch> \
            file://0002-Do-not-use-rcmd-on-build-with-musl.patch<file:///0002-Do-not-use-rcmd-on-build-with-musl.patch> \
            file://0001-genisoimage-Add-missing-extern-definition.patch<file:///0001-genisoimage-Add-missing-extern-definition.patch> \
+           file://0001-add-new-option-eltorito-platform.patch<file:///0001-add-new-option-eltorito-platform.patch> \
            "
 SRC_URI:append:class-nativesdk = " \
            file://0001-install-netscsid-to-bin-for-nativesdk.patch<file:///0001-install-netscsid-to-bin-for-nativesdk.patch> \
diff --git a/meta-oe/recipes-multimedia/cdrkit/files/0001-add-new-option-eltorito-platform.patch b/meta-oe/recipes-multimedia/cdrkit/files/0001-add-new-option-eltorito-platform.patch
new file mode 100644
index 000000000..dac3328a4
--- /dev/null
+++ b/meta-oe/recipes-multimedia/cdrkit/files/0001-add-new-option-eltorito-platform.patch
@@ -0,0 +1,335 @@
+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
+
--
2.27.0
IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.
Hongxu Jia April 26, 2022, 8:50 a.m. UTC | #2
Thanks for pointing out the license issue, this patch ports from 4 source files of cdrtools,
and both of them are `either GPL version 2, or (at your option) any later version.'

https://github.com/jobermayr/cdrtools/blob/master/mkisofs/mkisofs.c#L16
https://github.com/jobermayr/cdrtools/blob/master/mkisofs/mkisofs.h#L10
https://github.com/jobermayr/cdrtools/blob/master/mkisofs/iso9660.h#L11
https://github.com/jobermayr/cdrtools/blob/master/mkisofs/eltorito.c#L17

Both of cdrtools(2013)[1] and cdrkit(2010)[2] are not alive, I do not plan to send it to upstream cdrkit

[1] https://github.com/Distrotech/cdrtools.git
[2] https://github.com/Distrotech/cdrkit.git


//Hongxu

Patch

diff --git a/meta-oe/recipes-multimedia/cdrkit/cdrkit_1.1.11.bb b/meta-oe/recipes-multimedia/cdrkit/cdrkit_1.1.11.bb
index dd0405c95..757f99d1f 100644
--- a/meta-oe/recipes-multimedia/cdrkit/cdrkit_1.1.11.bb
+++ b/meta-oe/recipes-multimedia/cdrkit/cdrkit_1.1.11.bb
@@ -11,6 +11,7 @@  SRC_URI = "${DEBIAN_MIRROR}/main/c/${BPN}/${BPN}_${PV}.orig.tar.gz \
            file://0001-define-__THROW-to-avoid-build-issue-with-musl.patch \
            file://0002-Do-not-use-rcmd-on-build-with-musl.patch \
            file://0001-genisoimage-Add-missing-extern-definition.patch \
+           file://0001-add-new-option-eltorito-platform.patch \
            "
 SRC_URI:append:class-nativesdk = " \
            file://0001-install-netscsid-to-bin-for-nativesdk.patch \
diff --git a/meta-oe/recipes-multimedia/cdrkit/files/0001-add-new-option-eltorito-platform.patch b/meta-oe/recipes-multimedia/cdrkit/files/0001-add-new-option-eltorito-platform.patch
new file mode 100644
index 000000000..dac3328a4
--- /dev/null
+++ b/meta-oe/recipes-multimedia/cdrkit/files/0001-add-new-option-eltorito-platform.patch
@@ -0,0 +1,335 @@ 
+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
+