A short set of notes for working with embedded disk images on Linux, specifically Build.Dist disk images produced by the GenPi64 project. It is easy to use a more powerful machine in order to operate on disk images.
Get the code
Currently upstream is using the
alpha9 branch for development. Helps to have the code around for troubleshooting and/or debugging purposes.
git clone https://github.com/GenPi64/Build.Dist.git
git checkout origin/alpha9
Configuring a Gentoo system for development
Instead of compiling the aarch64 images from a Raspberry Pi, GenPi64 developers generally use a cross-chroot development environment to build the image files on more powerful amd64 hardware. In order to accomplish these development standards, the system may need a kernel recompile and some new packages with special USE flags.
The system kernel will need support for miscellaneous binary formats.
Executable file formats ---> <*> Kernel support for MISC binaries
Be aware that building in the symbol like shown above will require system restart; it may take less time to build support as a module and manually modprobe it via:
When not built-in, this feature must be mounted each time it is used:
mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc
It may be helpful to put the following packages in a new set, since the Build.Dist does not have an ebuild specifying or requiring dependencies.
# These packages are necessary in order to build GenPi images with Build.Dist # which is performed via a cross-chroot environment (QEMU with user targets). app-emulation/qemu dev-python/iniparse dev-python/lockfile dev-python/pychroot sys-apps/gptfdisk sys-fs/btrfs-progs
Be sure to add the following necessary USE flags for app-emulation/qemu:
app-emulation/qemu qemu_softmmu_targets_aarch64 qemu_softmmu_targets_arm qemu_user_targets_aarch64 qemu_user_targets_arm static-user xattrs # required by app-emulation/qemu::gentoo[-static,xattr,static-user] # required by @selected # required by @world (argument) sys-apps/attr static-libs # required by app-emulation/qemu::gentoo[-static,static-user] # required by @selected # required by @world (argument) dev-libs/glib static-libs # required by dev-libs/glib::gentoo # required by app-emulation/qemu::gentoo[-static,static-user] # required by @selected # required by @world (argument) dev-libs/libpcre static-libs
Install the prerequisite packages:
emerge -uNDavt @genpi-dev
Building the image
When building from a system running systemd as the init system, it is important set the following variables before running build.sh
NO_PARALLEL=1 TERM=xterm sh build.sh
Downloading the official image
Download, extract, and mount image
As of the present, the community ran GenPi64 project produces zstd compressed .img files. In order to actively work with one of these images, a few setup steps are necessary.
Download the image from GenPi64.com, or alternatively, obtain an image from the building the stage file instead.
wget --continue <URL>
Extract the image to a work area. Tips this can be in zram, tmpfs, or the generic filesystem.
zstdcat /path/to/genpi64-lite.img.zstd > /path/to/workdir/genpi64-lite.img && sync
Follow the extraction by mounting the image using losetup. If everything goes well and there are no other loop devices mounted, the output of the command will be /dev/loop0:
losetup --partscan --find --show genpi64-lite.img
Long listing the device will show all available partitions for the loop mounted image. For GenPi64 the output should look like the following:
ls -l /dev/loop0*
brw-rw---- 1 root disk 7, 0 Jan 18 15:15 /dev/loop0 brw-rw---- 1 root disk 259, 10 Jan 18 15:15 /dev/loop0p1 brw-rw---- 1 root disk 259, 11 Jan 18 15:15 /dev/loop0p2
Finally, create mount points if necessary and mount the partitions:
mkdir --parents /srv/genpi64
mount /dev/loop0p2 /srv/genpi64 #btrfs rootfs
mount /dev/loop0p1 /srv/genpi64/boot #vfat boot
pychroot tends to save a few steps in mounting all the virtual file systems.
Alternative mound (without pychroot):
Follow the guide from the Raspberry Pi Foundation for compiling the kernel. At the time of this writing, compilation for the Raspberry Pi 4 looks like:
make -j4 ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- bcm2711_defconfig
Writing the image
Generally the image will be written to a microSD card via mmc connection:
zstdcat genpi64-lite.img.zst > /dev/mmcblk0 && sync
umount --detach-loop /srv/genpi64/boot #vfat boot
umount --detach-loop --lazy --recursive /srv/genpi64 #rootfs
Tips and tricks
Custom kernel compiling
Download a branch of the Raspberry Pi Foundation sources from GitHub. For this example rpi-5.11.y will be used:
git clone https://github.com/raspberrypi/linux.git --branch rpi-5.11.y /usr/src/raspberrypi-sources
ln -s /usr/src/raspberrypi-sources /usr/src/linux
Modify the kernel following the directions on
After modifying the kernel, manually tweak the CONFIG_LOCALVERSION configuration value so that the installed modules do not clobber existing modules in /lib/modules/:
Appending the suffix
-p4 specifies the build is for the Pi 4.
CPU frequency scaling
Being a general purpose device, the base clock of the Rpi 4 is 700 MHz, however the clock speed should scale as appropriate for the duties performed. Here are a few tips to help adjust from the alpha5 GenPi64 base image:
- Change the default CPUfreq governor from
- Scaling governor can be checked via: cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
- Install sys-power/cpupower
- Set the governor to ondemand: cpupower frequency-set --governor ondemand
- Measure CPU frequency speed with: watch -n 1 vcgencmd measure_clock arm
Overclock the ARM core to at least 1200 MHz via config.txt.Default arm_freq value for the Rpi4 is
1500according to this list.
Bootloader firmware update
It is wise to check the firmware for updates every few months:
Set static IP address
By default the system will pull a DHCP address. In order to set a static IP on the network, NetworkManager is the utility available for this purpose. It will need added to the default runlevel (for OpenRC images).
Verify ntp and ntp-client will maintain system time
Most single board computers (true at least until Raspberry 4) do not include onboard hardware clocks, it is important for the system to query the network in order to set the software clock while the system is running. This generally occurs once during system boot time, and then is maintained while the system has power and a connection to an NTP server in order to prevent clock drift. It is generally useful to not see the date command return a time from the 1970s.
rc-update add ntp default
rc-update add ntp-client default
rc-service start ntp-client
rc-service start ntp