initramfs-tools/hook-functions
maximilian attems 8f8299d9ba mkinitramfs: copy over on build instead of using symlink tree
This facilitates mkinitramfs building.
It is intended as fix for the not possible ldconfig run inside
the symlink tree. It should also allow to cleanup the copy_exec() mess.

This also allows to no longer shipp duplicate busybox copies in
initramfs. dracut does it also. The symlinking was thought as
speed gain by jbailey, but I'm less then conviced it is worth it.

Also specify to cpio that the files should be owned by root.

In retrospect this really similar quasi a fowarded ported patch by
 Michal Schmidt <xschmi00@stud.feec.vutbr.cz>

Closes: #338405, #506540
Signed-off-by: maximilian attems <max@stro.at>
Tested-by: Benedikt Spranger <b.spranger@linutronix.de>
Reviewed-by: Michael Prokop <mika@debian.org>
2011-03-30 11:54:26 +02:00

536 lines
14 KiB
Bash

# -*- shell-script -*-
catenate_cpiogz() {
# Sanity check
if [ ! -e "${1}" ]; then
echo "W: catenate_cpiogz: arg1='${1}' does not exist." >&2
return
fi
cat "${1}" >>"${__TMPCPIOGZ}"
}
force_load()
{
manual_add_modules ${@}
echo "${@}" >>"${DESTDIR}/conf/modules"
}
# Takes a file containing a list of modules to be added as an
# argument, figures out dependancies, and adds them.
#
# Input file syntax:
#
# # comment
# modprobe_module_name [args ...]
# [...]
#
add_modules_from_file()
{
# Sanity check
if [ ! -e "${1}" ]; then
echo "W: add_modules_from_file: arg1='${1}' does not exist." >&2
return
fi
grep '^[^#]' ${1} | while read module args; do
[ -n "$module" ] || continue
force_load "${module}" "${args}"
done
}
# Add dependent modules + eventual firmware
manual_add_modules()
{
local kmod firmware
for kmod in $(modprobe --set-version="${version}" --ignore-install \
--quiet --show-depends "${1}" | awk '/^insmod/ { print $2 }'); do
# Prune duplicates
if [ -e "${DESTDIR}/${kmod}" ]; then
continue
fi
mkdir -p "${DESTDIR}/$(dirname "${kmod}")"
cp -pL "${kmod}" "${DESTDIR}/$(dirname "${kmod}")"
if [ "${verbose}" = "y" ]; then
echo "Adding module ${kmod}"
fi
# Add required firmware
for firmware in $(modinfo -F firmware "${kmod}"); do
if [ -e "${DESTDIR}/lib/firmware/${firmware}" ] \
|| [ -e "${DESTDIR}/lib/firmware/${version}/${firmware}" ]; then
continue
fi
# Only print warning for missing fw of loaded module
# or forced loaded module
if [ ! -e "/lib/firmware/${firmware}" ] \
&& [ ! -e "/lib/firmware/${version}/${firmware}" ] ; then
# Only warn about missing firmware if
# /proc/modules exists
if [ ! -e /proc/modules ] ; then
continue
fi
if grep -q "^$(basename "${kmod}" .ko)[[:space:]]" \
/proc/modules \
|| grep -q "^$(basename "${kmod}" .ko)" \
"${CONFDIR}/modules"; then
echo "W: Possible missing firmware /lib/firmware/${firmware} for module $(basename ${kmod} .ko)" >&2
fi
continue
fi
if [ ! -e "${DESTDIR}/lib/udev/firmware.agent" ] \
&& [ -e "/lib/udev/firmware.agent" ]; then
copy_exec /lib/udev/firmware.agent
fi
if [ -e "/lib/firmware/${version}/${firmware}" ]; then
copy_exec "/lib/firmware/${version}/${firmware}"
else
copy_exec "/lib/firmware/${firmware}"
fi
if [ "${verbose}" = "y" ]; then
echo "Adding firmware ${firmware}"
fi
done
done
}
# $1 = file to copy to ramdisk
# $2 (optional) Name for the file on the ramdisk
# Location of the image dir is assumed to be $DESTDIR
# We never overwrite the target if it exists.
copy_exec() {
local src target x nonoptlib
local libname dirname
src="${1}"
target="${2:-$1}"
[ -f "${src}" ] || return 1
if [ -d "${DESTDIR}/${target}" ]; then
# check if already copied
[ -e "${DESTDIR}/$target/${src##*/}" ] && return 0
else
[ -e "${DESTDIR}/$target" ] && return 0
#FIXME: inst_dir
mkdir -p "${DESTDIR}/${target%/*}"
fi
[ "${verbose}" = "y" ] && echo "Adding binary ${src}"
cp -pL "${src}" "${DESTDIR}/${target}"
# Copy the dependant libraries
for x in $(ldd ${src} 2>/dev/null | sed -e '
/\//!d;
/linux-gate/d;
/=>/ {s/.*=>[[:blank:]]*\([^[:blank:]]*\).*/\1/};
s/[[:blank:]]*\([^[:blank:]]*\) (.*)/\1/' 2>/dev/null); do
# Try to use non-optimised libraries where possible.
# We assume that all HWCAP libraries will be in tls,
# sse2, vfp or neon.
nonoptlib=$(echo "${x}" | sed -e 's#/lib/\(tls\|i686\|sse2\|neon\|vfp\).*/\(lib.*\)#/lib/\2#')
if [ -e "${nonoptlib}" ]; then
x="${nonoptlib}"
fi
libname=$(basename "${x}")
dirname=$(dirname "${x}")
# FIXME inst_lib
mkdir -p "${DESTDIR}/${dirname}"
if [ ! -e "${DESTDIR}/${dirname}/${libname}" ]; then
cp -pL "${x}" "${DESTDIR}/${dirname}"
[ "${verbose}" = "y" ] && echo "Adding library ${x}" || true
fi
done
}
# Copy entire subtrees to the initramfs
copy_modules_dir()
{
local kmod exclude
local dir="$1"
shift
if ! [ -d "${MODULESDIR}/${dir}" ]; then
return;
fi
if [ "${verbose}" = "y" ]; then
echo "Copying module directory ${dir}"
if [ $# -ge 1 ]; then
echo "(excluding $*)"
fi
fi
while [ $# -ge 1 ]; do
exclude="${exclude:-} -name $1 -prune -o "
shift
done
for kmod in $(find "${MODULESDIR}/${dir}" ${exclude:-} -name '*.ko' -print); do
manual_add_modules $(basename ${kmod} .ko)
done
}
# walk /sys for relevant modules
sys_walk_mod_add()
{
local driver_path module
device_path="$1"
while [ "${device_path}" != "/sys" ]; do
sys_walk_modalias ${device_path}
driver_path="$(readlink -f ${device_path}/driver/module)"
if [ -e "$driver_path" ]; then
module="$(basename $(readlink -f $driver_path))"
if [ -n "${module}" ]; then
force_load "${module}"
fi
fi
device_path="$(dirname ${device_path})"
done
}
# walk /sys for relevant modalias
sys_walk_modalias()
{
local device_path modalias
device_path="$(dirname "${1}")"
device_path="$(dirname "${device_path}")"
if [ -e "${device_path}/modalias" ]; then
modalias=$(cat "${device_path}/modalias")
fi
if [ -n "${modalias}" ]; then
force_load "${modalias}"
fi
}
# find and only copy root relevant modules
dep_add_modules()
{
local block minor root FSTYPE root_dev_path x
# require mounted sysfs
if [ ! -d /sys/devices/ ]; then
echo "mkinitramfs: MODULES dep requires mounted sysfs on /sys" >&2
exit 1
fi
# findout root block device + fstype
eval "$(mount | awk '/\/dev\// {if ($3 == "/") {print "root=" $1 "\nFSTYPE=" $5; exit}}')"
# On failure fallback to /proc/mounts if readable
if [ -z "$root" ] && [ -r /proc/mounts ]; then
eval "$(awk '!/^rootfs / {if ($2 == "/") {print "root=" $1 "\nFSTYPE=" $3; exit}}' /proc/mounts)"
fi
# recheck root device
if [ -z "$root" ]; then
echo "mkinitramfs: failed to determine root device" >&2
echo "mkinitramfs: workaround is MODULES=most, check:" >&2
echo "grep -r MODULES /etc/initramfs-tools/" >&2
echo "" >&2
echo "Error please report bug on initramfs-tools" >&2
echo "Include the output of 'mount' and 'cat /proc/mounts'" >&2
exit 1
fi
# handle ubifs and return since ubifs root is a char device but
# most of the commands below only work with block devices.
if [ "${FSTYPE}" = "ubifs" ]; then
manual_add_modules "${FSTYPE}"
return
fi
if [ "${root}" = "/dev/root" ] ; then
root="/dev/disk/by-uuid/"$(blkid -o value -s UUID ${root}) 2>/dev/null
fi
root="$(readlink -f ${root})"
# do not trust mount, check superblock
eval "$(/usr/lib/klibc/bin/fstype ${root})"
# check that fstype rootfs recognition
if [ "${FSTYPE}" = "unknown" ]; then
FSTYPE=$(blkid -o value -s TYPE "${root}")
if [ -z "${FSTYPE}" ]; then
echo "mkinitramfs: unknown fstype on root ${root}" >&2
echo "mkinitramfs: workaround is MODULES=most" >&2
echo "Error please report bug on initramfs-tools" >&2
exit 1
fi
fi
# Add rootfs
manual_add_modules "${FSTYPE}"
# lvm or luks root
if [ "${root#/dev/mapper/}" != "${root}" ] \
|| [ "${root#/dev/dm-}" != "${root}" ]; then
minor=$((0x$(stat --format "%T" ${root}) % 256))
block=$(ls -1 /sys/block/dm-${minor}/slaves | head -n 1)
# lvm on luks or luks on lvm, possibly lvm snapshots
while [ "${block#dm-}" != "${block}" ]; do
block=$(ls -1 /sys/block/${block}/slaves | head -n 1)
done
# lvm on md or luks on md
if [ "${block#md}" != "${block}" ]; then
block=$(sed -ne 's/multipath/[/' -e 's/linear/[/' -e 's/raid[0-9][0-9]*/[/' -e 's/\([hs]d[a-z][a-z]*\)[0-9][0-9]*/\1/g' -e '/^'${block}' :/s/^[^[]*\[ \([^\[]*\)\[.*$/\1/p' </proc/mdstat)
fi
# luks or lvm on cciss or ida
if [ "${block#cciss}" != "${block}" ] \
|| [ "${block#ida}" != "${block}" ]; then
block="${block%p*}"
else
block=${block%%[0-9]*}
fi
# md root new naming scheme /dev/md/X
elif [ "${root#/dev/md/}" != "${root}" ]; then
root=${root#/dev/md/}
# strip partion number
root=${root%%p[0-9]*}
# drop the partition number only for sdX and hdX devices
# and keep it for other devices like loop#, dm-# devices
block=$(sed -ne 's/multipath/[/' -e 's/linear/[/' -e 's/raid[0-9][0-9]*/[/' -e 's/\([hs]d[a-z][a-z]*\)[0-9][0-9]*/\1/g' -e '/^md'$root' :/s/^[^[]*\[ \([^\[]*\)\[.*$/\1/p' </proc/mdstat)
# md root /dev/mdX
elif [ "${root#/dev/md}" != "${root}" ]; then
root=${root#/dev/md}
# strip partion number
root=${root%%p[0-9]*}
# drop the partition number only for sdX and hdX devices
# and keep it for other devices like loop#, dm-# devices
block=$(sed -ne 's/multipath/[/' -e 's/linear/[/' -e 's/raid[0-9][0-9]*/[/' -e 's/\([hs]d[a-z][a-z]*\)[0-9][0-9]*/\1/g' -e '/^md'$root' :/s/^[^[]*\[ \([^\[]*\)\[.*$/\1/p' </proc/mdstat)
# cciss device
elif [ "${root#/dev/cciss/}" != "${root}" ]; then
block=${root#/dev/cciss/*}
block="cciss!${block%p*}"
# ida device
elif [ "${root#/dev/ida/}" != "${root}" ]; then
block=${root#/dev/ida/*}
block="ida!${block%p*}"
# loop root /dev/loopX
elif [ "${root#/dev/loop}" != "${root}" ]; then
root=${root#/dev/}
block=$(losetup -a \
| awk "/${root}/{print substr(\$3, 7, 3); exit}")
# Xen virtual device /dev/xvdX
elif [ "${root#/dev/xvd}" != "${root}" ]; then
block=${root#/dev/}
# Xen has a mode where only the individual partitions are
# registered with the kernel as well as the usual full disk
# with partition table scheme.
if [ ! -e /sys/block/${block} ] ; then
block=${block%%[0-9]*}
fi
# mmc root /dev/mmcblkXpX
elif [ "${root#/dev/mmcblk}" != "${root}" ]; then
block=${root#/dev/}
block=${block%%p[0-9]*}
# DAC960 - good old mylex raid - root dev format /dev/rd/cXdXpX
elif [ "${root#/dev/rd/c}" != "${root}" ]; then
block="rd!c${root#/dev/rd/c}"
block=${block%%p[0-9]*}
# etherd device
elif [ "${root#/dev/etherd/}" != "${root}" ]; then
block=${root#/dev/etherd/*}
block="etherd!${block%p*}"
# classical root device
else
block=${root#/dev/}
block=${block%%[0-9]*}
fi
# Error out if /sys lack block dev
if [ -z "${block}" ] || [ ! -e /sys/block/${block} ]; then
echo "mkinitramfs: for root ${root} missing ${block} /sys/block/ entry" >&2
echo "mkinitramfs: workaround is MODULES=most" >&2
echo "mkinitramfs: Error please report the bug" >&2
exit 1
fi
# sys walk ATA
root_dev_path=$(readlink -f /sys/block/${block}/device)
sys_walk_mod_add ${root_dev_path}
# catch old-style IDE
if [ -d "${DESTDIR}/lib/modules/${version}/kernel/drivers/ide" ]; then
sys_walk_modalias ${root_dev_path}
manual_add_modules ide-gd_mod
manual_add_modules ide-cd
fi
if [ -d "${DESTDIR}/lib/modules/${version}/kernel/drivers/scsi" ]; then
manual_add_modules sd_mod
fi
if [ -e /sys/bus/mmc/devices/ ]; then
manual_add_modules mmc_block
fi
if [ -e /sys/bus/virtio ] ; then
manual_add_modules virtio_pci
fi
if [ -e /sys/bus/i2o/devices/ ]; then
force_load i2o_block
force_load i2o_config
fi
if [ -e /sys/bus/ps3_system_bus/ ]; then
for x in ps3disk ps3rom ps3-gelic ps3_sys_manager; do
manual_add_modules "${x}"
done
fi
if [ -e /sys/bus/vio/ ]; then
for x in sunvnet sunvdc; do
manual_add_modules "${x}"
done
fi
}
# The modules "most" classes added per default to the initramfs
auto_add_modules()
{
case "${1:-}" in
base)
for x in ehci-hcd ohci-hcd uhci-hcd usbhid xhci hid-apple \
hid-cherry hid-logitech hid-microsoft hid-sunplus \
btrfs ext2 ext3 ext4 ext4dev isofs jfs nfs reiserfs udf xfs \
af_packet atkbd i8042 virtio_pci; do
manual_add_modules "${x}"
done
;;
net)
copy_modules_dir kernel/drivers/net \
appletalk arcnet bonding can hamradio irda pcmcia \
tokenring usb wan wimax wireless
;;
ide)
copy_modules_dir kernel/drivers/ide
;;
mmc)
copy_modules_dir kernel/drivers/mmc
;;
scsi)
copy_modules_dir kernel/drivers/scsi
for x in mptfc mptsas mptscsih mptspi zfcp; do
manual_add_modules "${x}"
done
;;
ata)
copy_modules_dir kernel/drivers/ata
;;
block)
copy_modules_dir kernel/drivers/block
;;
ubi)
for x in deflate zlib lzo ubi ubifs; do
manual_add_modules "${x}"
done
;;
ieee1394)
for x in ohci1394 sbp2; do
manual_add_modules "${x}"
done
;;
firewire)
for x in firewire-ohci firewire-sbp2; do
manual_add_modules "${x}"
done
;;
i2o)
for x in i2o_block; do
manual_add_modules "${x}"
done
;;
dasd)
for x in dasd_diag_mod dasd_eckd_mod dasd_fba_mod; do
manual_add_modules "${x}"
done
;;
usb_storage)
copy_modules_dir kernel/drivers/usb/storage
;;
*)
auto_add_modules base
auto_add_modules net
auto_add_modules ide
auto_add_modules scsi
auto_add_modules block
auto_add_modules ata
auto_add_modules i2o
auto_add_modules dasd
auto_add_modules ieee1394
auto_add_modules firewire
auto_add_modules mmc
auto_add_modules usb_storage
;;
esac
}
# 'depmod' only looks at symbol dependencies; there is no way for
# modules to declare explicit dependencies through module information,
# so dependencies on e.g. crypto providers are hidden. Until this is
# fixed, we need to handle those hidden dependencies.
hidden_dep_add_modules()
{
for dep in "lib/libcrc32c crc32c" "fs/ubifs/ubifs deflate zlib lzo"; do
set -- $dep
if [ -f "${DESTDIR}/lib/modules/${version}/kernel/$1.ko" ]; then
shift
for i in "$@" ; do
manual_add_modules "$i"
shift
done
fi
done
}
# mkinitramfs help message
usage()
{
cat >&2 << EOF
Usage: ${0} [OPTION]... -o outfile [version]
Options:
-c compress Override COMPRESS setting in initramfs.conf.
-d confdir Specify an alternative configuration directory.
-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
exit 1
}
# cache boot scripts order
cache_run_scripts()
{
DESTDIR=${1}
scriptdir=${2}
initdir=${DESTDIR}${scriptdir}
[ ! -d ${initdir} ] && return
runlist=$(get_prereq_pairs | tsort)
for crs_x in ${runlist}; do
[ -f ${initdir}/${crs_x} ] || continue
echo "${scriptdir}/${crs_x}" >> ${initdir}/ORDER
echo "[ -e /conf/param.conf ] && . /conf/param.conf" >> ${initdir}/ORDER
done
}