From the Journals of Tarn Barford
Dec 27, 2015
Cross compiling a minimal Linux sytem for the ARM architecture and emulating it in QEMU.
Almost all the information from this and my previous post can be found in this nice tutorial by Kamel Messaoudi, which also includes debugging user programs. I'm posting my notes as I go through them again and which will use as reference points for future posts.
A Linux kernel that can be emulated by QEMU can be built using the
versatile_defconfig
and a working cross-compiler.
wget https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.3.3.tar.xz
wget https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.3.3.tar.sign
gpg --recv 6092693E
unxz linux-4.3.3.tar.xz
gpg --verify linux-4.3.3.tar.sign
tar xf linux-4.3.3.tar
cd linux-4.3.3
make ARCH=arm versatile_defconfig
# to further configure the build
#make ARCH=arm menuconfig
make ARCH=arm CROSS_COMPILE=arm-unknown-linux-gnueabi- all
# this builds a kernal image to `./arch/arm/boot/zImage`
cp linux-4.3.3/arch/arm/boot/zImage .
Busybox is a single binary combining many Unix utilities including a shell.
wget https://busybox.net/downloads/busybox-1.24.1.tar.bz2
wget https://busybox.net/downloads/busybox-1.24.1.tar.bz2.sign
gpg --recv ACC9965B
gpg --verify busybox-1.24.1.tar.bz2.sign
tar xf busybox-1.24.1.tar.bz2
cd xf busybox-1.24.1
make ARCH=arm CROSS_COMPILE=arm-unknown-linux-gnueabi- defconfig
make ARCH=arm CROSS_COMPILE=arm-unknown-linux-gnueabi- install
This builds a minimal filesystem in ./_install
. Some additional directories
are required.
cd _install
mkdir -p lib proc sys dev etc etc/init.d
Some shared libraries are required by the BusyBox binary. The exact libraries
can be found using the arm-unknown-linux-gnueabi-readelf
program. I'm just
going to copy all the libraries from my toolchain
to the target.
cp ~/x-tools/arm-unknown-linux-gnueabi/arm-unknown-linux-gnueabi/sysroot/lib/* lib
Next we add an init script at /etc/init.d/rcS
which will be executed by the
BusyBox init script.
cat > ./etc/init.d/rcS << EOF
#!/bin/sh
# Mount the /proc and /sys filesystems
mount -t proc none /proc
mount -t sysfs none /sys
# Populate /dev
/sbin/mdev -s
# Enable the localhost interface
ifconfig lo up
EOF
It needs to be executable.
chmod +x etc/init.d/rcS
A compressed disk image of this filesystem which can be read by qemu
can be
made using the cpio
program.
find . | cpio -o --format=newc | gzip > ../../rootfs.img.gz
I use my system qemu package, but it is not hard to build.
qemu-system-arm -M versatilepb -m 128M -kernel ./zImage -initrd ./rootfs.img.gz -append "root=/dev/ram rdinit=/sbin/init"