root/build-tools/patch-iso
M. Vefa Bicakci 1a9872ca9d patch-iso: Fix up paths
Commit c8c75e81b5 ("relocate /pxeboot to /var/pxeboot", 2021-12-15)
inadvertently introduced a few bugs to patch-iso that prevent successful
execution of this script when a patch with pxe-network-installer is
attempted to be used. This is necessary, for example, to be able to
patch kernel and initial RAM file system images in an ISO image.

Here is an example for the error messages:

  + cp --preserve=all pxeboot/pxelinux.0 pxeboot/menu.c32 \
    pxeboot/chain.c32 .../patchiso_build_XXXXXX/var/pxeboot/
  cp: target '.../patchiso_build_XXXXXX/var/pxeboot/' \
    is not a directory

This commit fixes the paths used by patch-iso so that such errors are
not encountered.

Verification:
- patch-iso is successfully executed against a patch file that includes
  a newer pxe-network-installer package.

Closes-Bug: 1968566

Change-Id: I4606d062b45ed03b64f514131d3d6e27434e7675
Signed-off-by: M. Vefa Bicakci <vefa.bicakci@windriver.com>
2022-04-11 09:25:08 -04:00

428 lines
11 KiB
Bash
Executable File

#!/bin/bash
#
# Copyright (c) 2018-2020 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
# Utility for adding patches to an unpatched ISO
#
source "$(dirname $0)/image-utils.sh"
if [ -z "${MY_REPO}" ]; then
echo "Required environment variable MY_REPO is not set"
exit 1
fi
if [ -z "${MY_WORKSPACE}" ]; then
echo "Required environment variable MY_WORKSPACE is not set"
exit 1
fi
STX_DIR=${MY_REPO}/stx
SETUP_PATCH_REPO=${STX_DIR}/update/extras/scripts/setup_patch_repo.sh
if [ ! -x ${SETUP_PATCH_REPO} ]; then
echo "Cannot find or execute ${SETUP_PATCH_REPO}"
exit 1
fi
# Create temp dir if necessary
export TMPDIR="$MY_WORKSPACE/tmp"
mkdir -p $TMPDIR
REPO_UPGRADES_DIR=${STX_DIR}/metal/bsp-files/upgrades
RELEASE_INFO="$(get_release_info)"
if [ $? -ne 0 ]; then
echo "ERROR: failed to find a release info file."
exit 1
fi
PLATFORM_RELEASE=$(source $RELEASE_INFO && echo $PLATFORM_RELEASE)
function usage() {
echo ""
echo "Usage: "
echo " $(basename $0) -i <input bootimage.iso> -o <output bootimage.iso> [ -u ] <patch> ..."
echo " -i <file>: Specify input ISO file"
echo " -o <file>: Specify output ISO file"
echo " -u : Update with upgrades files from ${REPO_UPGRADES_DIR}"
echo ""
}
function extract_pkg_from_patch_repo() {
local repodir=${BUILDDIR}/patches
local pkgname=$1
local pkgfile=$(repoquery --disablerepo=* --repofrompath local,${repodir} --enablerepo=local --location -q ${pkgname})
if [ -z "${pkgfile}" ]; then
return 1
fi
rpm2cpio ${pkgfile/file://} | cpio -idmv
if [ $? -ne 0 ]; then
echo "Failed to extract $pkgname files from ${pkgfile/file://}"
exit 1
fi
}
declare INPUT_ISO=
declare OUTPUT_ISO=
declare ORIG_PWD=$PWD
declare DO_UPGRADES=1
while getopts "i:o:u" opt; do
case $opt in
i)
INPUT_ISO=$OPTARG
;;
o)
OUTPUT_ISO=$OPTARG
;;
u)
DO_UPGRADES=0
;;
*)
usage
exit 1
;;
esac
done
if [ -z "$INPUT_ISO" -o -z "$OUTPUT_ISO" ]; then
usage
exit 1
fi
if [ ! -f ${INPUT_ISO} ]; then
echo "Input file does not exist: ${INPUT_ISO}"
exit 1
fi
if [ -f ${OUTPUT_ISO} ]; then
echo "Output file already exists: ${OUTPUT_ISO}"
exit 1
fi
shift $((OPTIND-1))
if [ $# -le 0 ]; then
usage
exit
fi
for pf in $@; do
if [ ! -f $pf ]; then
echo "Patch file $pf does not exist"
exit 1
fi
if [[ ! $pf =~ \.patch$ ]]; then
echo "Specified file $pf does not have .patch extension"
exit 1
fi
done
declare MNTDIR=
declare BUILDDIR=
declare WORKDIR=
function check_requirements {
local -a required_utils=(
rsync
mkisofs
isohybrid
implantisomd5
)
if [ $UID -ne 0 ]; then
# If running as non-root user, additional utils are required
required_utils+=(
guestmount
guestunmount
)
fi
local -i missing=0
for req in ${required_utils[@]}; do
which ${req} >&/dev/null
if [ $? -ne 0 ]; then
echo "Unable to find required utility: ${req}" >&2
let missing++
fi
done
if [ ${missing} -gt 0 ]; then
echo "One or more required utilities are missing. Aborting..." >&2
exit 1
fi
}
function mount_iso {
if [ $UID -eq 0 ]; then
# Mount the ISO
mount -o loop ${INPUT_ISO} ${MNTDIR}
if [ $? -ne 0 ]; then
echo "Failed to mount ${INPUT_ISO}" >&2
exit 1
fi
else
# As non-root user, mount the ISO using guestmount
guestmount -a ${INPUT_ISO} -m /dev/sda1 --ro ${MNTDIR}
rc=$?
if [ $rc -ne 0 ]; then
# Add a retry
echo "Call to guestmount failed with rc=$rc. Retrying once..."
guestmount -a ${INPUT_ISO} -m /dev/sda1 --ro ${MNTDIR}
rc=$?
if [ $rc -ne 0 ]; then
echo "Call to guestmount failed with rc=$rc. Aborting..."
exit $rc
fi
fi
fi
}
function unmount_iso {
if [ $UID -eq 0 ]; then
umount ${MNTDIR}
else
guestunmount ${MNTDIR}
fi
rmdir ${MNTDIR}
}
function cleanup() {
if [ -n "$MNTDIR" -a -d "$MNTDIR" ]; then
unmount_iso
fi
if [ -n "$BUILDDIR" -a -d "$BUILDDIR" ]; then
\rm -rf $BUILDDIR
fi
if [ -n "$WORKDIR" -a -d "$WORKDIR" ]; then
\rm -rf $WORKDIR
fi
}
trap cleanup EXIT
MNTDIR=$(mktemp -d -p $PWD patchiso_mnt_XXXXXX)
if [ -z "${MNTDIR}" -o ! -d ${MNTDIR} ]; then
echo "Failed to create mntdir. Aborting..."
exit $rc
fi
BUILDDIR=$(mktemp -d -p $PWD patchiso_build_XXXXXX)
if [ -z "${BUILDDIR}" -o ! -d ${BUILDDIR} ]; then
echo "Failed to create builddir. Aborting..."
exit $rc
fi
# Mount the ISO
mount_iso
rsync -a ${MNTDIR}/ ${BUILDDIR}/
rc=$?
if [ $rc -ne 0 ]; then
echo "Call to rsync ISO content. Aborting..."
exit $rc
fi
unmount_iso
# Setup the patch repo
${SETUP_PATCH_REPO} -o ${BUILDDIR}/patches $@
rc=$?
if [ $rc -ne 0 ]; then
echo "Call to $(basename ${SETUP_PATCH_REPO}) failed with rc=$rc. Aborting..."
exit $rc
fi
# Look for components that need modification
#extract_pkg_from_patch_repo
WORKDIR=$(mktemp -d -p $PWD patchiso_work_XXXXXX)
if [ -z "${WORKDIR}" -o ! -d ${WORKDIR} ]; then
echo "Failed to create workdir. Aborting..."
exit $rc
fi
\cd ${WORKDIR}
\mkdir extract
\cd extract
# Changes to copied files here must also be reflected in build-iso
extract_pkg_from_patch_repo platform-kickstarts
if [ $? -eq 0 ]; then
# Replace files
\rm -f ${BUILDDIR}/*ks.cfg &&
\cp --preserve=all var/www/pages/feed/rel-*/*.cfg ${BUILDDIR}/ &&
\cp --preserve=all ${BUILDDIR}/controller_ks.cfg ${BUILDDIR}/ks.cfg
if [ $? -ne 0 ]; then
echo "Failed to copy extracted kickstarts"
exit 1
fi
fi
\cd ${WORKDIR}
\rm -rf extract
\mkdir extract
\cd extract
extract_pkg_from_patch_repo platform-kickstarts-pxeboot
if [ $? -eq 0 ]; then
# Replace files
\rm -f ${BUILDDIR}/var/pxeboot/pxeboot_controller.cfg \
${BUILDDIR}/var/pxeboot/pxeboot_smallsystem.cfg \
${BUILDDIR}/var/pxeboot/pxeboot_smallsystem_lowlatency.cfg &&
\cp --preserve=all pxeboot/* ${BUILDDIR}/var/pxeboot/
if [ $? -ne 0 ]; then
echo "Failed to copy extracted pxeboot kickstarts"
exit 1
fi
fi
\cd ${WORKDIR}
\rm -rf extract
\mkdir extract
\cd extract
extract_pkg_from_patch_repo pxe-network-installer
if [ $? -eq 0 ]; then
# Replace files
\rm -f ${BUILDDIR}/pxeboot/pxelinux.0 \
${BUILDDIR}/pxeboot/menu.c32 \
${BUILDDIR}/pxeboot/chain.c32 &&
\cp --preserve=all var/pxeboot/pxelinux.0 var/pxeboot/menu.c32 var/pxeboot/chain.c32 ${BUILDDIR}/pxeboot/
if [ $? -ne 0 ]; then
echo "Error: Could not copy all files from installer"
exit 1
fi
\rm -f ${BUILDDIR}/LiveOS/squashfs.img &&
\cp --preserve=all var/www/pages/feed/rel-*/LiveOS/squashfs.img ${BUILDDIR}/LiveOS/
if [ $? -ne 0 ]; then
echo "Error: Could not copy squashfs from LiveOS"
exit 1
fi
# Replace vmlinuz and initrd.img with our own pre-built ones
\rm -f \
${BUILDDIR}/vmlinuz \
${BUILDDIR}/images/pxeboot/vmlinuz \
${BUILDDIR}/initrd.img \
${BUILDDIR}/images/pxeboot/initrd.img &&
\cp --preserve=all var/pxeboot/rel-*/installer-bzImage_1.0 \
${BUILDDIR}/vmlinuz &&
\cp --preserve=all var/pxeboot/rel-*/installer-bzImage_1.0 \
${BUILDDIR}/images/pxeboot/vmlinuz &&
\cp --preserve=all var/pxeboot/rel-*/installer-intel-x86-64-initrd_1.0 \
${BUILDDIR}/initrd.img &&
\cp --preserve=all var/pxeboot/rel-*/installer-intel-x86-64-initrd_1.0 \
${BUILDDIR}/images/pxeboot/initrd.img
if [ $? -ne 0 ]; then
echo "Error: Failed to copy installer images"
exit 1
fi
fi
\cd ${WORKDIR}
\rm -rf extract
\mkdir extract
\cd extract
extract_pkg_from_patch_repo grub2-efi-x64-pxeboot
if [ $? -eq 0 ]; then
# Replace files
\rm -f ${BUILDDIR}/var/pxeboot/EFI/grubx64.efi &&
\cp --preserve=all pxeboot/EFI/grubx64.efi ${BUILDDIR}/var/pxeboot/EFI/
if [ $? -ne 0 ]; then
echo "Error: Failed to copy grub2-efi-x64-pxeboot files"
exit 1
fi
fi
\cd ${WORKDIR}
\rm -rf extract
\mkdir extract
\cd extract
extract_pkg_from_patch_repo grub2-common
if [ $? -eq 0 ]; then
# Replace files
for f in usr/lib/grub/x86_64-efi/*; do
f_base=$(basename $f)
\rm -f ${BUILDDIR}/var/pxeboot/EFI/$f_base &&
\cp --preserve=all ${f} ${BUILDDIR}/var/pxeboot/EFI/
if [ $? -ne 0 ]; then
echo "Error: Failed to copy grub2-common files"
exit 1
fi
done
fi
\cd ${WORKDIR}
\rm -rf extract
\mkdir extract
\cd extract
extract_pkg_from_patch_repo grub2-efi-x64-modules
if [ $? -eq 0 ]; then
# Replace files
for f in usr/lib/grub/x86_64-efi/*; do
f_base=$(basename $f)
\rm -f ${BUILDDIR}/var/pxeboot/EFI/$f_base &&
\cp --preserve=all ${f} ${BUILDDIR}/var/pxeboot/EFI/
if [ $? -ne 0 ]; then
echo "Error: Failed to copy grub2-efi-x64-modules files"
exit 1
fi
done
fi
\cd ${WORKDIR}
\rm -rf extract
\cd ${ORIG_PWD}
if [ ${DO_UPGRADES} -eq 0 ]; then
# Changes to copied files here must also be reflected in build-iso
echo "Updating upgrade support files"
ISO_UPGRADES_DIR="${BUILDDIR}/upgrades"
\rm -rf ${ISO_UPGRADES_DIR}
\mkdir ${ISO_UPGRADES_DIR}
\cp ${REPO_UPGRADES_DIR}/* ${ISO_UPGRADES_DIR}
sed -i "s/xxxSW_VERSIONxxx/${PLATFORM_RELEASE}/g" ${ISO_UPGRADES_DIR}/metadata.xml
chmod +x ${ISO_UPGRADES_DIR}/*.sh
# Write the version out (used in upgrade scripts - this is the same as SW_VERSION)
echo "VERSION=$PLATFORM_RELEASE" > ${ISO_UPGRADES_DIR}/version
fi
# Rebuild the ISO
mkisofs -o ${OUTPUT_ISO} \
-R -D -A 'oe_iso_boot' -V 'oe_iso_boot' \
-quiet \
-b isolinux.bin -c boot.cat -no-emul-boot \
-boot-load-size 4 -boot-info-table \
-eltorito-alt-boot \
-e images/efiboot.img \
-no-emul-boot \
${BUILDDIR}
isohybrid --uefi ${OUTPUT_ISO}
implantisomd5 ${OUTPUT_ISO}
# Sign the .iso with the developer private key
# Signing with the formal key is only to be done for customer release
# and is a manual step afterwards, as with the GA ISO
openssl dgst -sha256 \
-sign ${MY_REPO}/build-tools/signing/dev-private-key.pem \
-binary \
-out ${OUTPUT_ISO/%.iso/.sig} \
${OUTPUT_ISO}
rc=$?
if [ $rc -ne 0 ]; then
echo "Call to $(basename ${SETUP_PATCH_REPO}) failed with rc=$rc. Aborting..."
exit $rc
fi
echo "Patched ISO: ${OUTPUT_ISO}"