# Busybox as the init
###### tags: `Busybox`, `QEMU`, `Virtual Machine`, `Linux`, `Raspberry Pi` `Linux from Scratch`
## Linux Kernel Tries to Find init
```
[ 2.146201] Run /sbin/init as init process
[ 2.148061] Run /etc/init as init process
[ 2.149846] Run /bin/init as init process
[ 2.150521] Run /bin/sh as init process
[ 2.151871] Kernel panic - not syncing: No working init found. Try passing init= option to kernel. See Linux Documentation/admin-guide/init.rst for guidance.
```
## Build Busybox
```shell=
$ git clone https://git.busybox.net/busybox
$ cd busybox
$ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- defconfig
$ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- menuconfig
$ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu-
$ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- install
$ ls -l _install/
total 12
drwxr-xr-x 2 zack zack 4096 Jun 5 12:06 bin
lrwxrwxrwx 1 zack zack 11 Jun 5 12:06 linuxrc -> bin/busybox
drwxr-xr-x 2 zack zack 4096 Jun 5 12:06 sbin
drwxr-xr-x 4 zack zack 4096 Jun 5 12:06 usr
```
PS. When install Busybox into the root partition, have to set `CONFIG_PREFIX="<the root partition mount path>"`
## Prepare the Image and Partitions
```shell=
$ dd if=/dev/zero of=~/qemu-images/simple-busybox.img bs=8M count=16
16+0 records in
16+0 records out
134217728 bytes (134 MB, 128 MiB) copied, 0.086382 s, 1.6 GB/s
$ fdisk -l ~/qemu-images/simple-busybox.img
Disk /home/zack/qemu-images/simple-busybox.img: 128 MiB, 134217728 bytes, 262144 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x7ac31012
Device Boot Start End Sectors Size Id Type
/home/zack/qemu-images/simple-busybox.img1 * 2048 206847 204800 100M b W95 FAT32
/home/zack/qemu-images/simple-busybox.img2 206848 262143 55296 27M 83 Linux
$ mkfs.vfat -v --offset=2048 ~/qemu-images/simple-busybox.img $((100*1024*1024/1024))
$ mkfs.ext4 -E offset=$((512*206848)) ~/qemu-images/simple-busybox.img
```
## Prepare Root File System on the Image
```shell=
$ sudo mount -o offset=$((512*206848)) ~/qemu-images/simple-busybox.img /mnt/
$ sudo cp -r _install/* /mnt/
$ sudo mkdir -p /mnt/etc
$ sudo mkdir -p /mnt/etc/init.d
$ sudo mkdir -p /mnt/proc
$ sudo mkdir -p /mnt/sys
$ sudo mkdir -p /mnt/dev
$ sudo mkdir -p /mnt/tmp
$ sudo mkdir -p /mnt/root
$ sudo mkdir -p /mnt/var
$ sudo mkdir -p /mnt/lib
$ sudo mkdir -p /mnt/mnt
$ sudo mkdir -p /mnt/boot
$ ls -l /mnt/
total 15
drwxr-xr-x 2 root root 3072 Apr 5 22:39 bin
drwxr-xr-x 2 root root 1024 Apr 5 22:41 boot
drwxr-xr-x 2 root root 1024 Apr 5 22:41 dev
drwxr-xr-x 3 root root 1024 Apr 5 22:41 etc
lrwxrwxrwx 1 root root 11 Apr 5 22:39 linuxrc -> bin/busybox
drwxr-xr-x 2 root root 1024 Apr 5 22:41 mnt
drwxr-xr-x 2 root root 1024 Apr 5 22:41 proc
drwxr-xr-x 2 root root 1024 Apr 5 22:41 root
drwxr-xr-x 2 root root 3072 Apr 5 22:39 sbin
drwxr-xr-x 2 root root 1024 Apr 5 22:41 sys
drwxr-xr-x 2 root root 1024 Apr 5 22:41 tmp
drwxr-xr-x 4 root root 1024 Apr 5 22:39 usr
drwxr-xr-x 2 root root 1024 Apr 5 22:41 var
```
Note: Must take care the shared C libraries issue. Otherwise, kernel may fail to execute the `init`. **Static link** is a quick solution.
## Install the [/etc/inittab](https://git.busybox.net/busybox/tree/init/init.c?h=1_35_0#n29)
```shell=
$ sudo install ~/busybox/examples/inittab /mnt/etc/inittab
```
* Disable the default **askfirst shell** by commenting `::askfirst:-/bin/sh` to avoid duplicated shells on the same console.
* The QEMU VM need `ttyAMA0::respawn:/sbin/getty -L 0 ttyAMA0 vt100` for serial console.
## [Creating the /etc/fstab File](https://www.linuxfromscratch.org/lfs/view/9.1/chapter08/fstab.html)
```shell=
$ cat /mnt/etc/fstab
# Begin /etc/fstab
# file system mount-point type options dump fsck
# order
/dev/vda1 / ext4 rw,relatime 0 0
proc /proc proc nosuid,noexec,nodev 0 0
#sysfs /sys sysfs nosuid,noexec,nodev 0 0
#devpts /dev/pts devpts gid=5,mode=620 0 0
#tmpfs /run tmpfs defaults 0 0
#devtmpfs /dev devtmpfs mode=0755,nosuid 0 0
# End /etc/fstab
```
```shell=
## Install udhcpc script for obtaining & setting IP to interface
## http://dannysun-unknown.blogspot.com/2018/08/busybox-udhcpc-ipip.html
$ sudo install -d /mnt/usr/share/udhcpc
$ sudo install examples/udhcp/simple.script /mnt/usr/share/udhcpc/default.script
$ echo "nameserver 8.8.8.8" | sudo tee -a /mnt/etc/resolv.conf # Maybe not
## Set host name
$ echo "busybox-arm64" | sudo tee -a /mnt/etc/hostname
## Initial script
$ cat /mnt/etc/init.d/rcS
#!/bin/sh
mount -a
ip link set eth0 up
udhcpc
hostname -F /etc/hostname
ntpd -n -q -p time.stdtime.gov.tw
$ sudo chmod +x /mnt/etc/init.d/rcS
## User list
$ echo "root:x:0:0::/root:/bin/sh" | sudo tee -a /mnt/etc/passwd
$ echo "root::18541::::::" | sudo tee -a /mnt/etc/shadow
```
## Build Linux Kernel (virt)
```shell=
$ git checkout tags/v5.15.24
$ cp arch/arm/configs/vexpress_defconfig .config
$ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- menuconfig # Leave ARMv8 software model (Versatile Express) only
$ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu-
```
## Launch QEMU VM (virt)
```shell=
$ qemu-system-aarch64 -smp 2 -M virt -cpu cortex-a57 -m 1G -kernel ~/linux-stable/arch/arm64/boot/Image --append "console=ttyAMA0 root=/dev/vda2 rw rootfstype=ext4" -hda ~/qemu-images/simple-busybox.img
```
## Boot on Raspberry Pi 3B
* Raspberry Pi 3B's serial console is **ttyS1**.
* The mircro SD is **mmcblk0** as the block. So, the boot partition is **mmcblk0p1**. The root partition is **mmcblk0p2**.
* Need Raspberry Pi's boot firmware files from Raspberry Pi OS.
* Have interactive consoles by listing in `/etc/inittab`:
* Have `tty1::respawn:-/bin/sh` for normal console
* Have `::respawn:/sbin/getty -L ttyS1 115200 vt100` to replace the original **ttyAMA0** console
* Make sure there is `rw` in boot command for read-writable root file system.
* May need wait a small time before request with DHCP
* Raspberry Pi's wireless devices need the corresponding firmwares. They can be gotten from linux-firmware upstream.
```
[ 2.375289] brcmfmac mmc1:0001:1: Direct firmware load for brcm/brcmfmac43430-sdio.raspberrypi,3-model-b.bin failed with error -2
[ 2.387389] brcmfmac mmc1:0001:1: Direct firmware load for brcm/brcmfmac43430-sdio.bin failed with error -2
[ 2.557444] mmcblk0p2: Can't mount, would change RO state
[ 2.571947] Bluetooth: hci0: BCM: firmware Patch file not found, tried:
[ 2.578840] Bluetooth: hci0: BCM: 'brcm/BCM43430A1.hcd'
[ 2.578860] Bluetooth: hci0: BCM: 'brcm/BCM.hcd'
```
MSDOS Partition does not support that kernel boots with root from `PARTUUID`
```shell=
# blkid
/dev/vda2: UUID="8d5165f0-d51f-404b-a3a6-7765cf69bbc6" TYPE="ext4"
/dev/vda1: UUID="143C-2AED" TYPE="vfat"
```
## Reference
* https://riptutorial.com/embedded-linux
* [fdisk](https://man7.org/linux/man-pages/man8/fdisk.8.html)
* [mkfs.vfat](https://man7.org/linux/man-pages/man8/mkfs.vfat.8.html)
* [mkfs.ext4](https://man7.org/linux/man-pages/man5/ext4.5.html)
* [mount](https://man7.org/linux/man-pages/man8/mount.8.html)