Skip to content

Instantly share code, notes, and snippets.

@smoser
Last active November 22, 2021 12:13
Show Gist options
  • Save smoser/f28395d273a8b22a35122fd5205ad8b8 to your computer and use it in GitHub Desktop.
Save smoser/f28395d273a8b22a35122fd5205ad8b8 to your computer and use it in GitHub Desktop.
update or add to an initramfs or initrd with contents of a directory

Update an initramfs with contents of a directory without root

This tool allows you to take a initramfs and add contents of a directory to it. This is very useful if you need to test initramfs, you can simply take the original and add your files "over".

Also, because it does not extract the original cpio archive, it works without root.

Usage:

Usage: overlay-initramfs [ options ] source-initramfs directory [output]

   create an initramfs that has 'directory' overlayed on top
   of the source-initramfs.  This relies on the fact that you can
   append cpio archives to an initramfs and the kernel extraction
   just puts one on top of the other.

Notes

  • This probably needs to be updated with the new style initramfs that have an 'early' and 'early2' directory in them. In newer ubuntu (18.04+) there is a tool 'unmkinitramfs' that unpacks initramfs, but unfortunately there is no "re-initramfs" that would re-pack the unmkinitramfs output.
#!/bin/bash
VERBOSITY=0
TEMP_D=""
error() { echo "$@" 1>&2; }
fail() { [ $# -eq 0 ] || error "$@"; exit 1; }
Usage() {
cat <<EOF
Usage: ${0##*/} [ options ] source-initramfs directory [output]
create an initramfs that has 'directory' overlayed on top
of the source-initramfs. This relies on the fact that you can
append cpio archives to an initramfs and the kernel extraction
just puts one on top of the other.
EOF
}
bad_Usage() { Usage 1>&2; [ $# -eq 0 ] || error "$@"; exit 1; }
cleanup() {
[ -z "${TEMP_D}" -o ! -d "${TEMP_D}" ] || rm -Rf "${TEMP_D}"
}
debug() {
local level=${1}; shift;
[ "${level}" -gt "${VERBOSITY}" ] && return
error "${@}"
}
short_opts="hv"
long_opts="help,verbose"
getopt_out=$(getopt --name "${0##*/}" \
--options "${short_opts}" --long "${long_opts}" -- "$@") &&
eval set -- "${getopt_out}" ||
bad_Usage
output="-"
while [ $# -ne 0 ]; do
cur=${1}; next=${2};
case "$cur" in
-h|--help) Usage ; exit 0;;
-v|--verbose) VERBOSITY=$((${VERBOSITY}+1));;
--) shift; break;;
esac
shift;
done
[ $# -ge 1 -a $# -le 3 ] ||
bad_Usage "must give between 1 and 3 arguments"
orig="$1"
add_d="$2"
[ -f "$orig" ] || fail "${orig}: not a file"
[ -d "${add_d}" ] || fail "${add_d}: not a directory"
[ $# -eq 3 ] && output="$3"
TEMP_D=$(mktemp -d "${TMPDIR:-/tmp}/${0##*/}.XXXXXX") ||
fail "failed to make tempdir"
trap cleanup EXIT
start="$PWD"
cd "${add_d}" || fail "failed to chdir to ${add_d}"
find . > "${TEMP_D}/files" ||
fail "failed to get file list in ${add_d}"
cpio --format=newc -o > "${TEMP_D}/update.cpio" < "${TEMP_D}/files" ||
fail "failed to create update cpio"
cd "$start"
if [ "$output" = "-" ]; then
exec 3>&1
else
exec 3>"$output"
fi
[ $? -eq 0 ] || fail "failed redirect output"
set -o pipefail
( zcat "$orig" && cat "${TEMP_D}/update.cpio" ) | gzip -c >&3 ||
fail "failed to write to $output"
error "wrote to $output"
# vi: ts=4 noexpandtab
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment