]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[build] Create util/genfsimg for building filesystem-based images 204/head
authorMichael Brown <mcb30@ipxe.org>
Wed, 13 Jan 2021 11:50:26 +0000 (11:50 +0000)
committerMichael Brown <mcb30@ipxe.org>
Wed, 13 Jan 2021 17:58:02 +0000 (17:58 +0000)
Generalise util/geniso, util/gensdsk, and util/genefidsk to create a
single script util/genfsimg that can be used to build either FAT
filesystem images or ISO images.

Extend the functionality to allow for building multi-architecture UEFI
bootable ISO images and combined BIOS+UEFI images.

For example:

  ./util/genfsimg -o combined.iso \
      bin-x86_64-efi/ipxe.efi \
      bin-arm64-efi/ipxe.efi \
      bin/ipxe.lkrn

would generate a hybrid image that could be used as a CDROM (or hard
disk or USB key) on legacy BIOS, x86_64 UEFI, or ARM64 UEFI.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/Makefile.efi
src/arch/x86/Makefile.pcbios
src/util/genefidsk [deleted file]
src/util/genfsimg [new file with mode: 0755]
src/util/geniso [deleted file]
src/util/gensdsk [deleted file]

index 10f3fe74be5b70fe724d881debcda1a1146e258d..4b35381d3004a44bcfe650bc8821c833e1623fbe 100644 (file)
@@ -49,6 +49,6 @@ $(BIN)/efidrv.cab : $(BIN)/alldrv.efis # $(ALL_drv.efi) is not yet defined
        $(QM)$(ECHO) "  [CAB] $@"
        $(Q)$(LCAB) -n -q $(ALL_drv.efi) $@
 
-$(BIN)/%.usb : $(BIN)/%.efi
-       $(QM)$(ECHO) "  [GENEFIDSK] $@"
-       $(Q)bash util/genefidsk -o $@ -b $(EFI_BOOT_FILE) $<
+$(BIN)/%.iso $(BIN)/%.usb : $(BIN)/%.efi util/genfsimg
+       $(QM)$(ECHO) "  [GENFSIMG] $@"
+       $(Q)util/genfsimg -o $@ $<
index c44eefc1fa1f91e46ca9f9a1ae7d9dad039098ff..751d7d28cc6b81fb7ad8cb79e38bbf97ee8c31d5 100644 (file)
@@ -57,46 +57,11 @@ LIST_NAME_mrom := ROMS
 LIST_NAME_pcirom := ROMS
 LIST_NAME_isarom := ROMS
 
-# Locations of isolinux files
-#
-SYSLINUX_DIR_LIST      := \
-       /usr/lib/syslinux \
-       /usr/lib/syslinux/bios \
-       /usr/lib/syslinux/modules/bios \
-       /usr/share/syslinux \
-       /usr/share/syslinux/bios \
-       /usr/share/syslinux/modules/bios \
-       /usr/local/share/syslinux \
-       /usr/local/share/syslinux/bios \
-       /usr/local/share/syslinux/modules/bios \
-       /usr/lib/ISOLINUX
-ISOLINUX_BIN_LIST      := \
-       $(ISOLINUX_BIN) \
-       $(patsubst %,%/isolinux.bin,$(SYSLINUX_DIR_LIST))
-LDLINUX_C32_LIST       := \
-       $(LDLINUX_C32) \
-       $(patsubst %,%/ldlinux.c32,$(SYSLINUX_DIR_LIST))
-ISOLINUX_BIN   = $(firstword $(wildcard $(ISOLINUX_BIN_LIST)))
-LDLINUX_C32    = $(firstword $(wildcard $(LDLINUX_C32_LIST)))
-
-# rule to make a non-emulation ISO boot image
+# ISO or FAT filesystem images
 NON_AUTO_MEDIA += iso
-%iso:  %lkrn util/geniso
-       $(QM)$(ECHO) "  [GENISO] $@"
-       $(Q)ISOLINUX_BIN=$(ISOLINUX_BIN) LDLINUX_C32=$(LDLINUX_C32) \
-           VERSION="$(VERSION)" bash util/geniso -o $@ $<
-
-# rule to make a floppy emulation ISO boot image
-NON_AUTO_MEDIA += liso
-%liso: %lkrn util/geniso
-       $(QM)$(ECHO) "  [GENISO] $@"
-       $(Q)VERSION="$(VERSION)" bash util/geniso -l -o $@ $<
-
-# rule to make a syslinux floppy image (mountable, bootable)
-NON_AUTO_MEDIA += sdsk
-%sdsk: %lkrn util/gensdsk
-       $(QM)$(ECHO) "  [GENSDSK] $@"
-       $(Q)bash util/gensdsk $@ $<
+$(BIN)/%.iso $(BIN)/%.sdsk: $(BIN)/%.lkrn util/genfsimg
+       $(QM)$(ECHO) "  [GENFSIMG] $@"
+       $(Q)util/genfsimg -o $@ $<
 
 # rule to write disk images to /dev/fd0
 NON_AUTO_MEDIA += fd0
diff --git a/src/util/genefidsk b/src/util/genefidsk
deleted file mode 100755 (executable)
index 7064f99..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-#!/bin/sh
-#
-# Generate an EFI bootable disk image
-
-set -e
-
-function help() {
-       echo "Usage: ${0} [OPTIONS] <ipxe.efi>"
-       echo
-       echo "where OPTIONS are:"
-       echo " -h       Show this help"
-       echo " -b       Specify boot file name (e.g. bootx64.efi)"
-       echo " -o FILE  Save disk image to file"
-}
-
-BOOT=bootx64.efi
-
-while getopts "hb:o:" opt; do
-       case ${opt} in
-               h)
-                       help
-                       exit 0
-                       ;;
-               b)
-                       BOOT="${OPTARG}"
-                       ;;
-               o)
-                       OUT="${OPTARG}"
-                       ;;
-       esac
-done
-
-shift $((OPTIND - 1))
-IN=$1
-
-if [ -z "${IN}" ]; then
-       echo "${0}: no input file given" >&2
-       help
-       exit 1
-fi
-
-if [ -z "${OUT}" ]; then
-       echo "${0}: no output file given" >&2
-       help
-       exit 1
-fi
-
-# Create sparse output file
-rm -f ${OUT}
-truncate -s 1440K ${OUT}
-
-# Format disk
-mformat -i ${OUT} -f 1440 ::
-
-# Create directory structure
-mmd -i ${OUT} ::efi
-mmd -i ${OUT} ::efi/boot
-
-# Copy bootable image
-mcopy -i ${OUT} ${IN} ::efi/boot/${BOOT}
diff --git a/src/util/genfsimg b/src/util/genfsimg
new file mode 100755 (executable)
index 0000000..e49d4d7
--- /dev/null
@@ -0,0 +1,253 @@
+#!/bin/sh
+#
+# Generate a filesystem-based image
+
+set -e
+set -u
+
+# Print usage message
+#
+help() {
+    echo "usage: ${0} [OPTIONS] foo.lkrn|foo.efi [bar.lkrn|bar.efi,...]"
+    echo
+    echo "where OPTIONS are:"
+    echo " -h       show this help"
+    echo " -o FILE  save image to file"
+    echo " -p PAD   pad filesystem (in kB)"
+}
+
+# Get hex word from binary file
+#
+get_word() {
+    local FILENAME
+    local OFFSET
+
+    FILENAME="${1}"
+    OFFSET="${2}"
+
+    od -j "${OFFSET}" -N 2 -A n -t x1 -- "${FILENAME}" | tr -d " "
+}
+
+# Get appropriate EFI boot filename for CPU architecture
+#
+efi_boot_name() {
+    local FILENAME
+    local PESIG
+    local ARCH
+
+    FILENAME="${1}"
+
+    PESIG=$(get_word "${FILENAME}" 192)
+    if [ "${PESIG}" != "5045" ] ; then
+       echo "${FILENAME}: not an EFI executable" >&2
+       exit 1
+    fi
+    ARCH=$(get_word "${FILENAME}" 196)
+    case "${ARCH}" in
+       "4c01" )
+           echo "BOOTIA32.EFI"
+           ;;
+       "6486" )
+           echo "BOOTX64.EFI"
+           ;;
+       "c201" )
+           echo "BOOTARM.EFI"
+           ;;
+       "64aa" )
+           echo "BOOTAA64.EFI"
+           ;;
+       * )
+           echo "${FILENAME}: unrecognised EFI architecture ${ARCH}" >&2
+           exit 1
+    esac
+}
+
+# Copy syslinux file
+#
+copy_syslinux_file() {
+    local FILENAME
+    local DESTDIR
+    local SRCDIR
+
+    FILENAME="${1}"
+    DESTDIR="${2}"
+
+    for SRCDIR in \
+       /usr/lib/syslinux \
+       /usr/lib/syslinux/bios \
+       /usr/lib/syslinux/modules/bios \
+       /usr/share/syslinux \
+       /usr/share/syslinux/bios \
+       /usr/share/syslinux/modules/bios \
+       /usr/local/share/syslinux \
+       /usr/local/share/syslinux/bios \
+       /usr/local/share/syslinux/modules/bios \
+       /usr/lib/ISOLINUX \
+       ; do
+       if [ -e "${SRCDIR}/${FILENAME}" ] ; then
+           cp "${SRCDIR}/${FILENAME}" "${DESTDIR}/"
+           break
+       fi
+    done
+}
+
+# Parse command-line options
+#
+OUTFILE=
+PAD=0
+while getopts "hlo:p:" OPTION ; do
+    case "${OPTION}" in
+       h)
+           help
+           exit 0
+           ;;
+       o)
+           OUTFILE="${OPTARG}"
+           ;;
+       p)
+           PAD="${OPTARG}"
+           ;;
+       *)
+           help
+           exit 1
+           ;;
+    esac
+done
+if [ -z "${OUTFILE}" ]; then
+    echo "${0}: no output file given" >&2
+    help
+    exit 1
+fi
+shift $(( OPTIND - 1 ))
+
+# Create temporary working directory
+#
+WORKDIR=$(mktemp -d "${OUTFILE}.XXXXXX")
+ISODIR="${WORKDIR}/iso"
+FATDIR="${WORKDIR}/fat"
+mkdir -p "${ISODIR}" "${FATDIR}"
+
+# Configure output
+#
+case "${OUTFILE}" in
+    *.iso)
+       ISOIMG="${OUTFILE}"
+       FATIMG="${ISODIR}/esp.img"
+       BIOSDIR="${ISODIR}"
+       SYSLINUXCFG="${ISODIR}/isolinux.cfg"
+       ;;
+    *)
+       ISOIMG=
+       FATIMG="${OUTFILE}"
+       BIOSDIR="${FATDIR}"
+       SYSLINUXCFG="${FATDIR}/syslinux.cfg"
+       ;;
+esac
+ISOARGS=
+
+# Locate required tools
+#
+if [ -n "${ISOIMG}" ] ; then
+    MKISOFS=
+    for CMD in genisoimage mkisofs ; do
+       if ${CMD} --version >/dev/null 2>/dev/null ; then
+           MKISOFS="${CMD}"
+           break
+       fi
+    done
+    if [ -z "${MKISOFS}" ] ; then
+       echo "${0}: cannot find mkisofs or equivalent" >&2
+       exit 1
+    fi
+fi
+
+# Copy files to temporary working directory
+#
+LKRN=
+EFI=
+for FILENAME ; do
+    case "${FILENAME}" in
+       *.lkrn)
+           DESTDIR="${BIOSDIR}"
+           DESTFILE=$(basename "${FILENAME}")
+           if [ -z "${LKRN}" ] ; then
+               echo "SAY iPXE boot image" > "${SYSLINUXCFG}"
+               echo "TIMEOUT 30" >> "${SYSLINUXCFG}"
+               echo "DEFAULT ${DESTFILE}" >> "${SYSLINUXCFG}"
+           fi
+           echo "LABEL ${DESTFILE}" >> "${SYSLINUXCFG}"
+           echo " KERNEL ${DESTFILE}" >> "${SYSLINUXCFG}"
+           LKRN=1
+           ;;
+       *.efi)
+           DESTDIR="${FATDIR}/EFI/BOOT"
+           DESTFILE=$(efi_boot_name "${FILENAME}")
+           if [ -z "${EFI}" ] ; then
+               mkdir -p "${DESTDIR}"
+           fi
+           EFI=1
+           ;;
+       *)
+           echo "${0}: unrecognised input filename ${FILENAME}" >&2
+           help
+           exit 1
+           ;;
+    esac
+    if [ -e "${DESTDIR}/${DESTFILE}" ] ; then
+       echo "${0}: duplicate ${DESTFILE} from ${FILENAME}" >&2
+       exit 1
+    fi
+    cp "${FILENAME}" "${DESTDIR}/${DESTFILE}"
+done
+
+# Configure ISO image, if applicable
+#
+# Note that the BIOS boot files are required even for an EFI-only ISO,
+# since isohybrid will refuse to work without them.
+#
+if [ -n "${ISOIMG}" ] ; then
+    copy_syslinux_file "isolinux.bin" "${ISODIR}"
+    copy_syslinux_file "ldlinux.c32" "${ISODIR}" || true
+    ISOARGS="${ISOARGS} -no-emul-boot -eltorito-boot isolinux.bin"
+    ISOARGS="${ISOARGS} -boot-load-size 4 -boot-info-table"
+    if [ -n "${EFI}" ] ; then
+       ISOARGS="${ISOARGS} -eltorito-alt-boot -no-emul-boot -efi-boot esp.img"
+    else
+       FATIMG=
+    fi
+fi
+
+# Create FAT filesystem image, if applicable
+#
+if [ -n "${FATIMG}" ] ; then
+    FATSIZE=$(du -s -k ${FATDIR} | cut -f1)
+    FATSIZE=$(( FATSIZE + PAD + 256 ))
+    touch "${FATIMG}"
+    if [ "${FATSIZE}" -le "1440" ] ; then
+       truncate -s 1440K "${FATIMG}"
+       mformat -f 1440 -i "${FATIMG}" ::
+    else
+       truncate -s "${FATSIZE}K" "${FATIMG}"
+       mformat -i "${FATIMG}" ::
+    fi
+    mcopy -i "${FATIMG}" -s "${FATDIR}"/* ::
+    if [ "${BIOSDIR}" = "${FATDIR}" ] ; then
+       syslinux "${FATIMG}"
+    fi
+fi
+
+# Create ISO filesystem image, if applicable
+#
+if [ -n "${ISOIMG}" ] ; then
+    "${MKISOFS}" -quiet -volid "iPXE" -preparer "iPXE build system" \
+           -appid "iPXE - Open Source Network Boot Firmware" \
+           -publisher "ipxe.org" -sysid "iPXE" -J -R -o "${ISOIMG}" \
+           ${ISOARGS} "${ISODIR}"
+    if isohybrid --version >/dev/null 2>/dev/null ; then
+       isohybrid "${ISOIMG}"
+    fi
+fi
+
+# Clean up temporary working directory
+#
+rm -rf "${WORKDIR}"
diff --git a/src/util/geniso b/src/util/geniso
deleted file mode 100755 (executable)
index ff090d4..0000000
+++ /dev/null
@@ -1,141 +0,0 @@
-#!/bin/bash
-#
-# Generate a isolinux ISO boot image
-
-function help() {
-       echo "usage: ${0} [OPTIONS] foo.lkrn [bar.lkrn,...]"
-       echo
-       echo "where OPTIONS are:"
-       echo " -h       show this help"
-       echo " -l       build legacy image with floppy emulation"
-       echo " -o FILE  save iso image to file"
-}
-
-LEGACY=0
-FIRST=""
-
-while getopts "hlo:" opt; do
-       case ${opt} in
-               h)
-                       help
-                       exit 0
-                       ;;
-               l)
-                       LEGACY=1
-                       ;;
-               o)
-                       OUT="${OPTARG}"
-                       ;;
-       esac
-done
-
-shift $((OPTIND - 1))
-
-if [ -z "${OUT}" ]; then
-       echo "${0}: no output file given" >&2
-       help
-       exit 1
-fi
-
-# There should either be mkisofs or the compatible genisoimage program
-for command in genisoimage mkisofs; do
-       if ${command} --version >/dev/null 2>/dev/null; then
-               mkisofs=(${command})
-               break
-       fi
-done
-
-if [ -z "${mkisofs}" ]; then
-       echo "${0}: mkisofs or genisoimage not found, please install or set PATH" >&2
-       exit 1
-fi
-
-dir=$(mktemp -d bin/iso.dir.XXXXXX)
-cfg=${dir}/isolinux.cfg
-
-mkisofs+=(-quiet -l -volid "iPXE" -preparer "iPXE build system"
-       -appid "iPXE ${VERSION} - Open Source Network Boot Firmware"
-       -publisher "http://ipxe.org/" -c boot.cat)
-
-# generate the config
-cat > ${cfg} <<EOF
-# These default options can be changed in the geniso script
-SAY iPXE ISO boot image
-TIMEOUT 30
-EOF
-for f; do
-       if [ ! -r ${f} ]; then
-               echo "${f} does not exist, skipping" >&2
-               continue
-       fi
-       b=$(basename ${f})
-       g=${b%.lkrn}
-       g=${g//[^a-z0-9]}
-       g=${g:0:8}.krn
-       case "${FIRST}" in
-               "")
-                       echo "DEFAULT ${b}"
-                       FIRST=${g}
-                       ;;
-       esac
-       echo "LABEL ${b}"
-       echo " KERNEL ${g}"
-       cp ${f} ${dir}/${g}
-done >> ${cfg}
-
-case "${LEGACY}" in
-       1)
-               # check for mtools
-               case "$(mtools -V)" in
-                       Mtools\ version\ 3.9.9*|Mtools\ version\ 3.9.1[0-9]*|[mM]tools\ *\ [4-9].*)
-                               ;;
-                       *)
-                               echo "Mtools version 3.9.9 or later is required" >&2
-                               exit 1
-                               ;;
-               esac
-
-               # generate floppy image
-               img=${dir}/boot.img
-               mformat -f 1440 -C -i ${img} ::
-
-               # copy lkrn file to floppy image
-               for f in ${dir}/*.krn; do
-                       mcopy -m -i ${img} ${f} ::$(basename ${g})
-                       rm -f ${f}
-               done
-
-               # copy config file to floppy image
-               mcopy -i ${img} ${cfg} ::syslinux.cfg
-               rm -f ${cfg}
-
-               # write syslinux bootloader to floppy image
-               if ! syslinux ${img}; then
-                       echo "${0}: failed writing syslinux to floppy image ${img}" >&2
-                       exit 1
-               fi
-
-               # generate the iso image
-               "${mkisofs[@]}" -b boot.img -output ${OUT} ${dir}
-               ;;
-       0)
-               # copy isolinux bootloader
-               cp ${ISOLINUX_BIN} ${dir}
-
-               # syslinux 6.x needs a file called ldlinux.c32
-               if [ -n "${LDLINUX_C32}" -a -s "${LDLINUX_C32}" ]; then
-                       cp ${LDLINUX_C32} ${dir}
-               fi
-
-               # generate the iso image
-               "${mkisofs[@]}" -b isolinux.bin -no-emul-boot -boot-load-size 4 -boot-info-table -output ${OUT} ${dir}
-
-               # isohybrid will be used if available
-               if isohybrid --version >/dev/null 2>/dev/null; then
-                       isohybrid ${OUT} >/dev/null
-               fi
-               ;;
-esac
-
-# clean up temporary dir
-rm -fr ${dir}
diff --git a/src/util/gensdsk b/src/util/gensdsk
deleted file mode 100755 (executable)
index fe302d5..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-#!/bin/bash
-#
-# Generate a syslinux floppy that loads a iPXE image
-#
-# gensdsk foo.sdsk foo.lkrn
-#
-# the floppy image is the first argument
-#   followed by list of .lkrn images
-#
-
-case $# in
-0|1)
-       echo Usage: $0 foo.sdsk foo.lkrn ...
-       exit 1
-       ;;
-esac
-case "`mtools -V`" in
-Mtools\ version\ 3.9.9*|Mtools\ version\ 3.9.1[0-9]*|[mM]tools\ *\ [4-9].*)
-       ;;
-*)
-       echo Mtools version 3.9.9 or later is required
-       exit 1
-       ;;
-esac
-img=$1
-shift
-dir=`mktemp -d bin/sdsk.dir.XXXXXX`
-
-mformat -f 1440 -C -i $img ::
-cfg=$dir/syslinux.cfg
-cat > $cfg <<EOF
-
-# These default options can be changed in the gensdsk script
-TIMEOUT 30
-EOF
-first=
-for f
-do
-       if [ ! -r $f ]
-       then
-               echo $f does not exist, skipping 1>&2
-               continue
-       fi
-       # shorten name for 8.3 filesystem
-       b=$(basename $f)
-       g=${b%.lkrn}
-       g=${g//[^a-z0-9]}
-       g=${g:0:8}.krn
-       case "$first" in
-       "")
-               echo DEFAULT $b
-               ;;
-       esac
-       first=$g
-       echo LABEL $b
-       echo "" KERNEL $g
-       mcopy -m -i $img $f ::$g
-done >> $cfg
-mcopy -i $img $cfg ::syslinux.cfg
-if ! syslinux $img
-then
-       exit 1
-fi
-
-rm -fr $dir