Raspberry Pi Custom Installation/Kernel
To be able to boot from LVM a custom kernel is required with an initial ram disk
On raspbian a few things need to be installed and set up
root@localhost ~ # apt install bc git ncurses-devroot@localhost ~ #
modprobe configsDownload the kernel source
root@localhost ~ # cd /usr/srcroot@localhost ~ # wget -O rpi-4.9.y.zip https://codeload.github.com/raspberrypi/linux/zip/rpi-4.9.yroot@localhost ~ #
unzip rpi-4.9.y.zipPrepare and configure the kernel
root@localhost /usr/src # cd /usr/src/linux-rpi-4.9.yroot@localhost /usr/src #
make -j5 -l5 mrproperFor building upon the current running kernel copy the configuration from the procfs
root@localhost /usr/src/linux-rpi-4.9.y # zcat /proc/config.gz > .configFor the default rpi config use arch/arm/configs/bcmrpi_defconfig
root@localhost /usr/src/linux-rpi-4.9.y # cp arch/arm/configs/bcmrpi_defconfig .configFor the default rpi 3 config use arch/arm64/configs/bcmrpi64_defconfig
root@localhost /usr/src/linux-rpi-4.9.y # cp arch/arm64/configs/bcmrpi3_defconfig .configConfigure the kernel
root@localhost /usr/src/linux-rpi-4.9.y # make -j5 -l5 menuconfigSet LVM to compile into kernel and enabled initrd to be able to add custom initrd file
General setup --->
[*] Initial RAM filesystem and RAM disk (initramfs/initrd) support
[*] Support initial ramdisks compressed using gzip (NEW)
Device Drivers --->
Multiple devices driver support (RAID and LVM) --->
<*> Device mapper support
<*> Crypt target support
<*> Snapshot target
<*> Mirror target
<*> Multipath target
<*> I/O Path Selector based on the number of in-flight I/Os
<*> I/O Path Selector based on the service time
Compile the kernel and install modules
root@localhost /usr/src/linux-rpi-4.9.y # make -j5 -l5 && make -j5 -l5 modules_installCopy the kernel based on your previous choice
root@localhost /usr/src/linux-rpi-4.9.y # cp -v arch/arm/boot/zImage /boot/linux-4.9.y-raspbianOr
root@localhost /usr/src/linux-rpi-4.9.y # cp -v arch/arm/boot/zImage /boot/linux-4.9.y-rpiOr
root@localhost /usr/src/linux-rpi-4.9.y # cp -v arch/arm64/boot/zImage /boot/linux-4.9.y-rpi64Create an initramfs directory
root@localhost /usr/src/linux-rpi-4.9.y # mkdir -p /usr/src/initramfsroot@localhost /usr/src/linux-rpi-4.9.y #
cd /usr/src/initramfsInstall a static builds of busybox and e2fsck-static
root@localhost /usr/src/initramfs # apt install busybox-static e2fsck-staticCollect the files needed for the initial ram disk
root@localhost /usr/src/initramfs # touch initramfs_list# directory structure dir /bin 755 0 0 dir /dev 755 0 0 dir /etc 755 0 0 dir /lib 755 0 0 dir /lib64 755 0 0 dir /mnt 755 0 0 dir /mnt/root 755 0 0 dir /proc 755 0 0 dir /root 700 0 0 dir /sbin 755 0 0 dir /sys 755 0 0 dir /usr 755 0 0 dir /var 755 0 0 # busybox file /bin/busybox /bin/busybox 755 0 0 # fsck file /sbin/e2fsck /sbin/e2fsck.static 755 0 0 file /sbin/fsck /sbin/fsck 755 0 0 file /sbin/fsck.cramfs /sbin/fsck.cramfs 755 0 0 file /sbin/fsck.fat /sbin/fsck.fat 755 0 0 file /sbin/fsck.minix /sbin/fsck.minix 755 0 0 slink /sbin/dosfsck /sbin/fsck.fat 755 0 0 slink /sbin/fsck.ext2 /sbin/e2fsck 755 0 0 slink /sbin/fsck.ext3 /sbin/e2fsck 755 0 0 slink /sbin/fsck.ext4 /sbin/e2fsck 755 0 0 slink /sbin/fsck.msdos /sbin/fsck.fat 755 0 0 slink /sbin/fsck.vfat /sbin/fsck.fat 755 0 0 # lvm file /sbin/lvm /sbin/lvm 755 0 0 slink /sbin/lvchange /sbin/lvm 755 0 0 slink /sbin/lvconvert /sbin/lvm 755 0 0 slink /sbin/lvcreate /sbin/lvm 755 0 0 slink /sbin/lvdisplay /sbin/lvm 755 0 0 slink /sbin/lvextend /sbin/lvm 755 0 0 slink /sbin/lvmchange /sbin/lvm 755 0 0 slink /sbin/lvmconfig /sbin/lvm 755 0 0 slink /sbin/lvmdiskscan /sbin/lvm 755 0 0 slink /sbin/lvmsadc /sbin/lvm 755 0 0 slink /sbin/lvmsar /sbin/lvm 755 0 0 slink /sbin/lvreduce /sbin/lvm 755 0 0 slink /sbin/lvremove /sbin/lvm 755 0 0 slink /sbin/lvrename /sbin/lvm 755 0 0 slink /sbin/lvresize /sbin/lvm 755 0 0 slink /sbin/lvs /sbin/lvm 755 0 0 slink /sbin/lvscan /sbin/lvm 755 0 0 slink /sbin/pvchange /sbin/lvm 755 0 0 slink /sbin/pvck /sbin/lvm 755 0 0 slink /sbin/pvcreate /sbin/lvm 755 0 0 slink /sbin/pvdisplay /sbin/lvm 755 0 0 slink /sbin/pvmove /sbin/lvm 755 0 0 slink /sbin/pvremove /sbin/lvm 755 0 0 slink /sbin/pvresize /sbin/lvm 755 0 0 slink /sbin/pvs /sbin/lvm 755 0 0 slink /sbin/pvscan /sbin/lvm 755 0 0 slink /sbin/vgcfgbackup /sbin/lvm 755 0 0 slink /sbin/vgcfgrestore /sbin/lvm 755 0 0 slink /sbin/vgchange /sbin/lvm 755 0 0 slink /sbin/vgck /sbin/lvm 755 0 0 slink /sbin/vgconvert /sbin/lvm 755 0 0 slink /sbin/vgcreate /sbin/lvm 755 0 0 slink /sbin/vgdisplay /sbin/lvm 755 0 0 slink /sbin/vgexport /sbin/lvm 755 0 0 slink /sbin/vgextend /sbin/lvm 755 0 0 slink /sbin/vgimport /sbin/lvm 755 0 0 slink /sbin/vgmerge /sbin/lvm 755 0 0 slink /sbin/vgmknodes /sbin/lvm 755 0 0 slink /sbin/vgreduce /sbin/lvm 755 0 0 slink /sbin/vgremove /sbin/lvm 755 0 0 slink /sbin/vgrename /sbin/lvm 755 0 0 slink /sbin/vgs /sbin/lvm 755 0 0 slink /sbin/vgscan /sbin/lvm 755 0 0 slink /sbin/vgsplit /sbin/lvm 755 0 0 # libraries required by fsck, e2fsck file /lib/arm-linux-gnueabihf/libc.so.6 /lib/arm-linux-gnueabihf/libc.so.6 755 0 0 file /lib/arm-linux-gnueabihf/libz.so.1 /lib/arm-linux-gnueabihf/libz.so.1 755 0 0 file /lib/arm-linux-gnueabihf/libudev.so.1 /lib/arm-linux-gnueabihf/libudev.so.1 755 0 0 file /lib/arm-linux-gnueabihf/libdl.so.2 /lib/arm-linux-gnueabihf/libdl.so.2 755 0 0 file /lib/arm-linux-gnueabihf/libblkid.so.1 /lib/arm-linux-gnueabihf/libblkid.so.1 755 0 0 file /lib/arm-linux-gnueabihf/libdevmapper-event.so.1.02.1 /lib/arm-linux-gnueabihf/libdevmapper-event.so.1.02.1 755 0 0 file /lib/arm-linux-gnueabihf/libdevmapper.so.1.02.1 /lib/arm-linux-gnueabihf/libdevmapper.so.1.02.1 755 0 0 file /lib/arm-linux-gnueabihf/libreadline.so.5 /lib/arm-linux-gnueabihf/libreadline.so.5 755 0 0 file /lib/arm-linux-gnueabihf/librt.so.1 /lib/arm-linux-gnueabihf/librt.so.1 755 0 0 file /lib/arm-linux-gnueabihf/libc.so.6 /lib/arm-linux-gnueabihf/libc.so.6 755 0 0 file /lib/arm-linux-gnueabihf/libgcc_s.so.1 /lib/arm-linux-gnueabihf/libgcc_s.so.1 755 0 0 file /lib/arm-linux-gnueabihf/libm.so.6 /lib/arm-linux-gnueabihf/libm.so.6 755 0 0 file /lib/arm-linux-gnueabihf/libpcre.so.3 /lib/arm-linux-gnueabihf/libpcre.so.3 755 0 0 file /lib/arm-linux-gnueabihf/libpthread.so.0 /lib/arm-linux-gnueabihf/libpthread.so.0 755 0 0 file /lib/arm-linux-gnueabihf/libselinux.so.1 /lib/arm-linux-gnueabihf/libselinux.so.1 755 0 0 file /lib/arm-linux-gnueabihf/libtinfo.so.5 /lib/arm-linux-gnueabihf/libtinfo.so.5 755 0 0 file /lib/arm-linux-gnueabihf/libuuid.so.1 /lib/arm-linux-gnueabihf/libuuid.so.1 755 0 0 file /lib/ld-linux-armhf.so.3 /lib/ld-linux-armhf.so.3 755 0 0 file /usr/lib/arm-linux-gnueabihf/libarmmem.so /usr/lib/arm-linux-gnueabihf/libarmmem.so 755 0 0 # our init script file /init /usr/src/initramfs/init 755 0 0
Create the init script
root@localhost /usr/src/initramfs # touch init#!/bin/busybox sh
rescue_shell() {
echo "$@"
echo "Something went wrong. Dropping you to a shell."
/bin/busybox --install -s
exec /bin/sh
}
activate_vgs() {
/sbin/pvscan --uuid --verbose || rescue_shell "Error while scanning physical volumes"
/sbin/vgscan --mknodes --verbose || rescue_shell "Error while scanning volume groups"
for vg in $(/sbin/vgscan | grep "Found volume group" | cut -d\" -f2) ; do
echo "Activating volume group: $vg"
/sbin/vgchange -ay $vg --sysinit || rescue_shell "Error while activating $vg"
/sbin/vgmknodes --ignorelockingfailure $vg || rescue_shell "Error while making nodes for $vg"
done
}
find_rootfs() {
for cmd in $(cat /proc/cmdline) ; do
case $cmd in
root=*)
type=$(echo $cmd | cut -d= -f2)
echo "Mounting rootfs"
if [ $type == "LABEL" ] || [ $type == "UUID" ] ; then
uuid=$(echo $cmd | cut -d= -f3)
mount -o ro $(findfs "$type"="$uuid") /mnt/root
return
else
mount -o ro $(echo $cmd | cut -d= -f2) /mnt/root
return
fi
;;
esac
done
rescue_shell "No root partition found"
}
check_filesystem() {
# most of code coming from /etc/init.d/fsck
local fsck_opts= check_extra= RC_UNAME=$(uname -s)
# FIXME : get_bootparam forcefsck
if [ -e /forcefsck ]; then
fsck_opts="$fsck_opts -f"
check_extra="(check forced)"
fi
echo "Checking local filesystem $check_extra : $1"
if [ "$RC_UNAME" = Linux ]; then
fsck_opts="$fsck_opts -C0 -T"
fi
trap : INT QUIT
# using our own fsck, not the builtin one from busybox
/sbin/fsck -p $fsck_opts $1
case $? in
0) return 0;;
1) echo "Filesystem repaired"; return 0;;
2|3) if [ "$RC_UNAME" = Linux ]; then
echo "Filesystem repaired, but reboot needed"
reboot -f
else
rescue_shell "Filesystem still have errors; manual fsck required"
fi;;
4) if [ "$RC_UNAME" = Linux ]; then
rescue_shell "Fileystem errors left uncorrected, aborting"
else
echo "Filesystem repaired, but reboot needed"
reboot
fi;;
8) echo "Operational error"; return 0;;
12) echo "fsck interrupted";;
*) echo "Filesystem couldn't be fixed";;
esac
rescue_shell
}
# temporarily mount proc and sys
mount -t proc none /proc
mount -t sysfs none /sys
mount -t devtmpfs none /dev
# disable kernel messages from popping onto the screen
echo 0 > /proc/sys/kernel/printk
# clear the screen
clear
# scan for vgs and activate each and every one of them
activate_vgs || rescue_shell "Error while activating volume groups"
# mounting rootfs on /mnt/root
find_rootfs || rescue_shell "Error while finding root filesystem"
# space separated list of mountpoints that ...
mountpoints=""
# ... we want to find in /etc/fstab ...
ln -s /mnt/root/etc/fstab /etc/fstab
# ... to check filesystems and mount our devices.
for m in $mountpoints ; do
check_filesystem $m
echo "Mounting $m"
# mount the device and ...
mount $m || rescue_shell "Error while mounting $m"
# ... move the tree to its final location
mount --move $m "/mnt/root"$m || rescue_shell "Error while moving $m"
done
echo "All done. Switching to real root."
# clean up. The init process will remount proc sys and dev later
umount /proc
umount /sys
umount /dev
# switch to the real root and execute init
exec switch_root /mnt/root /sbin/init
Get back to the kernel directory
root@localhost /usr/src/initramfs # cd /usr/src/linux-rpi-4.9.ySet the generator script to be executable
root@localhost /usr/src/linux-rpi-4.9.y # chmod +x usr/gen_init_cpio scripts/gen_initramfs_list.shGenerate the initial ram disk and copy it with a name based on your previous choice
root@localhost /usr/src/linux-rpi-4.9.y # scripts/gen_initramfs_list.sh -o /boot/initrd-4.9.y-raspbian /usr/src/initramfs/initramfs_listOr
root@localhost /usr/src/linux-rpi-4.9.y # scripts/gen_initramfs_list.sh -o /boot/initrd-4.9.y-rpi /usr/src/initramfs/initramfs_listOr
root@localhost /usr/src/linux-rpi-4.9.y # scripts/gen_initramfs_list.sh -o /boot/initrd-4.9.y-rpi64 /usr/src/initramfs/initramfs_listUse the newly created kernel and initial ram fs
root@localhost /usr/src/linux-rpi-4.9.y # nano/boot/config.txtkernel=linux-4.9.y-raspbian initramfs initrd-4.9.y-raspbian
Or
kernel=linux-4.9.y-rpi initramfs initrd-4.9.y-rpi
Or
kernel=linux-4.9.y-rpi64 initramfs initrd-4.9.y-rpi64
In some cases the archive gets messed up, in that case decompress it re-compress it
root@localhost /usr/src/linux-rpi-4.9.y # mkdir -p /tmp/initrdroot@localhost /usr/src/linux-rpi-4.9.y #
cd /tmp/initrdroot@localhost /tmp/initrd # mv /boot/initrd-4.9.y-raspbian initrd-4.9.y-raspbian.cpio.gzroot@localhost /tmp/initrd #
gunzip initrd-4.9.y-raspbianroot@localhost /tmp/initrd #
cpio -idv < initrd-4.9.y-raspbianroot@localhost /tmp/initrd #
rm initrd-4.9.y-raspbianroot@localhost /tmp/initrd #
find . | cpio -ov > initrd-4.9.y-raspbian.cpioroot@localhost /tmp/initrd #
gzip initrd-4.9.y-raspbian.cpioroot@localhost /tmp/initrd #
mv initrd-4.9.y-raspbian.cpio.gz /boot/initrd-4.9.y-raspbian