Skip to content

Instantly share code, notes, and snippets.

@s4eidhp
Last active October 12, 2024 10:06
Show Gist options
  • Save s4eidhp/00ab9268ecd700c30936b10c126f9dff to your computer and use it in GitHub Desktop.
Save s4eidhp/00ab9268ecd700c30936b10c126f9dff to your computer and use it in GitHub Desktop.

Toolchain

cd ~
git clone https://github.com/crosstool-ng/crosstool-ng.git  
cd crosstool-ng 
git checkout crosstool-ng-1.26.0        # currently latest stable version
./bootstrap
./configure --prefix=${PWD}
make
make install
cd ~/crosstool-ng
bin/ct-ng list-samples
bin/ct-ng show-aarch64-rpi3-linux-gnu
bin/ct-ng aarch64-rpi3-linux-gnu
bin/ct-ng menuconfig

Modification

  • Allow extending the toolchain after it is created (by default, it is created as read-only):

    Paths and misc options -> Render the toolchain read-only -> false

  • Chane the tuple's vendor string:

    Toolchain options -> Tuple's vendor string: Change rpi3 to rpizero2w

Build

bin/ct-ng build
PATH=$PATH:~/x-tools/aarch64-rpizero2w-linux-gnu/bin

Check

create file hello.c like this:

#include <stdio.h>
#include <stdlib.h>
int main (int argc, char *argv[])
{
    printf ("Hello, world!\n");
    return 0;
}
aarch64-rpizero2w-linux-gnu-gcc hello.c -o hello
  • add -static to link libraries staticaly
  • move hello file to target and run it

U-Boot

git clone git://git.denx.de/u-boot.git
cd u-boot
git checkout v2023.10           # currently latest stable version

PATH=$PATH:~/x-tools/aarch64-rpizero2w-linux-gnu/bin
export CROSS_COMPILE=aarch64-rpizero2w-linux-gnu-
export ARCH=arm64

make rpi_arm64_defconfig
make

Prepare SD card

scripts/format-sdcard.sh
cd ~
sudo apt install subversion
svn checkout https://github.com/raspberrypi/firmware/trunk/boot
cp boot/{bootcode.bin,start.elf,fixup.dat,bcm2710-rpi-zero-2-w.dtb} /media/${USER}/boot/
rm -rf boot
cp u-boot/u-boot.bin /media/${USER}/boot/

cat << EOF > config.txt
enable_uart=1
arm_64bit=1
kernel=u-boot.bin
EOF
mv config.txt /media/${USER}/boot/
  • in this stage you can boot into U-Boot bootloader

Linux Kernel

cd ~
git clone --depth=1 -b rpi-6.1.y https://github.com/raspberrypi/linux.git       # currently latest stable version
cd linux
make ARCH=arm64 CROSS_COMPILE=/home/cloner/x-tools/aarch64-rpizero2w-linux-gnu/bin/aarch64-rpizero2w-linux-gnu- bcm2711_defconfig
make -j$(nproc) ARCH=arm64 CROSS_COMPILE=/home/cloner/x-tools/aarch64-rpizero2w-linux-gnu/bin/aarch64-rpizero2w-linux-gnu-
cp arch/arm64/boot/Image /media/${USER}/boot

cat << EOF > cmdline.txt
console=serial0,115200 console=tty1 root=/dev/mmcblk0p2 rootwait
EOF
sudo cp cmdline.txt /media/${USER}/boot/

# clean up
rm cmdline.txt

Configure U-Boot

cat << EOF > boot_cmd.txt
fatload mmc 0:1 \${kernel_addr_r} Image
fatload mmc 0:1 \${ramdisk_addr_r} uRamdisk
fatload mmc 0:1 \${fdt_addr} bcm2710-rpi-zero-2-w.dtb
booti \${kernel_addr_r} \${ramdisk_addr_r} \${fdt_addr}
EOF

~/u-boot/tools/mkimage -A arm64 -O linux -T script -C none -d boot_cmd.txt boot.scr
# Copy the compiled boot script to boot partition
sudo cp boot.scr /media/${USER}/boot/

# clean up
rm boot_cmd.txt boot.scr 
  • up to here your board should boot up and kernel starts normally but as we do not add Root filesystem, it ends up with panic

Root filesystem (Staging Area)

cd ~
mkdir rootfs
cd rootfs
mkdir {bin,dev,etc,home,lib64,proc,sbin,sys,tmp,usr,var}
mkdir usr/{bin,lib,sbin}
mkdir var/log

# Create a symbolink lib pointing to lib64
ln -s lib64 lib

# Change the owner of the directories to be root
# Because current user doesn't exist on target device
sudo chown -R root:root *

Busybox

cd ~
git clone git://busybox.net/busybox.git
cd busybox
git checkout 1_36_1             # latest stable version

# Config
make distclean
CROSS_COMPILE=${HOME}/x-tools/aarch64-rpizero2w-linux-gnu/bin/aarch64-rpizero2w-linux-gnu-
make ARCH=arm64 CROSS_COMPILE="$CROSS_COMPILE" defconfig
# Change the install directory to be the one just created
# Note that you should change usename in this command
sed -i 's%^CONFIG_PREFIX=.*$%CONFIG_PREFIX="/home/cloner/rootfs"%' .config

# Build
make CROSS_COMPILE="$CROSS_COMPILE"

# Install
# Use sudo because the directory is now owned by root
sudo make CROSS_COMPILE="$CROSS_COMPILE" install
  • Note that you can use ToyBox instead which is very often used in Android devices

Required Libraries

You need to copy shared libraries from toolchain to the staging directory.

cd ~/rootfs
PATH=$PATH:~/x-tools/aarch64-rpizero2w-linux-gnu/bin
aarch64-rpizero2w-linux-gnu-readelf -a ~/rootfs/bin/busybox | grep -E "(program interpreter)|(Shared library)"
export SYSROOT=$(~/x-tools/aarch64-rpizero2w-linux-gnu/bin/aarch64-rpizero2w-linux-gnu-gcc -print-sysroot)
sudo cp -L ${SYSROOT}/lib64/{ld-linux-aarch64.so.1,libm.so.6,libresolv.so.2,libc.so.6} ~/rootfs/lib64/

Size Reduction

We can reduce size of libraries and programs by stripping the binaries of symbol tables

sudo ~/x-tools/aarch64-rpizero2w-linux-gnu/bin/aarch64-rpizero2w-linux-gnu-strip ~/rootfs/lib64/*

Create device nodes

cd ~/rootfs
sudo mknod -m 666 dev/null c 1 3
sudo mknod -m 600 dev/console c 5 1

Boot with initramfs

cd ~/rootfs
find . | cpio -H newc -ov --owner root:root > ../initramfs.cpio
cd ..
gzip initramfs.cpio
~/u-boot/tools/mkimage -A arm64 -O linux -T ramdisk -d initramfs.cpio.gz uRamdisk

# Copy the initramffs to boot partition
sudo cp uRamdisk /media/${USER}/boot/

# clean up
rm uRamdisk initramfs.cpio.gz
  • Note that this manual is NOT complete and should add some steps to it in future!
#!/bin/bash
# Format a microSD card for the BeagelBone Black
# Mastering Embedded Linux Programming
# Copyright (c) Chris Simmonds, 2017
if [ $# -ne 1 ]; then
echo "Usage: $0 [drive]"
echo " drive is 'sdb', 'mmcblk0', etc"
exit 1
fi
function version_gt() { test "$(echo "$@" | tr " " "\n" | sort -V | head -n 1)" != "$1"; }
DRIVE=$1
# Check the drive exists in /sys/block
if [ ! -e /sys/block/${DRIVE}/size ]; then
echo "Drive does not exist"
exit 1
fi
# Check it is a flash drive (size < 32GiB)
NUM_SECTORS=`cat /sys/block/${DRIVE}/size`
if [ $NUM_SECTORS -eq 0 -o $NUM_SECTORS -gt 64000000 ]; then
echo "/dev/$DRIVE does not look like an SD card, bailing out"
exit 1
fi
# Unmount any partitions that have been automounted
if [ $DRIVE == "mmcblk0" ]; then
sudo umount /dev/${DRIVE}*
BOOT_PART=/dev/${DRIVE}p1
ROOT_PART=/dev/${DRIVE}p2
else
sudo umount /dev/${DRIVE}[1-9]
BOOT_PART=/dev/${DRIVE}1
ROOT_PART=/dev/${DRIVE}2
fi
# Overwite any existing partiton table with zeros
sudo dd if=/dev/zero of=/dev/${DRIVE} bs=1M count=10
if [ $? -ne 0 ]; then echo "Error: dd"; exit 1; fi
# Create 2 primary partitons on the sd card
# 1: FAT32, 100 MiB, boot flag
# 2: Linux, 1024 MiB
# Note that the parameters to sfdisk changed slightly v2.26
SFDISK_VERSION=`sfdisk --version | awk '{print $4}'`
if version_gt $SFDISK_VERSION "2.26"; then
sudo sfdisk /dev/${DRIVE} << EOF
,100M,0x0c,*
,1024M,L,
EOF
else
sudo sfdisk --unit M /dev/${DRIVE} << EOF
,100,0x0c,*
,1024,L,
EOF
fi
if [ $? -ne 0 ]; then echo "Error: sdfisk"; exit 1; fi
# Format p1 with FAT32 and p2 with ext4
sudo mkfs.vfat -F 16 -n boot ${BOOT_PART}
if [ $? -ne 0 ]; then echo "Error: mkfs.vfat"; exit 1; fi
sudo mkfs.ext4 -L rootfs ${ROOT_PART}
if [ $? -ne 0 ]; then echo "Error: mkfs.ext4"; exit 1; fi
echo "SUCCESS! Your microSD card has been formatted"
exit 0
# Add a toolchain created using CrosstoolNG to your path
# and export ARCH and CROSS_COMPILE variables ready to
# compile U-Boot, Linux, Busybox and anything else using
# the Kconfig/Kbuild scripts
# Saeid Haghighipour, [email protected]
PATH=$PATH:~/x-tools/aarch64-rpizero2w-linux-gnu/bin
export CROSS_COMPILE=aarch64-rpizero2w-linux-gnu-
export ARCH=arm64
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment