From 1c1c0099c7e4f6283ba917f3af8d7bc8f2f2e7c3 Mon Sep 17 00:00:00 2001 From: Krzesimir Nowak Date: Mon, 30 Jan 2023 13:41:37 +0100 Subject: [PATCH] build_library: Generate content files for initrd too --- build_library/build_image_util.sh | 14 +++ .../extract-initramfs-from-vmlinuz.sh | 107 ++++++++++++++++++ build_library/prod_image_util.sh | 8 +- 3 files changed, 128 insertions(+), 1 deletion(-) create mode 100755 build_library/extract-initramfs-from-vmlinuz.sh diff --git a/build_library/build_image_util.sh b/build_library/build_image_util.sh index 40fb4e3eda..b399832dcd 100755 --- a/build_library/build_image_util.sh +++ b/build_library/build_image_util.sh @@ -654,6 +654,8 @@ finish_image() { local image_grub="$8" local image_shim="$9" local image_kconfig="${10}" + local image_initrd_contents="${11}" + local image_initrd_contents_wtd="${12}" local install_grub=0 local disk_img="${BUILD_DIR}/${image_name}" @@ -812,6 +814,18 @@ EOF >"${BUILD_DIR}/pcrs/kernel.config" fi + if [[ -n "${image_initrd_contents}" ]] || [[ -n "${image_initrd_contents_wtd}" ]]; then + "${BUILD_LIBRARY_DIR}/extract-initramfs-from-vmlinuz.sh" "${root_fs_dir}/boot/flatcar/vmlinuz-a" "${BUILD_DIR}/tmp_initrd_contents" + if [[ -n "${image_initrd_contents}" ]]; then + write_contents "${BUILD_DIR}/tmp_initrd_contents" "${BUILD_DIR}/${image_initrd_contents}" + fi + + if [[ -n "${image_initrd_contents_wtd}" ]]; then + write_contents_with_technical_details "${BUILD_DIR}/tmp_initrd_contents" "${BUILD_DIR}/${image_initrd_contents_wtd}" + fi + rm -rf "${BUILD_DIR}/tmp_initrd_contents" + fi + rm -rf "${BUILD_DIR}"/configroot cleanup_mounts "${root_fs_dir}" trap - EXIT diff --git a/build_library/extract-initramfs-from-vmlinuz.sh b/build_library/extract-initramfs-from-vmlinuz.sh new file mode 100755 index 0000000000..9c1ffb6952 --- /dev/null +++ b/build_library/extract-initramfs-from-vmlinuz.sh @@ -0,0 +1,107 @@ +#!/bin/bash + +# Does as it says on the tin. +# +# Example: extract-initramfs-from-vmlinuz /boot/flatcar/vmlinuz-a out-dir +# +# This will create one or more out-dir/rootfs-N directories that contain the contents of the initramfs. + +set -euo pipefail +# check for unzstd. Will abort the script with an error message if the tool is not present. +unzstd -V >/dev/null +fail() { + echo "${*}" >&2 + exit 1 +} + +# Stolen from extract-vmlinux and modified. +try_decompress() { + local header="${1}" + local no_idea="${2}" + local tool="${3}" + local image="${4}" + local tmp="${5}" + local output_basename="${6}" + + local pos + local tool_filename=$(echo "${tool}" | cut -f1 -d' ') + # The obscure use of the "tr" filter is to work around older versions of + # "grep" that report the byte offset of the line instead of the pattern. + + # Try to find the header and decompress from here. + for pos in $(tr "${header}\n${no_idea}" "\n${no_idea}=" < "${image}" | + grep --text --byte-offset --only-matching "^${no_idea}") + do + pos=${pos%%:*} + # Disable error handling, because we will be potentially + # giving the tool garbage or a valid archive with some garbage + # appended to it. So let the tool extract the valid archive + # and then complain about the garbage at the end, but don't + # fail the script because of it. + set +e; tail "-c+${pos}" "${image}" | "${tool}" >"${tmp}/out" 2>/dev/null; set -e; + if [ -s "${tmp}/out" ]; then + mv "${tmp}/out" "${output_basename}-${tool_filename}-at-${pos}" + else + rm -f "${tmp}/out" + fi + done +} + +try_unzstd_decompress() { + local image="${1}" + local tmp="${2}" + local output_basename="${3}" + try_decompress '(\265/\375' xxx unzstd "${image}" "${tmp}" "${output_basename}" +} + +me="${0##*/}" +if [[ $# -ne 2 ]]; then + fail "Usage: ${me} " +fi +image="${1}" +out="${2}" +if [[ ! -s "${image}" ]]; then + fail "The image file '${image}' either does not exist or is empty" +fi +mkdir -p "${out}" + +tmp=$(mktemp --directory /tmp/eifv-XXXXXX) +trap "rm -rf ${tmp}" EXIT + +tmp_dec="${tmp}/decompress" +mkdir "${tmp_dec}" +fr_prefix="${tmp}/first-round" + +ROOTFS_IDX=0 +perform_round() { + local image="${1}" + local tmp_dec="${2}" + local round_prefix="${3}" + try_unzstd_decompress "${image}" "${tmp_dec}" "${round_prefix}" + for rnd in "${round_prefix}"*; do + if [[ $(file --brief "${rnd}") =~ 'cpio archive' ]]; then + mkdir -p "${out}/rootfs-${ROOTFS_IDX}" + while cpio --quiet --extract --make-directories --directory="${out}/rootfs-${ROOTFS_IDX}" --nonmatching 'dev/*'; do + ROOTFS_IDX=$(( ROOTFS_IDX + 1 )) + mkdir -p "${out}/rootfs-${ROOTFS_IDX}" + done <${rnd} + rmdir "${out}/rootfs-${ROOTFS_IDX}" + fi + done +} + +shopt -s nullglob +perform_round "${image}" "${tmp_dec}" "${fr_prefix}" +for fr in "${fr_prefix}"*; do + fr_files="${fr}-files" + fr_dec="${fr_files}/decompress" + mkdir -p "${fr_dec}" + sr_prefix="${fr_files}/second-round" + perform_round "${fr}" "${fr_dec}" "${sr_prefix}" +done + +if [[ ${ROOTFS_IDX} -eq 0 ]]; then + fail "no initramfs found in ${image}" +fi + +echo "done, found ${ROOTFS_IDX} rootfs(es)" diff --git a/build_library/prod_image_util.sh b/build_library/prod_image_util.sh index 8f5d514f4b..00005440e5 100755 --- a/build_library/prod_image_util.sh +++ b/build_library/prod_image_util.sh @@ -74,6 +74,8 @@ create_prod_image() { local image_pcr_policy="${image_name%.bin}_pcr_policy.zip" local image_grub="${image_name%.bin}.grub" local image_shim="${image_name%.bin}.shim" + local image_initrd_contents="${image_name%.bin}_initrd_contents.txt" + local image_initrd_contents_wtd="${image_name%.bin}_initrd_contents_wtd.txt" start_image "${image_name}" "${disk_layout}" "${root_fs_dir}" "${update_group}" @@ -137,7 +139,9 @@ EOF "${image_pcr_policy}" \ "${image_grub}" \ "${image_shim}" \ - "${image_kconfig}" + "${image_kconfig}" \ + "${image_initrd_contents}" \ + "${image_initrd_contents_wtd}" # Upload local to_upload=( @@ -150,6 +154,8 @@ EOF "${BUILD_DIR}/${image_pcr_policy}" "${BUILD_DIR}/${image_grub}" "${BUILD_DIR}/${image_kconfig}" + "${BUILD_DIR}/${image_initrd_contents}" + "${BUILD_DIR}/${image_initrd_contents_wtd}" ) local files_to_evaluate=( "${BUILD_DIR}/${image_name}" )