Difference between revisions of "Creating an Initramfs"
From CBLFS
Jump to navigationJump to searchMichael.six (talk | contribs) |
Michael.six (talk | contribs) |
||
(4 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
− | {{Package-Introduction|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 | + | {{Package-Introduction|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 disk is formatted reiserfs}} |
== Dependencies == | == Dependencies == | ||
Line 12: | Line 12: | ||
#!/bin/bash | #!/bin/bash | ||
errmsg(){ | errmsg(){ | ||
− | + | cat << EOT | |
[ERROR] $@ | [ERROR] $@ | ||
EOT | EOT | ||
} | } | ||
killme(){ | killme(){ | ||
− | + | errmsg "$@" | |
− | + | errmsg "Exiting ..." | |
− | + | exit 1 | |
} | } | ||
helpme(){ | helpme(){ | ||
− | + | cat << EOT | |
$(basename ${0}) is a script to automagically make | $(basename ${0}) is a script to automagically make | ||
a gzip compressed cpio archive containsing busybox | a gzip compressed cpio archive containsing busybox | ||
which can act as an initrd. | which can act as an initrd. | ||
− | + | -c - remove initramfs-tree before creating the | |
− | + | initramfs | |
− | + | -v|--verbose - use verbose messages | |
− | + | -k <version> - use modules from kernel <version> | |
− | + | -m <arg1,arg2> - comma separated list of additional modules | |
− | + | besides the ones contained in the file | |
− | + | /etc/sysconfig/mkinitramfs.modules to add | |
− | + | to the initramfs archive | |
− | + | -o <arg> - output finished archive to <arg> instead | |
− | + | of /boot/initramfs.igz | |
− | + | -r|--rootfs - use device as root device | |
− | |||
− | |||
Example: | Example: | ||
Line 50: | Line 48: | ||
} | } | ||
usage(){ | usage(){ | ||
− | + | cat << EOT | |
− | $(basename ${0}) -c -k 2.6.30.2 -m ext3 -r /dev/hda3 - | + | $(basename ${0}) -c -k 2.6.30.2 -m ext3 -r /dev/hda3 -o /boot/initramfs.igz-2.6.30.2 |
EOT | EOT | ||
} | } | ||
vrbmsg(){ | vrbmsg(){ | ||
− | + | if [ "${initramfs_use_verbose}" ]; then | |
− | + | cat << EOT | |
$@ | $@ | ||
EOT | EOT | ||
− | + | fi | |
} | } | ||
fnd_mod(){ | fnd_mod(){ | ||
− | + | module="$(find /lib/modules/${initramfs_use_kernel} -name ${1}.ko)" | |
− | + | if [ ! -n "${module}" ]; then | |
− | + | module="$(find /lib/modules/${initramfs_use_kernel} -name ${1}.ko.gz)" | |
− | + | fi | |
− | + | cat << EOT | |
${module} | ${module} | ||
EOT | EOT | ||
− | + | unset module | |
} | } | ||
initramfs_use_kernel="$(uname -r)" | initramfs_use_kernel="$(uname -r)" | ||
Line 76: | Line 74: | ||
initramfs_use_rootfstype="ext3" | initramfs_use_rootfstype="ext3" | ||
until [ -z "${1}" ]; do | until [ -z "${1}" ]; do | ||
− | + | case "${1}" in | |
− | + | -c) | |
− | + | rm -rf /boot/initramfs-tree | |
− | + | ;; | |
− | + | -v|--verbose) | |
− | + | initramfs_use_verbose='true' | |
− | + | ;; | |
− | + | -k) | |
− | + | initramfs_use_kernel="${2}" | |
− | + | shift | |
− | + | ;; | |
− | + | -m) | |
− | + | initramfs_use_modules="${2}" | |
− | + | shift | |
− | + | ;; | |
− | + | -o) | |
− | + | initramfs_output="${2}" | |
− | + | shift | |
− | + | ;; | |
− | + | -r|--rootfs) | |
− | + | initramfs_use_rootfs="${2}" | |
− | + | shift | |
− | + | ;; | |
− | + | -h|--help) | |
− | + | helpme | |
− | + | usage | |
− | + | exit 0 | |
− | + | ;; | |
− | + | -u|--usage) | |
− | + | usage | |
− | + | exit 0 | |
− | + | ;; | |
− | + | esac | |
− | + | shift | |
− | |||
− | |||
− | |||
− | |||
done | done | ||
for mkinitramfs_tool in /bin/busybox /usr/bin/cpio /bin/gzip; do | for mkinitramfs_tool in /bin/busybox /usr/bin/cpio /bin/gzip; do | ||
− | + | if [ ! -x "${mkinitramfs_tool}" ]; then | |
− | + | killme "Required tool ${mkinitramfs_tool} missing!" | |
− | + | fi | |
done | done | ||
if [ ! -d "$(dirname ${initramfs_output})" ]; then | if [ ! -d "$(dirname ${initramfs_output})" ]; then | ||
− | + | killme "Can not create ${initramfs_output}" | |
fi | fi | ||
if [ ! -d '/boot/initramfs-tree' ]; then | if [ ! -d '/boot/initramfs-tree' ]; then | ||
− | + | mkdir /boot/initramfs-tree | |
− | + | mkdir /boot/initramfs-tree/{bin,sbin,lib,etc,proc,root,sys,mnt} | |
− | + | mkdir /boot/initramfs-tree/lib/modules/${initramfs_use_kernel} | |
− | + | ln -s . /boot/initramfs-tree/usr | |
fi | fi | ||
if [ -f /etc/sysconfig/initramfs.modules ]; then | if [ -f /etc/sysconfig/initramfs.modules ]; then | ||
− | + | cat /etc/sysconfig/initramfs.modules | while read line; do | |
− | + | if [ -n "${line}" -a "$(head -c1 <<<${line})" != "#" ]; then | |
− | + | module="$(fnd_mod ${line})" | |
− | + | if [ -n "${module}" ]; then | |
− | + | vrbmsg "Found ${module}" | |
− | + | case "${module}" in | |
− | + | *.ko) | |
− | + | cat ${module} > /boot/initramfs-tree/lib/modules/${initramfs_use_kernel}/$(basename ${module}) | |
− | + | ;; | |
− | + | *.ko.gz) | |
− | + | gzip -dc ${module} > /boot/initramfs-tree/lib/modules${initramfs_use_kernel}/$(basename ${module} .gz) | |
− | + | :; | |
− | + | esac | |
− | + | else | |
− | + | errmsg "Couldn't find ${line}" | |
− | + | fi | |
− | + | fi | |
− | + | done | |
fi | fi | ||
if [ -n "${initramfs_use_modules}" ]; then | if [ -n "${initramfs_use_modules}" ]; then | ||
− | + | for line in ${initramfs_use_modules//,/ }; do | |
− | + | module="$(fnd_mod ${line})" | |
− | + | if [ -n "${module}" ]; then | |
− | + | vrbmsg "Found ${module}" | |
− | + | case "${module}" in | |
− | + | *.ko) | |
− | + | cat ${module} > /boot/initramfs-tree/lib/modules/${initramfs_use_kernel}/$(basename ${module}) | |
− | + | echo "$(basename ${module} .ko)" >> /boot/initramfs-tree/etc/modules | |
− | + | ;; | |
− | + | *.ko.gz) | |
− | + | gzip -dc ${module} > /boot/initramfs-tree/lib/modules/${initramfs_use_kernel}/$(basename ${module} .gz) | |
− | + | echo "$(basename ${module} .ko.gz)" >> /boot/initramfs-tree/etc/modules | |
− | + | ;; | |
− | + | esac | |
− | + | else | |
− | + | errmsg "Couldn't find ${line}" | |
− | + | fi | |
− | + | done | |
fi | fi | ||
cat /bin/busybox > /boot/initramfs-tree/bin/busybox | cat /bin/busybox > /boot/initramfs-tree/bin/busybox | ||
Line 182: | Line 176: | ||
/bin/busybox clear | /bin/busybox clear | ||
/bin/busybox cat << END | /bin/busybox cat << END | ||
− | This system | + | This system uses Community Beyond Linux From Scratch |
<http://cblfs.cross-lfs.org/> | <http://cblfs.cross-lfs.org/> | ||
END | END | ||
Line 206: | Line 200: | ||
# would return "/sbin/init" | # would return "/sbin/init" | ||
get_opt() { | get_opt() { | ||
− | + | echo "\$@" | /bin/busybox cut -d "=" -f 2 | |
} | } | ||
# Defaults | # Defaults | ||
Line 213: | Line 207: | ||
runlevel="3" | runlevel="3" | ||
for i in \$(cat /proc/cmdline); do | 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 | done | ||
# Mount the root device | # Mount the root device | ||
− | mount -o ro | + | mount -o ro "\${root}" /root |
− | if [ -f /root/lfs-root.img ]; then | + | # Below is an example of how to use the initramfs |
− | + | # to load clfs or lfs from a disk image | |
− | + | #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 && | |
− | + | # mkdir -p /root/mnt/"\${BNROOT}" && | |
− | fi | + | # mount /mnt/"\${BNROOT}" /root/mnt/"\${BNROOT}" |
− | if | + | # unset BNROOT |
− | + | #fi | |
− | + | 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 | fi | ||
echo "Failed 'exec switch_root /root \\"\${init}\\" \\"\${runlevel}\\"'" | echo "Failed 'exec switch_root /root \\"\${init}\\" \\"\${runlevel}\\"'" | ||
Line 249: | Line 245: | ||
EOT | EOT | ||
chmod 755 /boot/initramfs-tree/init | chmod 755 /boot/initramfs-tree/init | ||
+ | ( cd /boot/initramfs-tree | ||
+ | find . | cpio -H newc -o | gzip -9c > ${initramfs_output} | ||
+ | ) || exit 1 | ||
EOF | EOF | ||
chmod 755 /usr/sbin/mkinitramfs | chmod 755 /usr/sbin/mkinitramfs |
Latest revision as of 21:55, 30 October 2009
Contents
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 disk 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 << "EOF" #!/bin/bash errmsg(){ cat << EOT [ERROR] $@ EOT } killme(){ errmsg "$@" errmsg "Exiting ..." exit 1 } helpme(){ cat << EOT $(basename ${0}) is a script to automagically make a gzip compressed cpio archive containsing busybox which can act as an initrd. -c - remove initramfs-tree before creating the initramfs -v|--verbose - use verbose messages -k <version> - use modules from kernel <version> -m <arg1,arg2> - comma separated list of additional modules besides the ones contained in the file /etc/sysconfig/mkinitramfs.modules to add to the initramfs archive -o <arg> - output finished archive to <arg> instead of /boot/initramfs.igz -r|--rootfs - use device as root device Example: EOT } usage(){ cat << EOT $(basename ${0}) -c -k 2.6.30.2 -m ext3 -r /dev/hda3 -o /boot/initramfs.igz-2.6.30.2 EOT } vrbmsg(){ if [ "${initramfs_use_verbose}" ]; then cat << EOT $@ EOT fi } fnd_mod(){ module="$(find /lib/modules/${initramfs_use_kernel} -name ${1}.ko)" if [ ! -n "${module}" ]; then module="$(find /lib/modules/${initramfs_use_kernel} -name ${1}.ko.gz)" fi cat << EOT ${module} EOT unset module } initramfs_use_kernel="$(uname -r)" initramfs_output="/boot/initramfs.igz" initramfs_use_rootfs="/dev/hda2" initramfs_use_rootfstype="ext3" until [ -z "${1}" ]; do case "${1}" in -c) rm -rf /boot/initramfs-tree ;; -v|--verbose) initramfs_use_verbose='true' ;; -k) initramfs_use_kernel="${2}" shift ;; -m) initramfs_use_modules="${2}" shift ;; -o) initramfs_output="${2}" shift ;; -r|--rootfs) initramfs_use_rootfs="${2}" shift ;; -h|--help) helpme usage exit 0 ;; -u|--usage) usage exit 0 ;; esac shift done for mkinitramfs_tool in /bin/busybox /usr/bin/cpio /bin/gzip; do if [ ! -x "${mkinitramfs_tool}" ]; then killme "Required tool ${mkinitramfs_tool} missing!" fi done if [ ! -d "$(dirname ${initramfs_output})" ]; then killme "Can not create ${initramfs_output}" fi if [ ! -d '/boot/initramfs-tree' ]; then mkdir /boot/initramfs-tree mkdir /boot/initramfs-tree/{bin,sbin,lib,etc,proc,root,sys,mnt} mkdir /boot/initramfs-tree/lib/modules/${initramfs_use_kernel} 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 module="$(fnd_mod ${line})" if [ -n "${module}" ]; then vrbmsg "Found ${module}" case "${module}" in *.ko) cat ${module} > /boot/initramfs-tree/lib/modules/${initramfs_use_kernel}/$(basename ${module}) ;; *.ko.gz) gzip -dc ${module} > /boot/initramfs-tree/lib/modules${initramfs_use_kernel}/$(basename ${module} .gz) :; esac else errmsg "Couldn't find ${line}" fi fi done fi if [ -n "${initramfs_use_modules}" ]; then for line in ${initramfs_use_modules//,/ }; do module="$(fnd_mod ${line})" if [ -n "${module}" ]; then vrbmsg "Found ${module}" case "${module}" in *.ko) cat ${module} > /boot/initramfs-tree/lib/modules/${initramfs_use_kernel}/$(basename ${module}) echo "$(basename ${module} .ko)" >> /boot/initramfs-tree/etc/modules ;; *.ko.gz) gzip -dc ${module} > /boot/initramfs-tree/lib/modules/${initramfs_use_kernel}/$(basename ${module} .gz) echo "$(basename ${module} .ko.gz)" >> /boot/initramfs-tree/etc/modules ;; esac else errmsg "Couldn't find ${line}" fi done fi cat /bin/busybox > /boot/initramfs-tree/bin/busybox chmod 755 /boot/initramfs-tree/bin/busybox cat > /boot/initramfs-tree/init << EOT #!/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 << END This system uses Community Beyond Linux From Scratch <http://cblfs.cross-lfs.org/> END # 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="${initramfs_use_rootfs}" 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 of how to use the initramfs # to load clfs or lfs from a disk image #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 && # mkdir -p /root/mnt/"\${BNROOT}" && # mount /mnt/"\${BNROOT}" /root/mnt/"\${BNROOT}" # unset BNROOT #fi 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 echo "Failed 'exec switch_root /root \\"\${init}\\" \\"\${runlevel}\\"'" exec sh EOT chmod 755 /boot/initramfs-tree/init ( cd /boot/initramfs-tree find . | cpio -H newc -o | gzip -9c > ${initramfs_output} ) || exit 1 EOF chmod 755 /usr/sbin/mkinitramfs