summaryrefslogtreecommitdiffstats
path: root/mkinitramfs
diff options
context:
space:
mode:
Diffstat (limited to 'mkinitramfs')
-rwxr-xr-xmkinitramfs518
1 files changed, 518 insertions, 0 deletions
diff --git a/mkinitramfs b/mkinitramfs
new file mode 100755
index 0000000..df1b940
--- /dev/null
+++ b/mkinitramfs
@@ -0,0 +1,518 @@
+#!/bin/sh
+
+umask 0022
+export PATH='/usr/bin:/sbin:/bin'
+
+# Defaults
+keep="n"
+CONFDIR="/etc/initramfs-tools"
+verbose="n"
+# Will be updated by busybox's conf hook, if present
+BUSYBOXDIR=
+export BUSYBOXDIR
+
+usage()
+{
+ cat << EOF
+
+Usage: mkinitramfs [option]... -o outfile [version]
+
+Options:
+ -c compress Override COMPRESS setting in initramfs.conf.
+ -d confdir Specify an alternative configuration directory.
+ -l level Override COMPRESSLEVEL setting in initramfs.conf.
+ -k Keep temporary directory used to make the image.
+ -o outfile Write to outfile.
+ -r root Override ROOT setting in initramfs.conf.
+
+See mkinitramfs(8) for further details.
+
+EOF
+}
+
+usage_error()
+{
+ usage >&2
+ exit 2
+}
+
+OPTIONS=$(getopt -o c:d:hl:ko:r:v --long help -n "$0" -- "$@") || usage_error
+
+eval set -- "$OPTIONS"
+
+while true; do
+ case "$1" in
+ -c)
+ compress="$2"
+ shift 2
+ ;;
+ -d)
+ CONFDIR="$2"
+ shift 2
+ if [ ! -d "${CONFDIR}" ]; then
+ echo "${0}: ${CONFDIR}: Not a directory" >&2
+ exit 1
+ fi
+ ;;
+ -h|--help)
+ usage
+ exit 0
+ ;;
+ -l)
+ compresslevel="$2"
+ shift 2
+ ;;
+ -o)
+ outfile="$2"
+ shift 2
+ ;;
+ -k)
+ keep="y"
+ shift
+ ;;
+ -r)
+ ROOT="$2"
+ shift 2
+ ;;
+ -v)
+ verbose="y"
+ shift
+ ;;
+ --)
+ shift
+ break
+ ;;
+ *)
+ echo "Internal error!" >&2
+ exit 1
+ ;;
+ esac
+done
+
+# For dependency ordered mkinitramfs hook scripts.
+. /usr/share/initramfs-tools/scripts/functions
+. /usr/share/initramfs-tools/hook-functions
+
+. "${CONFDIR}/initramfs.conf"
+
+EXTRA_CONF=''
+maybe_add_conf() {
+ if [ -e "$1" ] && \
+ basename "$1" \
+ | grep '^[[:alnum:]][[:alnum:]\._-]*$' \
+ | grep -qv '\.dpkg-.*$'; then
+ if [ -d "$1" ]; then
+ echo "W: $1 is a directory instead of file" >&2
+ else
+ EXTRA_CONF="${EXTRA_CONF} $1"
+ . "$1"
+ fi
+ fi
+}
+for i in /usr/share/initramfs-tools/conf.d/*; do
+ # Configuration files in /etc mask those in /usr/share
+ if ! [ -e "${CONFDIR}"/conf.d/"$(basename "${i}")" ]; then
+ maybe_add_conf "${i}"
+ fi
+done
+for i in "${CONFDIR}"/conf.d/*; do
+ maybe_add_conf "${i}"
+done
+
+# source package confs
+for i in /usr/share/initramfs-tools/conf-hooks.d/*; do
+ if [ -d "${i}" ]; then
+ echo "W: ${i} is a directory instead of file." >&2
+ elif [ -e "${i}" ]; then
+ . "${i}"
+ fi
+done
+
+# Check busybox dependency
+if [ "${BUSYBOX}" = "y" ] && [ -z "${BUSYBOXDIR}" ]; then
+ echo >&2 "E: @BUSYBOX_PACKAGES@, version @BUSYBOX_MIN_VERSION@ or later, is required but not installed"
+ exit 1
+fi
+
+if [ -n "${UMASK:-}" ]; then
+ umask "${UMASK}"
+fi
+
+if [ -z "${outfile}" ]; then
+ usage_error
+fi
+
+touch "$outfile"
+outfile="$(readlink -f "$outfile")"
+
+# And by "version" we really mean path to kernel modules
+# This is braindead, and exists to preserve the interface with mkinitrd
+if [ ${#} -ne 1 ]; then
+ version="$(uname -r)"
+else
+ version="${1}"
+fi
+
+case "${version}" in
+/lib/modules/*/[!/]*)
+ ;;
+/lib/modules/[!/]*)
+ version="${version#/lib/modules/}"
+ version="${version%%/*}"
+ ;;
+esac
+
+case "${version}" in
+*/*)
+ echo "$PROG: ${version} is not a valid kernel version" >&2
+ exit 2
+ ;;
+esac
+
+if [ -z "${compress:-}" ]; then
+ compress=${COMPRESS?}
+fi
+unset COMPRESS
+
+if ! command -v "${compress}" >/dev/null 2>&1; then
+ echo "W: No ${compress} in ${PATH}, using gzip" >&2
+ compress=gzip
+fi
+
+# Check that kernel supports selected compressor, and fall back to gzip.
+# Exit if even gzip is not supported.
+case "${compress}" in
+gzip) kconfig_sym=CONFIG_RD_GZIP ;;
+bzip2) kconfig_sym=CONFIG_RD_BZIP2 ;;
+lzma) kconfig_sym=CONFIG_RD_LZMA ;;
+xz) kconfig_sym=CONFIG_RD_XZ ;;
+lzop) kconfig_sym=CONFIG_RD_LZO ;;
+lz4) kconfig_sym=CONFIG_RD_LZ4 ;;
+zstd) kconfig_sym=CONFIG_RD_ZSTD ;;
+esac
+while ! grep -q "^$kconfig_sym=y" "/boot/config-${version}"; do
+ if [ "${compress}" = gzip ]; then
+ echo "E: gzip compression ($kconfig_sym) not supported by kernel" >&2
+ exit 1
+ fi
+ echo "W: ${compress} compression ($kconfig_sym) not supported by kernel, using gzip" >&2
+ compress=gzip
+ kconfig_sym=CONFIG_RD_GZIP
+done
+
+if [ -z "${compresslevel:-}" ]; then
+ compresslevel=${COMPRESSLEVEL:-}
+fi
+case "${compress}" in
+lz4) compresslevel="-${compresslevel:-9}" ;;
+zstd) compresslevel="-${compresslevel:-9}" ;;
+#gzip|xz|bzip2|lzma|lzop included
+*)
+ # We're not using a compression level by default
+ compresslevel="${compresslevel:+-${compresslevel}}"
+ ;;
+esac
+unset COMPRESSLEVEL
+
+case "${compress}" in
+gzip) # If we're doing a reproducible build, use gzip -n
+ if [ -n "${SOURCE_DATE_EPOCH}" ]; then
+ compress="gzip -n"
+ # Otherwise, substitute pigz if it's available
+ elif command -v pigz >/dev/null; then
+ compress=pigz
+ fi
+ if [ -n "${compresslevel}" ]; then
+ compress="${compress} ${compresslevel}"
+ fi
+ ;;
+lz4) compress="lz4 ${compresslevel} -l" ;;
+zstd) compress="zstd -q ${compresslevel}"
+ # If we're not doing a reproducible build, enable multithreading
+ test -z "${SOURCE_DATE_EPOCH}" && compress="$compress -T0"
+ ;;
+xz) compress="xz ${compresslevel} --check=crc32"
+ # If we're not doing a reproducible build, enable multithreading
+ test -z "${SOURCE_DATE_EPOCH}" && compress="$compress --threads=0"
+ ;;
+bzip2|lzma|lzop)
+ compress="${compress} ${compresslevel}"
+ ;;
+*) echo "W: Unknown compression command ${compress}" >&2 ;;
+esac
+
+if [ -d "${outfile}" ]; then
+ echo "${outfile} is a directory" >&2
+ exit 1
+fi
+
+MODULESDIR="/lib/modules/${version}"
+
+if [ ! -e "${MODULESDIR}" ]; then
+ echo "W: missing ${MODULESDIR}" >&2
+ echo "W: Ensure all necessary drivers are built into the linux image!" >&2
+fi
+if [ ! -e "${MODULESDIR}/modules.dep" ]; then
+ depmod "${version}"
+fi
+
+# Prepare to clean up temporary files on exit
+DESTDIR=
+__TMPCPIOGZ=
+__TMPMAINCPIO=
+__TMPEARLYCPIO=
+clean_on_exit() {
+ if [ "${keep}" = "y" ]; then
+ echo "Working files in ${DESTDIR:-<not yet created>}," \
+ "early initramfs in ${__TMPEARLYCPIO:-<not yet created>}," \
+ "main initramfs in ${__TMPMAINCPIO:-<not yet created>} and" \
+ "overlay in ${__TMPCPIOGZ:-<not yet created>}"
+ else
+ for path in "${DESTDIR}" "${__TMPCPIOGZ}" "${__TMPMAINCPIO}" "${__TMPEARLYCPIO}"; do
+ test -z "${path}" || rm -rf "${path}"
+ done
+ fi
+}
+trap clean_on_exit EXIT
+trap "exit 1" INT TERM # makes the EXIT trap effective even when killed
+
+# Create temporary directory and files for initramfs contents
+[ -n "${TMPDIR}" ] && [ ! -w "${TMPDIR}" ] && unset TMPDIR
+DESTDIR="$(mktemp -d "${TMPDIR:-/var/tmp}/mkinitramfs_XXXXXX")" || exit 1
+chmod 755 "${DESTDIR}"
+__TMPCPIOGZ="$(mktemp "${TMPDIR:-/var/tmp}/mkinitramfs-OL_XXXXXX")" || exit 1
+__TMPMAINCPIO="$(mktemp "${TMPDIR:-/var/tmp}/mkinitramfs-MAIN_XXXXXX")" || exit 1
+__TMPEARLYCPIO="$(mktemp "${TMPDIR:-/var/tmp}/mkinitramfs-FW_XXXXXX")" || exit 1
+
+DPKG_ARCH=$(dpkg --print-architecture)
+
+# Export environment for hook scripts.
+#
+export MODULESDIR
+export version
+export CONFDIR
+export DESTDIR
+export DPKG_ARCH
+export verbose
+export KEYMAP
+export MODULES
+export BUSYBOX
+export RESUME
+export FSTYPE
+
+# Private, used by 'catenate_cpiogz'.
+export __TMPCPIOGZ
+
+# Private, used by 'prepend_earlyinitramfs'.
+export __TMPEARLYCPIO
+
+# Create usr-merged filesystem layout, to avoid duplicates if the host
+# filesystem is usr-merged.
+for d in /bin /lib* /sbin; do
+ mkdir -p "${DESTDIR}/usr${d}"
+ ln -s "usr${d}" "${DESTDIR}${d}"
+done
+for d in conf/conf.d etc run scripts ${MODULESDIR}; do
+ mkdir -p "${DESTDIR}/${d}"
+done
+
+# Copy in modules.builtin, modules.builtin.modinfo and modules.order (not generated by depmod)
+# and modules.builtin.bin (generated by depmod, but too late to avoid
+# error messages as in #948257)
+for x in modules.builtin modules.builtin.bin modules.builtin.modinfo modules.order; do
+ if [ -f "${MODULESDIR}/${x}" ]; then
+ cp -p "${MODULESDIR}/${x}" "${DESTDIR}${MODULESDIR}/${x}"
+ fi
+done
+
+# MODULES=list case. Always honour.
+for x in "${CONFDIR}/modules" /usr/share/initramfs-tools/modules.d/*; do
+ if [ -f "${x}" ]; then
+ add_modules_from_file "${x}"
+ fi
+done
+
+# MODULES=most is default
+case "${MODULES}" in
+dep)
+ dep_add_modules
+ ;;
+most)
+ auto_add_modules
+ ;;
+netboot)
+ auto_add_modules base
+ auto_add_modules net
+ ;;
+list)
+ # nothing to add
+ ;;
+*)
+ echo "W: mkinitramfs: unsupported MODULES setting: ${MODULES}." >&2
+ echo "W: mkinitramfs: Falling back to MODULES=most." >&2
+ auto_add_modules
+ ;;
+esac
+
+# Resolve hidden dependencies
+hidden_dep_add_modules
+
+# Add firmware for built-in code
+add_builtin_firmware
+
+# First file executed by linux
+cp -p /usr/share/initramfs-tools/init "${DESTDIR}/init"
+
+# add existant boot scripts
+for b in $(cd /usr/share/initramfs-tools/scripts/ && find . \
+ -regextype posix-extended -regex '.*/[[:alnum:]\._-]+$' -type f); do
+ [ -d "${DESTDIR}/scripts/$(dirname "${b}")" ] \
+ || mkdir -p "${DESTDIR}/scripts/$(dirname "${b}")"
+ cp -p "/usr/share/initramfs-tools/scripts/${b}" \
+ "${DESTDIR}/scripts/$(dirname "${b}")/"
+done
+# Prune dot-files/directories and limit depth to exclude VCS files
+for b in $(cd "${CONFDIR}/scripts" && find . -maxdepth 2 -name '.?*' -prune -o \
+ -regextype posix-extended -regex '.*/[[:alnum:]\._-]+$' -type f -print); do
+ [ -d "${DESTDIR}/scripts/$(dirname "${b}")" ] \
+ || mkdir -p "${DESTDIR}/scripts/$(dirname "${b}")"
+ cp -p "${CONFDIR}/scripts/${b}" "${DESTDIR}/scripts/$(dirname "${b}")/"
+done
+
+echo "DPKG_ARCH=${DPKG_ARCH}" > "${DESTDIR}/conf/arch.conf"
+cp -p "${CONFDIR}/initramfs.conf" "${DESTDIR}/conf"
+for i in ${EXTRA_CONF}; do
+ copy_file config "${i}" /conf/conf.d
+done
+
+# ROOT hardcoding
+if [ -n "${ROOT:-}" ]; then
+ echo "ROOT=${ROOT}" > "${DESTDIR}/conf/conf.d/root"
+fi
+
+if ! command -v ldd >/dev/null 2>&1 ; then
+ echo "E: no ldd around - install libc-bin" >&2
+ exit 1
+fi
+
+# fstab and mtab
+touch "${DESTDIR}/etc/fstab"
+ln -s /proc/mounts "${DESTDIR}/etc/mtab"
+
+# module-init-tools
+copy_exec /sbin/modprobe /sbin
+copy_exec /sbin/rmmod /sbin
+mkdir -p "${DESTDIR}/etc/modprobe.d" "${DESTDIR}/lib/modprobe.d"
+for file in /etc/modprobe.d/*.conf /lib/modprobe.d/*.conf ; do
+ if test -e "$file" || test -L "$file" ; then
+ copy_file config "$file"
+ fi
+done
+
+run_scripts /usr/share/initramfs-tools/hooks
+run_scripts "${CONFDIR}"/hooks
+
+# cache boot run order
+for b in $(cd "${DESTDIR}/scripts" && find . -mindepth 1 -type d); do
+ cache_run_scripts "${DESTDIR}" "/scripts/${b#./}"
+done
+
+# decompress modules for boot speed, if possible
+find "${DESTDIR}/${MODULESDIR}" -name '*.ko.*' | while read -r ko; do
+ case "$ko" in
+ *.xz)
+ if ! command -v xz >/dev/null 2>&1; then
+ break
+ fi
+ xz -d "${ko}"
+ ;;
+ *.zst)
+ if ! command -v zstd >/dev/null 2>&1; then
+ break
+ fi
+ zstd -q -d --rm "${ko}"
+ ;;
+ esac
+done
+
+# generate module deps
+depmod -a -b "${DESTDIR}" "${version}"
+rm -f "${DESTDIR}/lib/modules/${version}"/modules.*map
+
+# make sure that library search path is up to date
+cp -pPr /etc/ld.so.conf* "$DESTDIR"/etc/
+if ! ldconfig -r "$DESTDIR" ; then
+ [ "$(id -u)" != "0" ] \
+ && echo "ldconfig might need uid=0 (root) for chroot()" >&2
+fi
+# The auxiliary cache is not reproducible and is always invalid at boot
+# (see #845034)
+if [ -d "${DESTDIR}"/var/cache/ldconfig ]; then
+ rm -f "${DESTDIR}"/var/cache/ldconfig/aux-cache
+ rmdir --ignore-fail-on-non-empty "${DESTDIR}"/var/cache/ldconfig
+fi
+
+# Apply DSDT to initramfs
+if [ -e "${CONFDIR}/DSDT.aml" ]; then
+ copy_file DSDT "${CONFDIR}/DSDT.aml"
+fi
+
+[ "${verbose}" = y ] && echo "Building cpio ${outfile} initramfs"
+
+(
+# preserve permissions if root builds the image, see #633582
+[ "$(id -ru)" != 0 ] && cpio_owner_root="-R 0:0"
+
+# if SOURCE_DATE_EPOCH is set, try and create a reproducible image
+if [ -n "${SOURCE_DATE_EPOCH}" ]; then
+ # ensure that no timestamps are newer than $SOURCE_DATE_EPOCH
+ find "${DESTDIR}" -newermt "@${SOURCE_DATE_EPOCH}" -print0 | \
+ xargs -0r touch --no-dereference --date="@${SOURCE_DATE_EPOCH}"
+
+ # --reproducible requires cpio >= 2.12
+ cpio_reproducible="--reproducible"
+fi
+
+# work around lack of "set -o pipefail" for the following pipe:
+# cd "${DESTDIR}" && find . | LC_ALL=C sort | cpio --quiet $cpio_owner_root $cpio_reproducible -o -H newc >>"${outfile}" || exit 1
+ec1=1
+ec2=1
+exec 3>&1
+eval "$(
+ # http://cfaj.freeshell.org/shell/cus-faq-2.html
+ exec 4>&1 >&3 3>&-
+ cd "${DESTDIR}"
+ {
+ find . 4>&-; echo "ec1=$?;" >&4
+ } | {
+ LC_ALL=C sort
+ } | {
+ # shellcheck disable=SC2086
+ cpio --quiet $cpio_owner_root $cpio_reproducible -o -H newc 4>&- >"${__TMPMAINCPIO}"
+ echo "ec2=$?;" >&4
+ }
+)"
+if [ "$ec1" -ne 0 ]; then
+ echo "E: mkinitramfs failure find $ec1 cpio $ec2" >&2
+ exit "$ec1"
+fi
+if [ "$ec2" -ne 0 ]; then
+ echo "E: mkinitramfs failure cpio $ec2" >&2
+ exit "$ec2"
+fi
+) || exit 1
+
+{
+if [ -s "${__TMPEARLYCPIO}" ]; then
+ cat "${__TMPEARLYCPIO}" || exit 1
+fi
+
+$compress -c "${__TMPMAINCPIO}" ||
+ { echo "E: mkinitramfs failure $compress $?" >&2; exit 1; }
+
+if [ -s "${__TMPCPIOGZ}" ]; then
+ cat "${__TMPCPIOGZ}" || exit 1
+fi
+} >"${outfile}" || exit 1
+
+exit 0