Run a Root Filesystem for a Raspberry Pi 3 Model B+
Introduction
This is the seventh post in a series of posts (in a tutorial) about building an embedded Linux system for a Raspberry Pi 3 Model B+. A summary post for the tutorial can be found here. The summary post also talks about …
- what is required to follow along,
- the
<project/root/dir>, - some terms that will be used throughout the series,
- a link to an article that explains how to prepare the SD card,
- some hints on how to use the UART interface of the Raspberry Pi.
Now it’s finally time to put it all together and run a entire embedded Linux system on a Raspberry Pi 3 Model B+. Let’s get started.
Final Preparations of the Root Filesystem
After Building a Root Filesystem for a Raspberry Pi 3 Model B+ with busybox, we have to make some minor adjustments to it.
First of all let’s add a root user to the system. This user won’t have a
password right now. You should not use such a setup in production, but for now
it’s ok. In order to do so, we have to create an etc directory to the root
filesystem and add two files to it.
cd <project/root/dir>/rootfs
mkdir etc
echo "root:x:0:0:/root:/bin/sh" > etc/passwd
echo "root::::::::" > etc/shadow
chmod 0600 etc/shadow
Noto: For more information about these files and its entries run the
commands man passwd and man 5 shadow
Linux will try to run a program called init at startup. This usually starts
up and monitors other programs (like a shell for example). The init program
that busybox provides reads a configuration file etc/inittab. So let’s create
that file:
cat > etc/inittab << EOF
::sysinit:/etc/init.d/rcS
::askfirst:-/bin/ash
EOF
This file will cause init to run the script /etc/init.d/rcS and afterwards
ask the user to press enter before it runs the /bin/ash shell. We can use
/etc/init.d/rcS to mound to pseudo file systems (/proc and /sys). So
let’s create the necessary directories, the script, and make the script
executable:
mkdir proc sys
mkdir etc/init.d
cat > etc/init.d/rcS << EOF
#!/bin/sh
mount -t proc proc /proc
mount -t sysfs sysfs /sys
EOF
chmod u+x etc/init.d/rcS
On your host system all files in the root filesystem belong to your user, but on the Raspberry Pi they have to belong to the root user. So the ownership of all files in the created root filesystem have to be changed:
cd <project/root/dir>
sudo chown -R root:root rootfs
Note: For the next step make sure where to find your root filesystem
partion of your SD card when inserted into your host system. In my case it is
under /dev/sdb2.
Now it’s time to bring the root filesystem on the SD card that has been used earlier when running U-Boot and when running the kernel. So insert it into your host system, mount the root filesystem partition and copy the root filesystem onto the SD card.
cd <project/root/dir>
sudo mkdir /mnt/rootfs
sudo mount /dev/sdb2 /mnt/rootfs
sudo rsync -aHAXP --stats rootfs/ /mnt/rootfs/
Now you can unmount the SD card from your host system:
$> sudo umount /mnt/boot
and place the card into the card holder of the Raspberry Pi. Once the SD card
is in the Raspberry Pi and you have a connection to the UART interface, you can
power up the board. You should see the same output as shown in the post Run
U-Boot on a Raspberry Pi. Once you
have the u-boot command prompt, the following commands make the kernel boot:
U-Boot> setenv bootargs 8250.nr_uarts=1 console=ttyS0,115200 root=/dev/mmcblk0p2 rootfstype=ext4 rw rootwait
U-Boot> load mmc 0:1 $kernel_addr_r Image
15034880 bytes read in 1362 ms (10.5 MiB/s)
U-Boot> load mmc 0:1 $fdt_addr_r bcm2837-rpi-3-b-plus.dtb
21027 bytes read in 5 ms (4 MiB/s)
U-Boot> booti $kernel_addr_r - $fdt_addr_r
## Flattened Device Tree blob at 02600000
Booting using the fdt blob at 0x2600000
Working FDT set to 2600000
Using Device Tree in place at 0000000002600000, end 0000000002608222
Working FDT set to 2600000
Starting kernel ...
After Starting kernel ... more output should appear. It looks something like
this:
[ 0.000000] Booting Linux on physical CPU 0x0000000000 [0x410fd034]
[ 0.000000] Linux version 4.19.127-v8-schuam+ (andreas@penguin) (gcc version 13.2.0 (crosstool-NG 1.26.0)) #1 SMP PREEMPT Fri Jan 31 10:24:51 CET 2025
[ 0.000000] Machine model: Raspberry Pi 3 Model B Plus Rev 1.3
... output shortened ...
[ 1.349537] mmcblk0: mmc0:0002 N/A 1.88 GiB
[ 1.349980] of_cfs_init: OK
[ 1.358888] mmcblk0: p1 p2
[ 1.382711] EXT4-fs (mmcblk0p2): mounted filesystem with ordered data mode. Opts: (null)
[ 1.391031] VFS: Mounted root (ext4 filesystem) on device 179:2.
[ 1.398479] devtmpfs: error mounting -2
[ 1.411324] Freeing unused kernel memory: 2880K
[ 1.416150] Run /sbin/init as init process
[ 1.552705] usb 1-1: new high-speed USB device number 2 using dwc2
Please press Enter to activate this console. [ 1.737027] usb 1-1: New USB device found, idVendor=0424, idProduct=2514, bcdDevice= b.b3
... output shortened ...
[ 3.640081] random: crng init done
Since the kernel and the init program write their output to the same
terminal, it’s a little hard to see, but the init program actually printed
Please press Enter to activate this console.. So if you press enter, you will
get a console with the following command prompt:
~ #
And now you can use your new embedded Linux on the Raspberry Pi 3 Model B+ and
run command like ps, ls or what ever:
~ # ls
bin linuxrc proc sys
etc lost+found sbin usr
Well, that’s it for this series of post about embedded Linux on the Raspberry Pi 3 Model B+. Have fun with it.
Take care,
Andreas
Leave a comment