351 lines
8 KiB
Bash
Executable file
351 lines
8 KiB
Bash
Executable file
#!/bin/sh
|
|
|
|
umask 0022
|
|
export PATH='/usr/bin:/sbin:/bin'
|
|
|
|
# Defaults
|
|
keep="n"
|
|
CONFDIR="/etc/initramfs-tools"
|
|
verbose="n"
|
|
|
|
OPTIONS=`getopt -o c:d:ko:r:v -n "$0" -- "$@"`
|
|
|
|
# Check for non-GNU getopt
|
|
if [ $? != 0 ] ; then echo "W: non-GNU getopt" >&2 ; exit 1 ; fi
|
|
|
|
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
|
|
;;
|
|
-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=''
|
|
for i in /usr/share/initramfs-tools/conf.d/* ${CONFDIR}/conf.d/*; do
|
|
[ -e $i ] && EXTRA_CONF="${EXTRA_CONF} $(basename $i \
|
|
| grep '^[[:alnum:]][[:alnum:]\._-]*$' | grep -v '\.dpkg-.*$')";
|
|
done
|
|
# FIXME: deprecated those settings on mkinitramfs run
|
|
# these conf dirs are for boot scripts and land on initramfs
|
|
for i in ${EXTRA_CONF}; do
|
|
if [ -e ${CONFDIR}/conf.d/${i} ]; then
|
|
. ${CONFDIR}/conf.d/${i}
|
|
elif [ -e /usr/share/initramfs-tools/conf.d/${i} ]; then
|
|
. /usr/share/initramfs-tools/conf.d/${i}
|
|
fi
|
|
done
|
|
|
|
# source package confs
|
|
for i in /usr/share/initramfs-tools/conf-hooks.d/*; do
|
|
if [ -e "${i}" ]; then
|
|
. "${i}"
|
|
fi
|
|
done
|
|
|
|
if [ -n "${UMASK:-}" ]; then
|
|
umask "${UMASK}"
|
|
fi
|
|
|
|
if [ -z "${outfile}" ]; then
|
|
usage
|
|
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
|
|
|
|
# Check that we're using a new enough kernel version, first for ourselves,
|
|
# then for each of the hooks, which can have a MINKVER variable defined
|
|
check_minkver ${version}
|
|
check_minkver ${version} /usr/share/initramfs-tools/hooks
|
|
check_minkver ${version} ${CONFDIR}/hooks
|
|
|
|
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 1
|
|
;;
|
|
esac
|
|
|
|
# Check userspace and kernel support for compressed initramfs images
|
|
if [ -z "${compress:-}" ]; then
|
|
compress=${COMPRESS}
|
|
else
|
|
COMPRESS=${compress}
|
|
fi
|
|
|
|
if ! command -v "${compress}" >/dev/null 2>&1; then
|
|
compress=gzip
|
|
[ "${verbose}" = y ] && \
|
|
echo "No ${COMPRESS} in ${PATH}, using gzip"
|
|
COMPRESS=gzip
|
|
fi
|
|
|
|
if ! `grep -q -i ^config_rd_${COMPRESS%p} /boot/config-${version}` ; then
|
|
compress=gzip
|
|
[ "${verbose}" = y ] && \
|
|
echo "linux-2.6 misses ${COMPRESS} support, using gzip"
|
|
fi
|
|
|
|
# Always compress with best compression mode to save space.
|
|
[ "$compress" = xz ] && compress="xz --check=crc32"
|
|
compress="$compress -9"
|
|
|
|
if [ -d "${outfile}" ]; then
|
|
echo "${outfile} is a directory" >&2
|
|
exit 1
|
|
fi
|
|
|
|
MODULESDIR="/lib/modules/${version}"
|
|
|
|
if [ ! -e "${MODULESDIR}" ]; then
|
|
echo "WARNING: missing ${MODULESDIR}"
|
|
echo "Device driver support needs thus be built-in linux image!"
|
|
fi
|
|
if [ ! -e "${MODULESDIR}/modules.dep" ]; then
|
|
depmod ${version}
|
|
fi
|
|
|
|
DESTDIR="$(mktemp -d ${TMPDIR:-/tmp}/mkinitramfs_XXXXXX)" || exit 1
|
|
chmod 755 "${DESTDIR}"
|
|
|
|
# do not execute cache_run_scripts() if mounted with noexec
|
|
NOEXEC=""
|
|
if [ -r /etc/mtab ]; then
|
|
fs=$(df -P $DESTDIR | tail -1 | awk '{print $6}')
|
|
if [ -n "$fs" ] && mount | grep -q "on $fs .*noexec" ; then
|
|
NOEXEC=1
|
|
fi
|
|
fi
|
|
|
|
__TMPCPIOGZ="$(mktemp ${TMPDIR:-/tmp}/mkinitramfs-OL_XXXXXX)" || exit 1
|
|
|
|
DPKG_ARCH=`uname -m`
|
|
|
|
# Export environment for hook scripts.
|
|
#
|
|
export MODULESDIR
|
|
export version
|
|
export CONFDIR
|
|
export DESTDIR
|
|
export DPKG_ARCH
|
|
export verbose
|
|
export KEYMAP
|
|
export MODULES
|
|
|
|
# Private, used by 'catenate_cpiogz'.
|
|
export __TMPCPIOGZ
|
|
|
|
for d in bin conf/conf.d etc lib/modules run sbin scripts ${MODULESDIR}; do
|
|
mkdir -p "${DESTDIR}/${d}"
|
|
done
|
|
|
|
# Copy the modules.order file in
|
|
if [ -f "${MODULESDIR}/modules.order" ]; then
|
|
cp -p "${MODULESDIR}/modules.order" \
|
|
"${DESTDIR}${MODULESDIR}/modules.order"
|
|
fi
|
|
|
|
# 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}."
|
|
echo "W: mkinitramfs: Falling back to MODULES=most."
|
|
auto_add_modules
|
|
;;
|
|
esac
|
|
|
|
# Resolve hidden dependencies
|
|
hidden_dep_add_modules
|
|
|
|
# Have to do each file, because cpio --dereference doesn't recurse down
|
|
# symlinks.
|
|
|
|
cp -p /usr/share/initramfs-tools/init ${DESTDIR}/init
|
|
|
|
# add existant boot scripts
|
|
for b in $(cd /usr/share/initramfs-tools/scripts/ && find -L . \
|
|
-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
|
|
for b in $(cd "${CONFDIR}/scripts" && find -L . \
|
|
-regextype posix-extended -regex '.*/[[:alnum:]\._-]+$' -type f); do
|
|
[ -d "${DESTDIR}/scripts/$(dirname "${b}")" ] \
|
|
|| mkdir -p "${DESTDIR}/scripts/$(dirname "${b}")"
|
|
cp -p "${CONFDIR}/scripts/${b}" "${DESTDIR}/scripts/$(dirname "${b}")/"
|
|
done
|
|
|
|
cp -p "${CONFDIR}/initramfs.conf" ${DESTDIR}/conf
|
|
for i in ${EXTRA_CONF}; do
|
|
if [ -e "${CONFDIR}/conf.d/${i}" ]; then
|
|
copy_exec "${CONFDIR}/conf.d/${i}" /conf/conf.d
|
|
elif [ -e "/usr/share/initramfs-tools/conf.d/${i}" ]; then
|
|
copy_exec "/usr/share/initramfs-tools/conf.d/${i}" /conf/conf.d
|
|
fi
|
|
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 "WARNING: no ldd around - install libc-bin" >&2
|
|
exit 1
|
|
fi
|
|
|
|
run_scripts /usr/share/initramfs-tools/hooks
|
|
run_scripts "${CONFDIR}"/hooks
|
|
|
|
# cache boot run order
|
|
if [ -n "$NOEXEC" ]; then
|
|
echo "W: TMPDIR is mounted noexec, will not cache run scripts."
|
|
else
|
|
for b in $(cd "${DESTDIR}/scripts" && find . -mindepth 1 -type d); do
|
|
cache_run_scripts "${DESTDIR}" "/scripts/${b#./}"
|
|
done
|
|
fi
|
|
|
|
# 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 -ar /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
|
|
|
|
# Apply DSDT to initramfs
|
|
if [ -e "${CONFDIR}/DSDT.aml" ]; then
|
|
copy_exec "${CONFDIR}/DSDT.aml" /
|
|
fi
|
|
|
|
# Remove any looping or broken symbolic links, since they break cpio.
|
|
[ "${verbose}" = y ] && xargs_verbose="-t"
|
|
(cd "${DESTDIR}" && find . -type l -printf '%p %Y\n' | sed -n 's/ [LN]$//p' \
|
|
| xargs ${xargs_verbose:-} -rL1 rm -f)
|
|
|
|
[ "${verbose}" = y ] && echo "Building cpio ${outfile} initramfs"
|
|
(
|
|
# work around lack of "set -o pipefail" for the following pipe:
|
|
# cd "${DESTDIR}" && find . | cpio --quiet -R 0:0 -o -H newc | gzip >"${outfile}" || exit 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
|
|
} | {
|
|
cpio --quiet -R 0:0 -o -H newc 4>&-; echo "ec2=$?;" >&4
|
|
} | ${compress} >"${outfile}"
|
|
echo "ec3=$?;" >&4
|
|
`
|
|
if [ "$ec1" -ne 0 ]; then
|
|
echo "E: mkinitramfs failure find $ec1 cpio $ec2 $compress $ec3"
|
|
exit "$ec1"
|
|
fi
|
|
if [ "$ec2" -ne 0 ]; then
|
|
echo "E: mkinitramfs failure cpio $ec2 $compress $ec3"
|
|
exit "$ec2"
|
|
fi
|
|
if [ "$ec3" -ne 0 ]; then
|
|
echo "E: mkinitramfs failure $compress $ec3"
|
|
exit "$ec3"
|
|
fi
|
|
) || exit 1
|
|
|
|
if [ -s "${__TMPCPIOGZ}" ]; then
|
|
cat "${__TMPCPIOGZ}" >>"${outfile}" || exit 1
|
|
fi
|
|
|
|
if [ "${keep}" = "y" ]; then
|
|
echo "Working files in ${DESTDIR} and overlay in ${__TMPCPIOGZ}"
|
|
else
|
|
rm -rf "${DESTDIR}"
|
|
rm -rf "${__TMPCPIOGZ}"
|
|
fi
|
|
|
|
exit 0
|