mirror of
https://github.com/ipxe/ipxe
synced 2026-05-16 15:00:48 +03:00
[build] Create util/gensrvimg for building network boot server images
In the spirit of util/genfsimg, create a script util/gensrvimg that can be used to install compiled iPXE binaries to a directory tree suitable for copying to a TFTP or HTTP server. The script detects the CPU architecture for each input file and installs it into the appropriate subdirectory. Top-level symlinks are created for each filename, with earlier files taking precedence. Signed binaries are detected and automatically placed into a Secure Boot specific subdirectory, thereby allowing the reduced-feature Secure Boot binaries to coexist with full-feature binaries in a single installation directory tree. An iPXE shim may be specified and will be automatically installed alongside the signed binaries, with the relevant symlink created for each signed binary. Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
@@ -360,7 +360,7 @@ jobs:
|
|||||||
shimx64.efi
|
shimx64.efi
|
||||||
|
|
||||||
combine:
|
combine:
|
||||||
name: BIOS + UEFI
|
name: Combine
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs:
|
needs:
|
||||||
- bios
|
- bios
|
||||||
@@ -370,7 +370,10 @@ jobs:
|
|||||||
container:
|
container:
|
||||||
image: ghcr.io/ipxe/ipxe-builder-utils
|
image: ghcr.io/ipxe/ipxe-builder-utils
|
||||||
env:
|
env:
|
||||||
binaries: >-
|
efishims: >-
|
||||||
|
-e shim/shimaa64.efi
|
||||||
|
-e shim/shimx64.efi
|
||||||
|
fsbinaries: >-
|
||||||
bin-x86_64-pcbios/${DRIVERS}.lkrn
|
bin-x86_64-pcbios/${DRIVERS}.lkrn
|
||||||
bin-arm32-efi/${DRIVERS}.efi
|
bin-arm32-efi/${DRIVERS}.efi
|
||||||
bin-arm64-efi/${DRIVERS}.efi
|
bin-arm64-efi/${DRIVERS}.efi
|
||||||
@@ -379,6 +382,38 @@ jobs:
|
|||||||
bin-riscv32-efi/${DRIVERS}.efi
|
bin-riscv32-efi/${DRIVERS}.efi
|
||||||
bin-riscv64-efi/${DRIVERS}.efi
|
bin-riscv64-efi/${DRIVERS}.efi
|
||||||
bin-x86_64-efi/${DRIVERS}.efi
|
bin-x86_64-efi/${DRIVERS}.efi
|
||||||
|
srvbinaries: >-
|
||||||
|
bin/ipxe.pxe
|
||||||
|
bin/ipxe-legacy.pxe
|
||||||
|
bin/undionly.kpxe
|
||||||
|
bin-arm32-efi/ipxe.efi
|
||||||
|
bin-arm32-efi/ipxe-legacy.efi
|
||||||
|
bin-arm32-efi/snponly.efi
|
||||||
|
bin-arm64-efi/ipxe.efi
|
||||||
|
bin-arm64-efi/ipxe-legacy.efi
|
||||||
|
bin-arm64-efi/snponly.efi
|
||||||
|
bin-arm64-efi-sb/ipxe.efi
|
||||||
|
bin-arm64-efi-sb/snponly.efi
|
||||||
|
bin-i386-efi/ipxe.efi
|
||||||
|
bin-i386-efi/ipxe-legacy.efi
|
||||||
|
bin-i386-efi/snponly.efi
|
||||||
|
bin-loong64-efi/ipxe.efi
|
||||||
|
bin-loong64-efi/ipxe-legacy.efi
|
||||||
|
bin-loong64-efi/snponly.efi
|
||||||
|
bin-riscv32-efi/ipxe.efi
|
||||||
|
bin-riscv32-efi/ipxe-legacy.efi
|
||||||
|
bin-riscv32-efi/snponly.efi
|
||||||
|
bin-riscv64-efi/ipxe.efi
|
||||||
|
bin-riscv64-efi/ipxe-legacy.efi
|
||||||
|
bin-riscv64-efi/snponly.efi
|
||||||
|
bin-x86_64-efi/ipxe.efi
|
||||||
|
bin-x86_64-efi/ipxe-legacy.efi
|
||||||
|
bin-x86_64-efi/snponly.efi
|
||||||
|
bin-x86_64-efi-sb/ipxe.efi
|
||||||
|
bin-x86_64-efi-sb/snponly.efi
|
||||||
|
bin-x86_64-pcbios/ipxe.pxe
|
||||||
|
bin-x86_64-pcbios/ipxe-legacy.pxe
|
||||||
|
bin-x86_64-pcbios/undionly.kpxe
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
- name: Check out code
|
- name: Check out code
|
||||||
@@ -387,9 +422,9 @@ jobs:
|
|||||||
- name: Download
|
- name: Download
|
||||||
uses: actions/download-artifact@v7
|
uses: actions/download-artifact@v7
|
||||||
with:
|
with:
|
||||||
pattern: "{bin-x86_64-pcbios,bin-*-efi,bin-*-efi-sb,shim}"
|
pattern: "{bin,bin-x86_64-pcbios,bin-*-efi,bin-*-efi-sb,shim}"
|
||||||
|
|
||||||
- name: Combine
|
- name: ISO + USB
|
||||||
run: |
|
run: |
|
||||||
# Provide an editable placeholder autoexec.ipxe for the USB image
|
# Provide an editable placeholder autoexec.ipxe for the USB image
|
||||||
cat > autoexec.ipxe <<'EOF'
|
cat > autoexec.ipxe <<'EOF'
|
||||||
@@ -400,11 +435,16 @@ jobs:
|
|||||||
&& shell || autoboot
|
&& shell || autoboot
|
||||||
EOF
|
EOF
|
||||||
for DRIVERS in ipxe ipxe-legacy ; do
|
for DRIVERS in ipxe ipxe-legacy ; do
|
||||||
./src/util/genfsimg -o ${DRIVERS}.iso ${{ env.binaries }}
|
./src/util/genfsimg -o ${DRIVERS}.iso ${{ env.fsbinaries }}
|
||||||
./src/util/genfsimg -o ${DRIVERS}.usb -s autoexec.ipxe \
|
./src/util/genfsimg -o ${DRIVERS}.usb -s autoexec.ipxe \
|
||||||
${{ env.binaries }}
|
${{ env.fsbinaries }}
|
||||||
done
|
done
|
||||||
|
|
||||||
|
- name: Server
|
||||||
|
run: |
|
||||||
|
./src/util/gensrvimg -o ipxeboot.tar.gz ${{ env.efishims }} \
|
||||||
|
${{ env.srvbinaries }}
|
||||||
|
|
||||||
- name: Upload
|
- name: Upload
|
||||||
uses: actions/upload-artifact@v6
|
uses: actions/upload-artifact@v6
|
||||||
with:
|
with:
|
||||||
@@ -415,6 +455,7 @@ jobs:
|
|||||||
ipxe.usb
|
ipxe.usb
|
||||||
ipxe-legacy.iso
|
ipxe-legacy.iso
|
||||||
ipxe-legacy.usb
|
ipxe-legacy.usb
|
||||||
|
ipxeboot.tar.gz
|
||||||
|
|
||||||
netboot:
|
netboot:
|
||||||
name: Netboot
|
name: Netboot
|
||||||
|
|||||||
@@ -49,6 +49,8 @@ get_word() {
|
|||||||
#
|
#
|
||||||
efi_boot_name() {
|
efi_boot_name() {
|
||||||
local FILENAME
|
local FILENAME
|
||||||
|
local MZSIG
|
||||||
|
local PEOFF
|
||||||
local PESIG
|
local PESIG
|
||||||
local ARCH
|
local ARCH
|
||||||
|
|
||||||
|
|||||||
Executable
+325
@@ -0,0 +1,325 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# Generate a network bootable directory image
|
||||||
|
|
||||||
|
set -e
|
||||||
|
set -u
|
||||||
|
|
||||||
|
# Print usage message
|
||||||
|
#
|
||||||
|
help() {
|
||||||
|
echo "usage: ${0} [OPTIONS] foo.[k]pxe|foo.efi [bar.[k]pxe|bar.efi,...]"
|
||||||
|
echo
|
||||||
|
echo "where OPTIONS are:"
|
||||||
|
echo " -h show this help"
|
||||||
|
echo " -a ARCH select default CPU architecture [x86_64]"
|
||||||
|
echo " -d DIR install images to directory"
|
||||||
|
echo " -e SHIM specify an EFI shim helper"
|
||||||
|
echo " -o FILE save image archive to file"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get hex byte from binary file
|
||||||
|
#
|
||||||
|
get_byte() {
|
||||||
|
local FILENAME
|
||||||
|
local OFFSET
|
||||||
|
|
||||||
|
FILENAME="${1}"
|
||||||
|
OFFSET="${2}"
|
||||||
|
|
||||||
|
od -j "${OFFSET}" -N 1 -A n -t x1 -- "${FILENAME}" | tr -d " "
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get hex word from binary file
|
||||||
|
#
|
||||||
|
get_word() {
|
||||||
|
local FILENAME
|
||||||
|
local OFFSET
|
||||||
|
local LSB
|
||||||
|
local MSB
|
||||||
|
|
||||||
|
FILENAME="${1}"
|
||||||
|
OFFSET="${2}"
|
||||||
|
|
||||||
|
LSB=$(get_byte "${FILENAME}" $(( ${OFFSET} + 0 )) )
|
||||||
|
MSB=$(get_byte "${FILENAME}" $(( ${OFFSET} + 1 )) )
|
||||||
|
echo "${MSB}${LSB}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get hex dword from binary file
|
||||||
|
#
|
||||||
|
get_dword() {
|
||||||
|
local FILENAME
|
||||||
|
local OFFSET
|
||||||
|
local LSW
|
||||||
|
local MSW
|
||||||
|
|
||||||
|
FILENAME="${1}"
|
||||||
|
OFFSET="${2}"
|
||||||
|
|
||||||
|
LSW=$(get_word "${FILENAME}" $(( ${OFFSET} + 0 )) )
|
||||||
|
MSW=$(get_word "${FILENAME}" $(( ${OFFSET} + 2 )) )
|
||||||
|
echo "${MSW}${LSW}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get appropriate subdirectory name for CPU architecture from EFI binary
|
||||||
|
#
|
||||||
|
efi_subdir_name() {
|
||||||
|
local FILENAME
|
||||||
|
local MZSIG
|
||||||
|
local PEOFF
|
||||||
|
local PESIG
|
||||||
|
local ARCH
|
||||||
|
local OPTSIG
|
||||||
|
local SECSIZE
|
||||||
|
local SBSUFFIX
|
||||||
|
|
||||||
|
FILENAME="${1}"
|
||||||
|
|
||||||
|
MZSIG=$(get_word "${FILENAME}" 0)
|
||||||
|
if [ "${MZSIG}" != "5a4d" ] ; then
|
||||||
|
echo "${FILENAME}: invalid MZ header" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
PEOFF=$(get_byte "${FILENAME}" 0x3c)
|
||||||
|
PESIG=$(get_word "${FILENAME}" 0x${PEOFF})
|
||||||
|
if [ "${PESIG}" != "4550" ] ; then
|
||||||
|
echo "${FILENAME}: invalid PE header" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
ARCH=$(get_word "${FILENAME}" $(( 0x${PEOFF} + 4 )) )
|
||||||
|
OPTSIG=$(get_word "${FILENAME}" $(( 0x${PEOFF} + 24 )) )
|
||||||
|
case "${OPTSIG}" in
|
||||||
|
"010b" )
|
||||||
|
SECSIZE=$(get_dword "${FILENAME}" $(( 0x${PEOFF} + 156 )) )
|
||||||
|
;;
|
||||||
|
"020b" )
|
||||||
|
SECSIZE=$(get_dword "${FILENAME}" $(( 0x${PEOFF} + 172 )) )
|
||||||
|
;;
|
||||||
|
* )
|
||||||
|
echo "${FILENAME}: unrecognised optional header ${OPTSIG}" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
if [ "${SECSIZE}" != "00000000" ] ; then
|
||||||
|
SBSUFFIX="-sb"
|
||||||
|
else
|
||||||
|
SBSUFFIX=""
|
||||||
|
fi
|
||||||
|
case "${ARCH}" in
|
||||||
|
"014c" )
|
||||||
|
echo "i386${SBSUFFIX}"
|
||||||
|
;;
|
||||||
|
"8664" )
|
||||||
|
echo "x86_64${SBSUFFIX}"
|
||||||
|
;;
|
||||||
|
"01c2" )
|
||||||
|
echo "arm32${SBSUFFIX}"
|
||||||
|
;;
|
||||||
|
"6264" )
|
||||||
|
echo "loong64${SBSUFFIX}"
|
||||||
|
;;
|
||||||
|
"aa64" )
|
||||||
|
echo "arm64${SBSUFFIX}"
|
||||||
|
;;
|
||||||
|
"5064" )
|
||||||
|
echo "riscv64${SBSUFFIX}"
|
||||||
|
;;
|
||||||
|
"5032" )
|
||||||
|
echo "riscv32${SBSUFFIX}"
|
||||||
|
;;
|
||||||
|
* )
|
||||||
|
echo "${FILENAME}: unrecognised EFI architecture ${ARCH}" >&2
|
||||||
|
exit 1
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get appropriate subdirectory name for CPU architecture from iPXE NBP
|
||||||
|
#
|
||||||
|
nbp_subdir_name() {
|
||||||
|
local FILENAME
|
||||||
|
local LJMP
|
||||||
|
local SEGMENT
|
||||||
|
local MAGIC
|
||||||
|
local ARCH
|
||||||
|
|
||||||
|
FILENAME="${1}"
|
||||||
|
|
||||||
|
LJMP=$(get_byte "${FILENAME}" 0)
|
||||||
|
if [ "${LJMP}" != "ea" ] ; then
|
||||||
|
echo "${FILENAME}: invalid LJMP instruction" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
SEGMENT=$(get_word "${FILENAME}" 3)
|
||||||
|
if [ "${SEGMENT}" != "07c0" ] ; then
|
||||||
|
echo "${FILENAME}: invalid LJMP segment" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
MAGIC=$(get_word "${FILENAME}" 6)
|
||||||
|
if [ "${MAGIC}" != "18ae" ] ; then
|
||||||
|
echo "${FILENAME}: invalid iPXE magic" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
ARCH=$(get_byte "${FILENAME}" 5)
|
||||||
|
case "${ARCH}" in
|
||||||
|
"32" )
|
||||||
|
echo "i386"
|
||||||
|
;;
|
||||||
|
"64" )
|
||||||
|
echo "x86_64"
|
||||||
|
;;
|
||||||
|
* )
|
||||||
|
echo "${FILENAME}: unrecognised NBP architecture ${ARCH}" >&2
|
||||||
|
exit 1
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get appropriate subdirectory name for CPU architecture
|
||||||
|
#
|
||||||
|
subdir_name() {
|
||||||
|
local FILENAME
|
||||||
|
local BYTE
|
||||||
|
|
||||||
|
FILENAME="${1}"
|
||||||
|
|
||||||
|
BYTE=$(get_byte "${FILENAME}" 0)
|
||||||
|
case "${BYTE}" in
|
||||||
|
"4d" )
|
||||||
|
efi_subdir_name "${FILENAME}"
|
||||||
|
;;
|
||||||
|
"ea" )
|
||||||
|
nbp_subdir_name "${FILENAME}"
|
||||||
|
;;
|
||||||
|
* )
|
||||||
|
echo "${FILENAME}: unrecognised format" >&2
|
||||||
|
exit 1
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# Parse command-line options
|
||||||
|
#
|
||||||
|
DEFARCH=x86_64
|
||||||
|
OUTDIR=
|
||||||
|
OUTFILE=
|
||||||
|
SHIMAA64=
|
||||||
|
SHIMX64=
|
||||||
|
while getopts "ha:d:e:o:" OPTION ; do
|
||||||
|
case "${OPTION}" in
|
||||||
|
h)
|
||||||
|
help
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
a)
|
||||||
|
DEFARCH="${OPTARG}"
|
||||||
|
;;
|
||||||
|
d)
|
||||||
|
OUTDIR="${OPTARG}"
|
||||||
|
;;
|
||||||
|
e)
|
||||||
|
SHIM="${OPTARG}"
|
||||||
|
SHIMARCH=$(subdir_name "${SHIM}")
|
||||||
|
case "${SHIMARCH}" in
|
||||||
|
arm64* )
|
||||||
|
SHIMAA64="${SHIM}"
|
||||||
|
;;
|
||||||
|
x86_64* )
|
||||||
|
SHIMX64="${SHIM}"
|
||||||
|
;;
|
||||||
|
* )
|
||||||
|
echo "${SHIM}: unsupported shim architecture" >&2
|
||||||
|
exit 1
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
o)
|
||||||
|
OUTFILE="${OPTARG}"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
help
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
if [ -z "${OUTDIR}" -a -z "${OUTFILE}" ] ; then
|
||||||
|
echo "${0}: no output directory or file given" >&2
|
||||||
|
help
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
shift $(( OPTIND - 1 ))
|
||||||
|
if [ $# -eq 0 ] ; then
|
||||||
|
echo "${0}: no input files given" >&2
|
||||||
|
help
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create temporary working directory, if applicable
|
||||||
|
#
|
||||||
|
WORKDIR=
|
||||||
|
if [ -z "${OUTDIR}" ] ; then
|
||||||
|
WORKDIR=$(mktemp -d "${OUTFILE}.XXXXXX")
|
||||||
|
OUTDIR="${WORKDIR}/ipxeboot"
|
||||||
|
fi
|
||||||
|
mkdir -p "${OUTDIR}"
|
||||||
|
|
||||||
|
# Copy files to output directory
|
||||||
|
#
|
||||||
|
for FILENAME ; do
|
||||||
|
SUBDIR=$(subdir_name "${FILENAME}")
|
||||||
|
ARCH="${SUBDIR%-sb}"
|
||||||
|
DESTDIR="${OUTDIR}/${SUBDIR}"
|
||||||
|
BASENAME=$(basename "${FILENAME}")
|
||||||
|
SHIMLINK="${BASENAME%.efi}-shim.efi"
|
||||||
|
mkdir -p "${DESTDIR}"
|
||||||
|
install -m 644 "${FILENAME}" "${DESTDIR}/${BASENAME}"
|
||||||
|
case "${SUBDIR}" in
|
||||||
|
arm64-sb )
|
||||||
|
if [ -n "${SHIMAA64}" ] ; then
|
||||||
|
install -m 644 "${SHIMAA64}" "${DESTDIR}/shimaa64.efi"
|
||||||
|
ln -sfn "shimaa64.efi" "${DESTDIR}/${SHIMLINK}"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
x86_64-sb )
|
||||||
|
if [ -n "${SHIMX64}" ] ; then
|
||||||
|
install -m 644 "${SHIMX64}" "${DESTDIR}/shimx64.efi"
|
||||||
|
ln -sfn "shimx64.efi" "${DESTDIR}/${SHIMLINK}"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
if [ "${ARCH}" = "${DEFARCH}" ] ; then
|
||||||
|
if [ "${ARCH}" = "${SUBDIR}" ] ; then
|
||||||
|
ln -sfn "${SUBDIR}/${BASENAME}" "${OUTDIR}/${BASENAME}"
|
||||||
|
else
|
||||||
|
ln -sfn "${SUBDIR}" "${OUTDIR}/sb"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Create output archive file, if applicable
|
||||||
|
#
|
||||||
|
if [ -n "${OUTFILE}" ] ; then
|
||||||
|
TOPDIR=$(dirname "${OUTDIR}")
|
||||||
|
BASENAME=$(basename "${OUTDIR}")
|
||||||
|
case "${OUTFILE}" in
|
||||||
|
*.tar )
|
||||||
|
tar cf "${OUTFILE}" -C "${TOPDIR}" "${BASENAME}"
|
||||||
|
;;
|
||||||
|
*.tar.gz | *.tgz )
|
||||||
|
tar czf "${OUTFILE}" -C "${TOPDIR}" "${BASENAME}"
|
||||||
|
;;
|
||||||
|
*.tar.bz2 )
|
||||||
|
tar cjf "${OUTFILE}" -C "${TOPDIR}" "${BASENAME}"
|
||||||
|
;;
|
||||||
|
*.tar.xz )
|
||||||
|
tar cJf "${OUTFILE}" -C "${TOPDIR}" "${BASENAME}"
|
||||||
|
;;
|
||||||
|
* )
|
||||||
|
echo "${OUTFILE}: unrecognised archive format" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Clean up temporary working directory
|
||||||
|
#
|
||||||
|
if [ -n "${WORKDIR}" ] ; then
|
||||||
|
rm -rf "${WORKDIR}"
|
||||||
|
fi
|
||||||
Reference in New Issue
Block a user