User:Charles17/custom initramfs

From Gentoo Wiki
Jump to: navigation, search

Initramfs for LVM2

Started from forums topic and based on Custom Initramfs

Kernel

For embedding the initramfs into the kernel image, the kernel option Initramfs source file(s) ( CONFIG_INITRAMFS_SOURCE ) needs to contain the root of the initramfs, (e.g. /usr/src/initramfs):

KERNEL linux-4.19
General setup  --->
    (/usr/src/initramfs) Initramfs source file(s)
user $grep CONFIG_INITRAMFS_SOURCE /usr/src/linux-4.19.97-gentoo/.config
CONFIG_INITRAMFS_SOURCE="/usr/src/initramfs"

Directory structure

(From Custom Initramfs)

root #mkdir --parents /usr/src/initramfs/{bin,dev,etc,lib,lib64,mnt/root,proc,root,sbin,sys}
root #cp --archive /dev/{null,console} /usr/src/initramfs/dev/

Looks like:

user $tree /usr/src/initramfs/
/usr/src/initramfs/
├── bin
├── dev
│   ├── console
│   └── null
├── etc
├── lib
├── lib64
├── mnt
│   └── root
├── proc
├── root
├── sbin
└── sys

Adding busybox

user $ldd /bin/busybox
        not a dynamic executable
root #lddtree --copy-to-tree /usr/src/initramfs /bin/busybox

(The --copy-to-tree option depends on app-misc/pax-utils built with the python USE flag.)

user $tree /usr/src/initramfs/
/usr/src/initramfs/
├── bin
│   └── busybox
├── dev
│   ├── console
│   └── null
├── etc
├── lib
├── lib64
├── mnt
│   └── root
├── proc
├── root
├── sbin
└── sys
user $file /usr/src/initramfs/bin/busybox
/usr/src/initramfs/bin/busybox: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, for GNU/Linux 2.6.32, stripped

Adding LVM2

Here LVM2 is used without the static-libs USE flag.

user $ldd /sbin/lvm
        linux-vdso.so.1 (0x00007fffb07ea000)
        libdevmapper-event.so.1.02 => /lib64/libdevmapper-event.so.1.02 (0x00007f3f1efc5000)
        libudev.so.1 => /lib64/libudev.so.1 (0x00007f3f1ef9e000)
        libdl.so.2 => /lib64/libdl.so.2 (0x00007f3f1ef98000)
        libblkid.so.1 => /lib64/libblkid.so.1 (0x00007f3f1ef44000)
        libdevmapper.so.1.02 => /lib64/libdevmapper.so.1.02 (0x00007f3f1eeeb000)
        libaio.so.1 => /lib64/libaio.so.1 (0x00007f3f1eee6000)
        libreadline.so.7 => /lib64/libreadline.so.7 (0x00007f3f1ee94000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f3f1ecc6000)
        libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f3f1eca4000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f3f1f42d000)
        libuuid.so.1 => /lib64/libuuid.so.1 (0x00007f3f1ec9b000)
        libm.so.6 => /lib64/libm.so.6 (0x00007f3f1eb57000)
        libtinfow.so.6 => /lib64/libtinfow.so.6 (0x00007f3f1eb19000)
root #lddtree --copy-to-tree /usr/src/initramfs /sbin/lvm
user $tree /usr/src/initramfs
/usr/src/initramfs
├── bin
│   └── busybox
├── dev
│   ├── console
│   └── null
├── etc
├── lib
├── lib64
│   ├── ld-linux-x86-64.so.2
│   ├── libaio.so.1
│   ├── libblkid.so.1
│   ├── libc.so.6
│   ├── libdevmapper-event.so.1.02
│   ├── libdevmapper.so.1.02
│   ├── libdl.so.2
│   ├── libm.so.6
│   ├── libpthread.so.0
│   ├── libreadline.so.7
│   ├── libtinfow.so.6
│   ├── libudev.so.1
│   └── libuuid.so.1
├── mnt
│   └── root
├── proc
├── root
├── sbin
│   └── lvm
└── sys

Creating the init script

root #vim /usr/src/initramfs/init
#!/bin/busybox sh


# Install symlinks to all busybox applets first.
# /bin/busybox mkdir -p /usr/sbin /usr/bin
# /bin/busybox --install -s


rescue_shell() {
	printf '\e[1;31m' # bold red foreground
	printf "$1 Dropping you to a shell."
	printf "\e[00m\n" # normal colour foreground
	# load the keymap
	[ -f /keymap ] && loadkmap < /keymap
	exec setsid cttyhack /bin/sh
}

# initialise
mount -t proc none /proc || rescue_shell "mount /proc failed."
mount -t sysfs none /sys || rescue_shell "mount /sys failed."
mount -t devtmpfs none /dev || rescue_shell "mount /dev failed."

# set hardcoded default values
crypt_root=""
root=""
resume=""
mount_ro_rw='ro'

# parse kernel command line
for p in $(cat /proc/cmdline); do
	case "${p}" in
#		crypt_root=*)
#			crypt_root="${p#*=}"
#			;;
		root=*)
			root="${p#*=}"
			;;
		resume=*)
			resume="${p#*=}"
			;;
		ro|rw)
			mount_ro_rw="${p}"
			;;
	esac
done

# echo root="${root}"
# echo resume="${resume}"
# sleep 30

# # decrypt
# #  convert UUID or LABEL to device node
# crypt_root="$(findfs "${crypt_root}")"
# #  decryption is first tried using the key file /crypto_key.bin
# #  if this fails, prompt for a password
# cryptsetup open "${crypt_root}" lvm --type luks --key-file /crypto_key.bin || \
# 	cryptsetup open "${crypt_root}" lvm --type luks || \
# 	rescue_shell "Decryption failed."

# activate lvm
#  create /dev/mapper/control
lvm vgscan --mknodes || rescue_shell "vgscan failed."
#  activate all LVM volumes
lvm vgchange --sysinit -a ly || rescure_shell "vgchange failed."
#  create device nodes for the volumes
lvm vgscan --mknodes || rescue_shell "vgscan failed."

# mount the real root
#  convert UUID or LABEL to device node
# root="$(findfs "${root}")"
mount -o "${mount_ro_rw}" "${root}" /mnt/root || rescue_shell "mount ${root} failed."

# enable resume from hibernate
if [ -n "${resume}" ]; then
	# copy the major:minor of the swap block device into /sys/power/resume
	printf '%u:%u\n' $(stat -L -c '0x%t 0x%T' "${resume}") > /sys/power/resume || \
		rescue_shell "Activating resume failed."
fi

# clean up
umount /proc
umount /sys
umount /dev

# boot the real system
exec switch_root /mnt/root /sbin/init

Recompiling the kernel

user $cd /usr/src/linux-4.19.97-gentoo
root #make && make modules_install

External resources