]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[build] Use a partition table in generated USB disk images
authorMichael Brown <mcb30@ipxe.org>
Mon, 23 Mar 2026 16:08:09 +0000 (16:08 +0000)
committerMichael Brown <mcb30@ipxe.org>
Wed, 25 Mar 2026 12:33:45 +0000 (12:33 +0000)
The USB disk image constructed by util/genfsimg is currently a raw FAT
filesystem, with no containing partition.  This makes it incompatible
with the use of CONSOLE_INT13, since there is no way to add a
dedicated log partition without a partition table.

Add a partition table when building a non-ISO image, using the mbr.bin
provided by syslinux (since we are already using syslinux to invoke
the ipxe.lkrn within the FAT filesystem).

The BIOS .usb targets are built using a manually constructed partition
table with C/H/S geometry x/64/32.  Match this geometry to minimise
the differences between genfsimg and non-genfsimg USB disk images.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/util/genfsimg

index 84deea42b6b9933dbc024b5805321c1d67de2483..9187f63f07ce726cb7c99f4a6d59757c6778f381 100755 (executable)
@@ -97,15 +97,13 @@ efi_boot_arch() {
     esac
 }
 
-# Copy syslinux file
+# Find syslinux file
 #
-copy_syslinux_file() {
+find_syslinux_file() {
     local FILENAME
-    local DESTDIR
     local SRCDIR
 
     FILENAME="${1}"
-    DESTDIR="${2}"
 
     for SRCDIR in \
        /usr/lib/syslinux \
@@ -122,7 +120,7 @@ copy_syslinux_file() {
        /usr/lib/ISOLINUX \
        ; do
        if [ -e "${SRCDIR}/${FILENAME}" ] ; then
-           install -m 644 "${SRCDIR}/${FILENAME}" "${DESTDIR}/"
+           echo "${SRCDIR}/${FILENAME}"
            return 0
        fi
     done
@@ -130,6 +128,20 @@ copy_syslinux_file() {
     return 1
 }
 
+# Copy syslinux file
+#
+copy_syslinux_file() {
+    local FILENAME
+    local DESTDIR
+    local SRCFILE
+
+    FILENAME="${1}"
+    DESTDIR="${2}"
+
+    SRCFILE=$(find_syslinux_file "${FILENAME}")
+    install -m 644 "${SRCFILE}" "${DESTDIR}/"
+}
+
 # Parse command-line options
 #
 OUTFILE=
@@ -190,6 +202,7 @@ fi
 WORKDIR=$(mktemp -d "${OUTFILE}.XXXXXX")
 ISODIR="${WORKDIR}/iso"
 FATDIR="${WORKDIR}/fat"
+MTOOLSRC="${WORKDIR}/mtoolsrc"
 mkdir -p "${ISODIR}" "${FATDIR}"
 
 # Configure output
@@ -200,15 +213,33 @@ case "${OUTFILE}" in
        FATIMG="${ISODIR}/esp.img"
        BIOSDIR="${ISODIR}"
        SYSLINUXCFG="${ISODIR}/isolinux.cfg"
+       FATPART=
+       ;;
+    *.sdsk)
+       ISOIMG=
+       FATIMG="${OUTFILE}"
+       BIOSDIR="${FATDIR}"
+       SYSLINUXCFG="${FATDIR}/syslinux.cfg"
+       FATPART=
        ;;
     *)
        ISOIMG=
        FATIMG="${OUTFILE}"
        BIOSDIR="${FATDIR}"
        SYSLINUXCFG="${FATDIR}/syslinux.cfg"
+       FATPART="4"
        ;;
 esac
 
+# Configure mtools
+#
+cat >"${MTOOLSRC}" <<EOF
+drive F:
+  file="${FATIMG}"
+  ${FATPART:+partition=}${FATPART}
+EOF
+export MTOOLSRC
+
 # Copy files to temporary working directory
 #
 LKRN=
@@ -312,13 +343,22 @@ fi
 if [ -n "${FATIMG}" ] ; then
     FATSIZE=$(du -s -k "${FATDIR}" | cut -f1)
     FATSIZE=$(( FATSIZE + PAD + 256 ))
-    if [ "${FATSIZE}" -le "1440" ] ; then
+    if [ -n "${FATPART}" -o "${FATSIZE}" -gt "1440" ] ; then
+       FATHEADS=64
+       FATSECTS=32
+       FATALIGN=$(( ( FATHEADS * FATSECTS ) / 2 ))
+       FATCYLS=$(( ( FATSIZE + FATALIGN - 1 ) / FATALIGN ))
+       FATSIZE=$(( FATCYLS * FATALIGN ))
+       FATARGS="-t ${FATCYLS} -h ${FATHEADS} -s ${FATSECTS}"
+    else
        FATSIZE=1440
-       FATARGS="-f 1440"
+       FATARGS="-f ${FATSIZE}"
+    fi
+    if [ -n "${FATPART}" ] ; then
+       FATOFFS="${FATSECTS}"
+       FATMBR=$(find_syslinux_file "mbr.bin")
     else
-       FATCYLS=$(( ( FATSIZE + 503 ) / 504 ))
-       FATSIZE=$(( FATCYLS * 504 ))
-       FATARGS="-s 63 -h 16 -t ${FATCYLS}"
+       FATOFFS=0
     fi
     if [ -n "${SOURCE_DATE_EPOCH:-}" ] ; then
        FATSERIAL=$(( SOURCE_DATE_EPOCH % 100000000 ))
@@ -327,10 +367,16 @@ if [ -n "${FATIMG}" ] ; then
     touch "${FATIMG}"
     truncate -s 0 "${FATIMG}"
     truncate -s "${FATSIZE}K" "${FATIMG}"
-    mformat -v iPXE -i "${FATIMG}" ${FATARGS} ::
-    mcopy -i "${FATIMG}" -s "${FATDIR}"/* ::
+    if [ -n "${FATPART}" ] ; then
+       dd if="${FATMBR}" of="${FATIMG}" conv=notrunc status=none
+       mpartition -c -I -t "${FATCYLS}" -h "${FATHEADS}" -s "${FATSECTS}" \
+                  -b "${FATOFFS}" F:
+       mpartition -a F:
+    fi
+    mformat -v iPXE ${FATARGS} F:
+    mcopy -s "${FATDIR}"/* F:
     if [ "${BIOSDIR}" = "${FATDIR}" ] ; then
-       syslinux "${FATIMG}"
+       syslinux --offset "$(( FATOFFS * 512 ))" "${FATIMG}"
     fi
 fi