Add '-e' (or -eltorito-boot-efi) option for writing an EFI eltorito boot
authorjmatthew <jmatthew@openbsd.org>
Tue, 21 Nov 2023 08:46:06 +0000 (08:46 +0000)
committerjmatthew <jmatthew@openbsd.org>
Tue, 21 Nov 2023 08:46:06 +0000 (08:46 +0000)
image, in addition to or instead of the x86 boot image, to the output file.
Per the UEFI standard, the EFI boot image should be an image of an EFI
System Partition to be loaded in no-emulation mode, so we always record it
that way rather than checking if it looks like a floppy image.

with, tested by and ok yasuoka@
strong encouragement from deraadt@

gnu/usr.sbin/mkhybrid/src/defaults.h
gnu/usr.sbin/mkhybrid/src/eltorito.c
gnu/usr.sbin/mkhybrid/src/iso9660.h
gnu/usr.sbin/mkhybrid/src/mkhybrid.8
gnu/usr.sbin/mkhybrid/src/mkisofs.c
gnu/usr.sbin/mkhybrid/src/mkisofs.h

index 2003f9a..7665464 100644 (file)
@@ -2,7 +2,7 @@
  * Header file defaults.h - assorted default values for character strings in
  * the volume descriptor.
  *
- *     $Id: defaults.h,v 1.1 2000/10/10 20:40:13 beck Exp $
+ *     $Id: defaults.h,v 1.2 2023/11/21 08:46:06 jmatthew Exp $
  */
 
 #define  PREPARER_DEFAULT      NULL
@@ -17,6 +17,7 @@
 #define  VOLUME_ID_DEFAULT     "CDROM"
 #define  BOOT_CATALOG_DEFAULT   "boot.catalog"
 #define  BOOT_IMAGE_DEFAULT     NULL
+#define  EFI_BOOT_IMAGE_DEFAULT NULL
 #ifdef APPLE_HYB
 #define         DEFTYPE                "TEXT"  /* default Apple TYPE */
 #define  DEFCREATOR            "unix"  /* default Apple CREATOR */
index ccb4454..4526d98 100644 (file)
@@ -44,6 +44,8 @@
 static struct eltorito_validation_entry valid_desc;
 static struct eltorito_defaultboot_entry default_desc;
 static struct eltorito_boot_descriptor gboot_desc;
+static struct eltorito_sectionheader_entry shdr_desc;
+static struct eltorito_defaultboot_entry efi_desc;
 
 static int tvd_write   __PR((FILE * outfile));
 
@@ -120,8 +122,9 @@ void FDECL1(get_torito_desc, struct eltorito_boot_descriptor *, boot_desc)
     int                                bootcat;
     int                                checksum;
     unsigned char                    * checksum_ptr;
-    struct directory_entry      * de;
+    struct directory_entry      * de = NULL;
     struct directory_entry      * de2;
+    struct directory_entry      * efi_de = NULL;
     int                                i;
     int                                nsectors;
     
@@ -149,8 +152,12 @@ void FDECL1(get_torito_desc, struct eltorito_boot_descriptor *, boot_desc)
      * now adjust boot catalog
      * lets find boot image first 
      */
-    de=search_tree_file(root, boot_image);
-    if (!de) 
+    if (boot_image != NULL)
+       de=search_tree_file(root, boot_image);
+    if (efi_boot_image != NULL)
+        efi_de=search_tree_file(root, efi_boot_image);
+
+    if (de == NULL && efi_boot_image == NULL)
     {
        fprintf(stderr,"Uh oh, I cant find the boot image!\n");
        exit(1);
@@ -162,7 +169,8 @@ void FDECL1(get_torito_desc, struct eltorito_boot_descriptor *, boot_desc)
      */
     memset(&valid_desc, 0, sizeof(valid_desc));
     valid_desc.headerid[0] = 1;
-    valid_desc.arch[0] = EL_TORITO_ARCH_x86;
+    valid_desc.arch[0] =
+       (boot_image != NULL)? EL_TORITO_ARCH_x86 : EL_TORITO_ARCH_EFI;
     
     /*
      * we'll shove start of publisher id into id field, may get truncated
@@ -198,6 +206,8 @@ void FDECL1(get_torito_desc, struct eltorito_boot_descriptor *, boot_desc)
     checksum = -checksum;
     set_721(valid_desc.cksum, (unsigned int) checksum);
     
+    if (de == NULL)
+       goto skip_x86;
     /*
      * now make the initial/default entry for boot catalog 
      */
@@ -279,7 +289,28 @@ void FDECL1(get_torito_desc, struct eltorito_boot_descriptor *, boot_desc)
 #endif
     set_731(default_desc.bootoff, 
            (unsigned int) get_733(de->isorec.extent));
-    
+ skip_x86:
+    /*
+     * add the EFI boot image, if specified
+     */
+    if (efi_de != NULL) {
+       if (de != NULL) {
+           memset(&shdr_desc, 0, sizeof(shdr_desc));
+           shdr_desc.header_id[0] = EL_TORITO_SHDR_ID_LAST_SHDR;
+           shdr_desc.platform_id[0] = EL_TORITO_ARCH_EFI;
+           set_721(shdr_desc.entry_count, 1);
+       }
+
+       memset(&efi_desc, 0, sizeof(efi_desc));
+       efi_desc.boot_id[0] = EL_TORITO_BOOTABLE;
+       set_721(efi_desc.loadseg, 0);
+       efi_desc.arch[0] = EL_TORITO_ARCH_EFI;
+
+       nsectors = ((efi_de->size + 511) & ~(511))/512;
+       set_721(efi_desc.nsect, nsectors);
+       set_731(efi_desc.bootoff, (unsigned int)get_733(efi_de->isorec.extent));
+    }
+
     /*
      * now write it to disk 
      */
@@ -295,7 +326,14 @@ void FDECL1(get_torito_desc, struct eltorito_boot_descriptor *, boot_desc)
      * write out 
      */
     write(bootcat, &valid_desc, 32);
-    write(bootcat, &default_desc, 32);
+    if (de != NULL)
+    {
+       write(bootcat, &default_desc, 32);
+       if (efi_de != NULL)
+           write(bootcat, &shdr_desc, sizeof(shdr_desc));
+    }
+    if (efi_de != NULL)
+       write(bootcat, &efi_desc, sizeof(efi_desc));
     close(bootcat);
 } /* get_torito_desc(... */
 
index 6227270..e856110 100644 (file)
@@ -21,7 +21,7 @@
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 /*
- *     $Id: iso9660.h,v 1.1 2000/10/10 20:40:16 beck Exp $
+ *     $Id: iso9660.h,v 1.2 2023/11/21 08:46:06 jmatthew Exp $
  */
 
 #ifndef _ISOFS_FS_H
@@ -52,6 +52,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_MEDIA_NOEMUL 0
 #define EL_TORITO_MEDIA_12FLOP  1
@@ -129,6 +130,16 @@ 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)];
+};
+
 
 /* We use this to help us look up the parent inode numbers. */
 
index 884b312..33b0a82 100644 (file)
@@ -2,7 +2,7 @@
 .\" To print, first run through tbl
 .\" -*- nroff -*-
 .\"
-.\" $Id: mkhybrid.8,v 1.4 2022/07/11 03:11:49 daniel Exp $
+.\" $Id: mkhybrid.8,v 1.5 2023/11/21 08:46:06 jmatthew Exp $
 .\"
 .TH MKHYBRID 8 "7 April 1999" "Version 1.12b5.1"
 .SH NAME
@@ -46,6 +46,10 @@ mkhybrid \- create an hybrid ISO9660/JOLIET/HFS filesystem with optional Rock Ri
 .B \-D
 ]
 [
+.B \-e
+.I efi_boot_image
+]
+[
 .B \-hide
 .I glob
 ]
@@ -474,6 +478,18 @@ Do not use deep directory relocation, and instead just pack them in the
 way we see them.  This violates the ISO9660 standard, but it works on many
 systems.  Use with caution.
 .TP
+.BI \-e " efi_boot_image
+Specifies the path and filename of the EFI boot image to be used when making
+an "El Torito" bootable CD.
+The pathname must be relative to the source path specified to
+.B mkhybrid.
+The file should contain an EFI system partition image.
+The
+.B \-e
+option can be used with or without the
+.B \-b
+option.
+.TP
 .B \-f
 Follow symbolic links when generating the filesystem.  When this option is not
 in use, symbolic links will be entered using Rock Ridge if enabled, otherwise
index 6ff6106..f59c5a7 100644 (file)
@@ -110,6 +110,7 @@ char * volume_id = VOLUME_ID_DEFAULT;
 char * system_id = SYSTEM_ID_DEFAULT;
 char * boot_catalog = BOOT_CATALOG_DEFAULT;
 char * boot_image = BOOT_IMAGE_DEFAULT;
+char * efi_boot_image = EFI_BOOT_IMAGE_DEFAULT;
 int volume_set_size = 1;
 int volume_sequence_number = 1;
 
@@ -274,6 +275,8 @@ static const struct ld_option ld_options[] =
       'd', NULL, "Omit trailing periods from filenames", ONE_DASH },
   { {"disable-deep-relocation", no_argument, NULL, 'D'},
       'D', NULL, "Disable deep directory relocation", ONE_DASH },
+  { {"eltorito-boot-efi", required_argument, NULL, 'e' },
+      'e', "FILE", "Set El Torito EFI boot image name" , ONE_DASH },
   { {"follow-links", no_argument, NULL, 'f'},
       'f', NULL, "Follow symbolic links", ONE_DASH },
   { {"help", no_argument, NULL, OPTION_HELP},
@@ -865,6 +868,14 @@ int FDECL2(main, int, argc, char **, argv){
                exit(1);
        }
        break;
+      case 'e':
+       use_eltorito++;
+       efi_boot_image = optarg;
+       if (efi_boot_image == NULL) {
+               fprintf(stderr,"Required EFI boot image pathname missing\n");
+               exit(1);
+       }
+       break;
       case 'c':
        use_eltorito++;
        boot_catalog = optarg;  /* pathname of the boot image on cd */
index e7af9e6..5f1065e 100644 (file)
@@ -20,7 +20,7 @@
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 /*
- *     $Id: mkisofs.h,v 1.4 2015/09/09 20:02:31 miod Exp $
+ *     $Id: mkisofs.h,v 1.5 2023/11/21 08:46:06 jmatthew Exp $
  */
 
 /* APPLE_HYB James Pearson j.pearson@ge.ucl.ac.uk 12/3/99 */
@@ -462,6 +462,7 @@ extern char * system_id;
 extern char * volume_id;
 extern char * boot_catalog;
 extern char * boot_image;
+extern char * efi_boot_image;
 extern int volume_set_size;
 extern int volume_sequence_number;