[syslinux] [PATCH 6/6] utils/isohybrid.c: Introduce option --mbr and make isohybrid.c compilable standalone

Thomas Schmitt scdbackup at gmx.net
Sun Jun 22 13:24:22 PDT 2014


Although isohybrid.c is supposed to be a companion of the local SYSLINUX
installation, there may be situations where the file isolinux.bin and the
matching MBR template do not stem directly from such an installation.

This change adds an option --mbr, which allows to load an MBR template
file. This may be an isohdp[fp]x*.bin MBR template from the local SYSLINUX
installation, or the first 512 bytes of the isohybrid-capable ISO image
from which isolinux.bin and the other ISOLINUX files are taken.

If macro ISOHYBRID_C_STANDALONE is defined, then the hardcoded MBR templates
are not accessible and isohdpfx.o is not needed at compile time. In this
case, option --mbr becomes mandatory.
I used this for testing my changes with Fedora-Live-Desktop-x86_64-20-1.iso.

isohybrid.c is then compilable without further components of ISOLINUX by:

  cc -DISOHYBRID_C_STANDALONE -Wall -o isohybrid isohybrid.c -luuid

Test run:

  cp Fedora-Live-Desktop-x86_64-20-1.iso \
     Fedora-Live-Desktop-x86_64-20-1-rehybrid.iso

  valgrind ./isohybrid --uefi --mac \
           --mbr Fedora-Live-Desktop-x86_64-20-1.mbr \
           Fedora-Live-Desktop-x86_64-20-1-rehybrid.iso

yields:

  ==13828== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 1)
  ...
  ==13828== LEAK SUMMARY:
  ==13828==    definitely lost: 2,048 bytes in 1 blocks.

(Not that valgrind would have detected the memcpy() abuse of patch 001.
 But at least i seem to have not introduced more obvious sins.)
---
 utils/isohybrid.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 46 insertions(+), 2 deletions(-)

diff --git a/utils/isohybrid.c b/utils/isohybrid.c
index 072402f..0011b78 100644
--- a/utils/isohybrid.c
+++ b/utils/isohybrid.c
@@ -63,6 +63,8 @@ uint32_t id = 0;                /* MBR: 0 <= id <= 0xFFFFFFFF(4294967296) */
 uint8_t hd0 = 0;                /* 0 <= hd0 <= 2 */
 uint8_t partok = 0;             /* 0 <= partok <= 1 */
 
+char mbr_template_path[1024] = {0};   /* Path to MBR template */
+
 uint16_t ve[16];
 uint32_t catoffset = 0;
 uint32_t c = 0, cc = 0, cs = 0;
@@ -223,7 +225,7 @@ usage(void)
 void
 printh(void)
 {
-#define FMT "%-18s %s\n"
+#define FMT "%-20s %s\n"
 
     usage();
 
@@ -237,6 +239,7 @@ printh(void)
     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(FMT, "   -b --mbr <PATH>", "Load MBR from PATH");
 
     printf("\n");
     printf(FMT, "   --forcehd0", "Assume we are loaded as disk ID 0");
@@ -272,6 +275,7 @@ check_option(int argc, char *argv[])
         { "partok", no_argument, NULL, 'p'},
 	{ "uefi", no_argument, NULL, 'u'},
 	{ "mac", no_argument, NULL, 'm'},
+        { "mbr", required_argument, NULL, 'b' },
 
         { "help", no_argument, NULL, '?' },
         { "verbose", no_argument, NULL, 'v' },
@@ -347,6 +351,12 @@ check_option(int argc, char *argv[])
 		errx(1, "setting an entry is unsupported with EFI or Mac");
 	    break;
 
+	case 'b':
+            if (strlen(optarg) >= sizeof(mbr_template_path))
+                errx(1, "--mbr : Path too long");
+            strcpy(mbr_template_path, optarg);
+            break;
+
         case 'v':
             mode |= VERBOSE;
             break;
@@ -571,6 +581,24 @@ display_catalogue(void)
     printf("de_mbz2: %hu\n", de_mbz2);
 }
 
+
+void
+read_mbr_template(char *path, uint8_t *mbr)
+{
+    FILE *fp;
+    int ret;
+
+    fp = fopen(path, "rb");
+    if (fp == NULL)
+        err(1, "could not open MBR template file `%s'", path);
+    clearerr(fp);
+    ret = fread(mbr, 1, MBRSIZE, fp);
+    if (ferror(fp))
+        err(1, "error while reading MBR template file `%s'", path);
+    fclose(fp);
+}
+
+
 int
 initialise_mbr(uint8_t *mbr)
 {
@@ -580,9 +608,25 @@ initialise_mbr(uint8_t *mbr)
     uint8_t bhead = 0, bsect = 0, bcyle = 0;
     uint8_t ehead = 0, esect = 0, ecyle = 0;
 
+#ifndef ISOHYBRID_C_STANDALONE
     extern unsigned char isohdpfx[][MBRSIZE];
+#endif
+
+    if (mbr_template_path[0]) {
+        read_mbr_template(mbr_template_path, mbr);
+    } else {
+
+#ifdef ISOHYBRID_C_STANDALONE
+
+        err(1, "This is a standalone binary. You must specify --mbr. E.g with /usr/lib/syslinux/isohdpfx.bin");
 
-    memcpy(mbr, &isohdpfx[hd0 + 3 * partok], MBRSIZE);
+#else
+
+        memcpy(mbr, &isohdpfx[hd0 + 3 * partok], MBRSIZE);
+
+#endif /* ! ISOHYBRID_C_STANDALONE */
+
+    }
 
     if (mode & MAC) {
 	memcpy(mbr, afp_header, sizeof(afp_header));
-- 
1.8.4.2



More information about the Syslinux mailing list