Creating an Initramfs
From CBLFS
Introduction to Creating an Initramfs
The mkinitramfs script creates a gzip compressed cpio archive using busybox and a simple shell init script, which can be used in place of an initrd to do such things as load kernel modules before the system boots, in order to access functionality that is not compiled into the kernel, and therefore must be loaded, such as usb disks, scsi disks, etc. This is different than loading modules automatically at boot time, because those are loaded after the root disk is mounted, fsck'd etc, and typically an initrd contains modules which are loaded into the kernel before anything else, to fascilitate mounting the root fs. IE kernel doesn't have reiserfs support compiled in, but your root fs is formatted reiserfs
Project Homepage: Unknown
Dependencies
Required
The init script created for the initramfs will drop to the shell in busybox if there is an error, while only a few things are actually needed for the init to function, while compiling busybox you might want to keep in mind that it may need additional functionality to be able to work properly if the initramfs drops to the shell. Also this assumes that busybox is compiled statically linked, if that is not the case, additional libraries will be required to be added to the initramfs-tree. To test this run 'file /bin/busybox'. If file reports it as dynamically linked, running 'ldd /bin/busybox' should help you determine what libraries may be needed.
Creating the mkinitramfs script
cat > /usr/sbin/mkinitramfs << "END"
#!/bin/bash
# This is a bash script to create a busybox
# based gzipped cpio archive to be used as
# an initrd
INITRAMFS_USE_KERNEL="$(uname -r)"
INITRAMFS_OUTPUT="/boot/initramfs.igz"
until [ -z "${1}" ]; do
case ${1} in
-c) rm -rf /boot/initramfs-tree
;;
-k)
INITRAMFS_USE_KERNEL="${2}"
shift
;;
-m)
INITRAMFS_USE_MODULES="${2}"
shift
;;
-v|--verbose)
INITRAMFS_USE_VERBOSE="true"
;;
-m)
INITRAMFS_USE_MODULES="${2}"
shift
;;
-o)
INITRAMFS_OUTPUT="${2}"
shift
;;
esac
shift
done
ermsg(){
cat << EOF
[ERROR] $@
EOF
}
killme(){
ermsg "$@"
ermsg "Exiting ..."
exit 1
}
vrbmsg(){
if [ "${INITRAMFS_USE_VERBOSE}" = 'true' ]; then
cat << EOF
$@
EOF
fi
}
if [ ! -x /bin/busybox ]; then
killme "The initramfs needs busybox ..."
fi
if [ ! -x /usr/bin/cpio ]; then
killme "The initramfs needs cpio ..."
fi
if [ ! -x /bin/gzip ]; then
killme "The initramfs needs gzip ..."
fi
rm -f /tmp/mkinitramfs.modules
rm -f /tmp/mkinitramfs.moddeps
get_moddeps(){
if [ -f /lib/modules/${INITRAMFS_USE_KERNEL}/modules.dep ]; then
grep "${1}": /lib/modules/${INITRAMFS_USE_KERNEL}/modules.dep \
| sed -e "s|${1}:||"
else
cat << EOF
get_moddeps failure
EOF
fi
}
fnd_module(){
fnd_mod_outpt="$(find /lib/modules/${INITRAMFS_USE_KERNEL} -name ${1}.ko)"
if [ -z "${fnd_mod_oupt}" ]; then
fnd_mod_outpt="$(find /lib/modules/${INITRAMFS_USE_KERNEL} -name ${1}.ko.gz)"
fi
echo ${fnd_mod_outpt} | sed -e "s|/lib/modules/${INITRAMFS_USE_KERNEL}/||"
}
if [ ! -d /boot/initramfs-tree ]; then
mkdir /boot/initramfs-tree &&
mkdir /boot/initramfs-tree/{etc,bin,sbin,lib} &&
mkdir /boot/initramfs-tree/{proc,root,mnt,sys}
mkdir /boot/initramfs-tree/lib/modules \
|| killme "Problem making the initramfs-tree ..."
ln -s . /boot/initramfs-tree/usr
fi
if [ -f /etc/sysconfig/initramfs.modules ]; then
cat /etc/sysconfig/initramfs.modules | while read line; do
if [ -n "${line}" -a "$(head -c1 <<<${line})" != "#" ]; then
if [ -n "$(fnd_module ${line})" ]; then
fnd_module ${line} >> /tmp/mkinitramfs.modules
else
ermsg "Couldn't find module ${line}"
fi
fi
done
fi
if [ -n "${INITRAMFS_USE_MODULES}" ]; then
for ITEM in $(echo ${INITRAMFS_USE_MODULES//,/ }); do
if [ -n "$(fnd_module ${ITEM})" ]; then
fnd_module ${ITEM} >> /tmp/mkinitramfs.modules
else
ermsg "Couldn't find module ${ITEM}"
fi
done
unset ITEM
fi
touch /tmp/mkinitramfs.moddeps
if [ -f /tmp/mkinitramfs.modules ]; then
cat /tmp/mkinitramfs.modules | while read IMOD; do
vrbmsg "generating module dependencies for ${IMOD}" &&
if [ "$(get_moddeps ${IMOD})" != "get_moddeps failure" ]; then
if [ -n "$(get_moddeps ${IMOD})" ]; then
for ITEM in $(get_moddeps ${IMOD}); do
if [ -z "$(grep ${IMOD} /tmp/mkinitramfs.moddeps)" ]; then
echo "${ITEM}" >> /tmp/mkinitramfs.moddeps
fi
done
unset ITEM
fi
fi
if [ -z "$(grep ${IMOD} /tmp/mkinitramfs.moddeps)" ]; then
echo "${IMOD}" >> /tmp/mkinitramfs.moddeps
fi
done
fi
unset IMOD
if [ -f /tmp/mkinitramfs.moddeps ]; then
cat /tmp/mkinitramfs.moddeps | while read line; do
case ${line} in
*.ko.gz)
gzip -dc /lib/modules/${INITRAMFS_USE_KERNEL}/${line} \
> /boot/initramfs-tree/lib/modules/$(basename ${line} .ko.gz).ko
echo "$(basename ${line} .ko.gz)" >> /boot/initramfs-tree/etc/modules
;;
*.ko)
cat /lib/modules/${MKINITRAMFS_USE_KERNEL}/${line} \
> /boot/initramfs-tree/lib/modules/$(basename ${line})
echo "$(basename ${line} .ko)" >> /boot/initramfs-tree/etc/modules
;;
esac
done
fi
# Now for the init
cat << "EOT" >/boot/initramfs-tree/init
#!/bin/busybox sh
# Mount things which are needed by this script
/bin/busybox mount -t proc proc /proc
/bin/busybox mount -t sysfs sysfs /sys
# Disable kernel messages from popping up on
# the screen
/bin/busybox echo 0 > /proc/sys/kernel/printk
# Clear the screen
/bin/busybox clear
/bin/busybox cat << EOF
This system is uses Community Beyond Linux From Scratch
<http://cblfs.cross-lfs.org/>
EOF
# Create the symlinks to busybox
/bin/busybox --install -s
# Create device nodes
/bin/busybox mknod /dev/null c 1 3
/bin/busybox mknod /dev/tty c 5 0
# Check for modules
if [ -f /etc/modules ]; then
/bin/busybox depmod /lib/modules
/bin/busybox cat /etc/modules | while read line; do
if [ -n "${line}" ]; then
/bin/busybox modprobe ${line/.ko/}
fi
done
fi
# Sleep for devices to connect, like USB
/bin/busybox sleep 5
/bin/busybox mdev -s
# Function for parsing command line options with
# '=' in them. Ex. get_opt("init=/sbin/init")
# would return "/sbin/init"
get_opt() {
echo "$@" | /bin/busybox cut -d "=" -f 2
}
# Defaults
init="/sbin/init"
root="/dev/hda1"
runlevel="3"
for i in $(cat /proc/cmdline); do
case ${i} in
root\=*)
root=$(get_opt ${i})
;;
init\=*)
init=$(get_opt ${i})
;;
runlevel\=*)
runlevel=$(get_opt ${i})
;;
esac
done
# Mount the root device
mount -o ro "${root}" /root
# Below is an example for loading a disk image from
# a linux partition
if [ -f /root/lfs-root.img ]; then
BNROOT=$(/bin/busybox basename "${root}")
umount root
mkdir -p /mnt/"${BNROOT}" &&
mount "${root}" /mnt/"${BNROOT}" &&
mount -o loop /mnt/"${BNROOT}"/lfs-root.img /root &&
# Make sure that we don't lose access to the partition
# containing the disk image
mkdir -p /root/mnt/"${BNROOT}" &&
mount /mnt/"${BNROOT}" /root/mnt/"${BNROOT}"
unset BNROOT
fi
# Check if the $init exists, and is executable
if [[ -x "/root/${init}" ]]; then
# Unmount all other mounts so that the ram used by
# the initramfs can be cleared after switch_root
umount /sys /proc
# Switch to the new root and execute the init at
# the specified runlevel
exec switch_root /root "${init}" "${runlevel}"
fi
# This will only be run if the exec above failed
echo "Failed 'exec switch_root /root \"${init}\" \"${runlevel}\"'"
exec sh
EOT
chmod 0755 /boot/initramfs-tree/init
cat /bin/busybox > /boot/initramfs-tree/bin/busybox
chmod 0755 /boot/initramfs-tree/bin/busybox
if [ ! -d "$(dirname ${INITRAMFS_OUTPUT})" ]; then
killme "Cannot create ${INITRAMFS_OUTPUT}"
fi
( cd /boot/initramfs-tree &&
find . | cpio -H newc -o | gzip -9c > ${INITRAMFS_OUTPUT} || exit 1
) || exit 1
rm -f /tmp/mkinitramfs.modules
rm -f /tmp/mkinitramfs.moddeps
unset INITRAMFS_OUTPUT INITRAMFS_USE_KERNEL INITRAMFS_USE_MODULES INITRAMFS_USE_KERNEL
END
chmod 0755 /usr/sbin/mkinitramfs