Building a very minimal initramfs
I’m working on trying to get a Qualcomm IPQ8064 device working properly. I’d got as far as an extremely hacked up chain of networking booting and the serial console working, so the next stage was to try and get a basic userland in place to try and make poking things a bit easier. While I have a cross-compiling environment all setup (that’s how I’m building my kernels) I didn’t really want to get into something complicated just to be able to poke around sysfs etc. I figured I could use a static BusyBox in an initramfs. I was right, but there were a couple of hiccups along the way so I’m writing it up so I remember next time.
First, I cheated and downloaded a prebuilt static binary from https://busybox.net/downloads/binaries/ (very convenient, thanks) - the IPQ8064 is a dual core ARMv7 so I used
busybox-armv7l. There were various sites with init scripts to go along with this; I ended up with a variation of Star Brilliant’s gist:
Minimal init script
#!/bin/busybox sh busybox mkdir -p /dev /etc /proc /root /sbin /sys /usr/bin /usr/sbin busybox mount -t proc proc /proc busybox mount -t sysfs sys /sys busybox mount -t devtmpfs dev /dev echo Starting up... echo ttyMSM0::respawn:/sbin/getty -L ttyMSM0 115200 vt100 >> /etc/inittab echo Login with root and no password. > /etc/issue echo >> /etc/issue echo root::0:0:root:/root:/bin/sh > /etc/passwd busybox mdev -s busybox --install hostname localhost ip link set lo up echo 5 > /proc/sys/kernel/printk exec /linuxrc
busybox and the init script aren’t sufficient. If you have any problems then you’re going to want a console device. Otherwise you’ll do what I did, forget to change one of the tty references in the script to the right device, and spend too long trying to figure out why you’re not getting any output as soon as you start running userspace. It turns out that
CONFIG_DEVTMPFS_MOUNT isn’t sufficient for the initramfs (the Kconfig help even tells you that). So I need to create a
/dev/console device file inside the initramfs too. And I don’t build as root (and you shouldn’t either) which makes creating a device node hard. It’s ok though, because the Linux kernel doesn’t need you to be root to build it, and it has a default initramfs with a console device in it. This is helpfully generated using
usr/gen_init_cpio, which takes a file defining what you want to put in the cpio file that becomes your initramfs. I used the following:
Minimal initramfs creation file
# Simple busybox based initramfs dir /dev 0755 0 0 nod /dev/console 0600 0 0 c 5 1 dir /root 0700 0 0 dir /bin 0755 0 0 dir /sbin 0755 0 0 file /init basic-init 0755 0 0 file /bin/busybox busybox-armv7l 0755 0 0
All that then needs to be done is
linux/usr/gen_init_cpio initramfs.list > initramfs.cpio and the resulting
initramfs.cpio is suitable for inclusion in your kernel. The precompiled binaries have a lot of stuff enabled, which makes for a pretty useful debugging environment with fairly minimal work.