diff --git a/LICENSE b/LICENSE index 1d38a58..346d047 100644 --- a/LICENSE +++ b/LICENSE @@ -671,4 +671,4 @@ into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read -. \ No newline at end of file +. diff --git a/README.md b/README.md index 7dd2e1c..f4043ff 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ## Overview -This is a collection of scripts that are used to build a Ubuntu 20.04 preinstalled desktop/server image for the Raspberry Pi Zero 2W, 3, 4, and 400. +This is a collection of scripts that build Ubuntu preinstalled desktop/server images for the Raspberry Pi Zero 2W, 3, 4, 5, and 400. The Ubuntu release is set per profile (e.g. 20.04 for legacy, 24.04 or 22.04 for rpi). ![Raspberry Pi 4](https://www.electromaker.io/uploads/images/board-guide/single-board-computer/medium/Raspberry%20Pi%204B-540x386.png) @@ -21,9 +21,34 @@ Please install the below packages on your host machine: sudo apt-get install -y build-essential gcc-aarch64-linux-gnu bison \ qemu-user-static qemu-system-arm qemu-efi u-boot-tools binfmt-support \ debootstrap flex libssl-dev bc rsync kmod cpio xz-utils fakeroot parted \ -udev dosfstools uuid-runtime grub-pc +udev dosfstools uuid-runtime grub-pc libgnutls28-dev ``` +## Supported platforms + +One image works across all of these boards; the correct U-Boot and device tree are chosen at boot via `config.txt`: + +| Board | SoC | config.txt section | +|-------------|----------|----------------------| +| Pi Zero 2W | BCM2710A1| `[all]` or `[pi3]` | +| Pi 3 | BCM2837 | `[pi3]` | +| Pi 4 / 400 | BCM2711 | `[pi4]` | +| Pi 5 | BCM2712 | `[pi5]` | + +Two build profiles (switch in `scripts/config`): + +| Profile | File | Boards | +|------------|------------------------|---------------------------| +| **legacy** | `scripts/config.legacy` | Pi Zero 2W, 3, 4, 400 | +| **rpi** | `scripts/config.rpi` | Pi Zero 2W, 3, 4, 5, 400 | + +- **Use legacy:** In `scripts/config`, set `BUILD_PROFILE=legacy` (default). Uses kernel/firmware tag `1.20220830` and U-Boot `v2022.01`. +- **Use RPi (incl. Pi 5):** In `scripts/config`, set `BUILD_PROFILE=rpi`. Uses kernel branch and firmware/U-Boot tags from `scripts/config.rpi`; **UBUNTU_RELEASE** defaults to **noble** (24.04); set to **jammy** in `config.rpi` for 22.04. Pi 5 uses `rpi_arm64_defconfig` (same binary as other 64-bit boards). + +Or pass the profile as an argument (recommended; survives sudo): `sudo ./build.sh rpi` + +After changing the profile or editing `scripts/config.legacy` / `scripts/config.rpi`, run `sudo ./build.sh` (or remove `build/` and rebuild). + ## Building To checkout the source and build: @@ -58,7 +83,7 @@ Password: root To flash the Ubuntu 20.04 preinstalled image to removable media: ``` -xz -dc images/ubuntu-20.04-preinstalled-desktop-arm64-rpi.tar.xz | sudo dd of=/dev/sdX bs=4k +xz -dc images/ubuntu-24.04-preinstalled-desktop-arm64-rpi.img.xz | sudo dd of=/dev/sdX bs=4M status=progress conv=fsync ``` > This assumes that the removable media is added as /dev/sdX and all it’s partitions are unmounted. diff --git a/build.sh b/build.sh index a6b26fe..58164ef 100755 --- a/build.sh +++ b/build.sh @@ -8,6 +8,11 @@ if [ "$(id -u)" -ne 0 ]; then exit 1 fi +# Profile (legacy or rpi): use argument so it works with sudo. E.g. sudo ./build.sh rpi +if [ -n "$1" ]; then + export BUILD_PROFILE="$1" +fi + # Build the U-Boot bootloader ./scripts/build-u-boot.sh @@ -18,4 +23,4 @@ fi ./scripts/build-rootfs.sh # Build the Ubuntu preinstalled images -./scripts/build-image.sh \ No newline at end of file +./scripts/build-image.sh diff --git a/scripts/build-image.sh b/scripts/build-image.sh index 4eb8280..96dbfe5 100755 --- a/scripts/build-image.sh +++ b/scripts/build-image.sh @@ -199,6 +199,15 @@ dtoverlay=dwc2,dr_mode=host [all] EOF + # Pi 5 uses rpi_arm64_defconfig (same binary as [all]); add [pi5] for correct DTB + cat >> ${mount_point}/boot/config.txt << EOF + +[pi5] +kernel=u-boot-rpi-arm64.bin +device_tree=bcm2712-rpi-5-b.dtb +os_check=0 +EOF + # Copy uboot binary cp u-boot-rpi-3.bin ${mount_point}/boot cp u-boot-rpi-4.bin ${mount_point}/boot @@ -221,4 +230,4 @@ EOF echo -e "\nCompressing $(basename "${img}.xz")\n" xz -9 --extreme --force --keep --quiet --threads=0 "${img}" rm -f "${img}" -done \ No newline at end of file +done diff --git a/scripts/build-kernel.sh b/scripts/build-kernel.sh index 347df27..953b19d 100755 --- a/scripts/build-kernel.sh +++ b/scripts/build-kernel.sh @@ -8,12 +8,22 @@ if [ "$(id -u)" -ne 0 ]; then exit 1 fi -cd "$(dirname -- "$(readlink -f -- "$0")")" && cd .. +REPO_ROOT="$(cd "$(dirname -- "$(readlink -f -- "$0")")/.." && pwd)" +[ -f "$REPO_ROOT/scripts/config" ] && source "$REPO_ROOT/scripts/config" + +# Kernel ref: use RPI_RELEASE (same as firmware) for compatibility across all platforms +KERNEL_REF="${RPI_RELEASE:-rpi-6.1.y}" + +cd "$REPO_ROOT" mkdir -p build && cd build # Download the raspberry pi linux kernel source if [ ! -d linux ]; then - git clone --depth=1 --progress -b 1.20220830 https://github.com/raspberrypi/linux + git clone --depth=1 --progress -b "$KERNEL_REF" https://github.com/raspberrypi/linux +else + git -C linux fetch origin + git -C linux checkout "$KERNEL_REF" 2>/dev/null || git -C linux checkout "origin/$KERNEL_REF" 2>/dev/null || true + git -C linux pull --ff-only origin "$KERNEL_REF" 2>/dev/null || true fi cd linux diff --git a/scripts/build-rootfs.sh b/scripts/build-rootfs.sh index 07e6748..336c75e 100755 --- a/scripts/build-rootfs.sh +++ b/scripts/build-rootfs.sh @@ -8,7 +8,14 @@ if [ "$(id -u)" -ne 0 ]; then exit 1 fi -cd "$(dirname -- "$(readlink -f -- "$0")")" && cd .. +REPO_ROOT="$(cd "$(dirname -- "$(readlink -f -- "$0")")/.." && pwd)" +[ -f "$REPO_ROOT/scripts/config" ] && source "$REPO_ROOT/scripts/config" + +# Firmware ref: use RPI_FIRMWARE_TAG if set (for Pi 5 use e.g. 1.20240306), else RPI_RELEASE. +# Config profiles (config.legacy / config.rpi) always set these. +FIRMWARE_REF="${RPI_FIRMWARE_TAG:-$RPI_RELEASE}" + +cd "$REPO_ROOT" mkdir -p build && cd build if [ ! -d linux ]; then @@ -18,7 +25,14 @@ fi # Download the raspberry pi firmware if [ ! -d firmware ]; then - git clone --depth 1 --progress -b 1.20220830 https://github.com/raspberrypi/firmware.git + git clone --depth 1 --progress -b "$FIRMWARE_REF" https://github.com/raspberrypi/firmware.git +else + if [ -n "$FIRMWARE_REF" ]; then + git -C firmware fetch origin tag "$FIRMWARE_REF" --no-tags 2>/dev/null || git -C firmware fetch origin 2>/dev/null || true + git -C firmware checkout "$FIRMWARE_REF" 2>/dev/null || true + else + git -C firmware pull --ff-only + fi fi # These env vars can cause issues with chroot @@ -26,12 +40,20 @@ unset TMP unset TEMP unset TMPDIR -# Debootstrap options +# Debootstrap options (UBUNTU_RELEASE from config: focal=20.04, jammy=22.04, noble=24.04) arch=arm64 -release=focal +release="${UBUNTU_RELEASE:-focal}" mirror=http://ports.ubuntu.com/ubuntu-ports chroot_dir=rootfs +# Version for output tarball names (e.g. 20.04, 22.04, 24.04) +case "$release" in + focal) UBUNTU_VERSION=20.04 ;; + jammy) UBUNTU_VERSION=22.04 ;; + noble) UBUNTU_VERSION=24.04 ;; + *) UBUNTU_VERSION="${release}" ;; +esac + # Clean chroot dir and make sure folder is not mounted umount -lf ${chroot_dir}/dev/pts 2> /dev/null || true umount -lf ${chroot_dir}/* 2> /dev/null || true @@ -346,7 +368,7 @@ umount -lf ${chroot_dir}/dev/pts 2> /dev/null || true umount -lf ${chroot_dir}/* 2> /dev/null || true # Tar the entire rootfs -cd ${chroot_dir} && XZ_OPT="-0 -T0" tar -cpJf ../ubuntu-20.04-preinstalled-server-arm64-rpi.rootfs.tar.xz . && cd .. +cd ${chroot_dir} && XZ_OPT="-0 -T0" tar -cpJf ../ubuntu-${UBUNTU_VERSION}-preinstalled-server-arm64-rpi.rootfs.tar.xz . && cd .. # Mount the temporary API filesystems mkdir -p ${chroot_dir}/{proc,sys,run,dev,dev/pts} @@ -378,4 +400,4 @@ umount -lf ${chroot_dir}/dev/pts 2> /dev/null || true umount -lf ${chroot_dir}/* 2> /dev/null || true # Tar the entire rootfs -cd ${chroot_dir} && XZ_OPT="-0 -T0" tar -cpJf ../ubuntu-20.04-preinstalled-desktop-arm64-rpi.rootfs.tar.xz . && cd .. +cd ${chroot_dir} && XZ_OPT="-0 -T0" tar -cpJf ../ubuntu-${UBUNTU_VERSION}-preinstalled-desktop-arm64-rpi.rootfs.tar.xz . && cd .. diff --git a/scripts/build-u-boot.sh b/scripts/build-u-boot.sh index ee1f382..2dd940e 100755 --- a/scripts/build-u-boot.sh +++ b/scripts/build-u-boot.sh @@ -8,12 +8,26 @@ if [ "$(id -u)" -ne 0 ]; then exit 1 fi -cd "$(dirname -- "$(readlink -f -- "$0")")" && cd .. +REPO_ROOT="$(cd "$(dirname -- "$(readlink -f -- "$0")")/.." && pwd)" +[ -f "$REPO_ROOT/scripts/config" ] && source "$REPO_ROOT/scripts/config" + +cd "$REPO_ROOT" mkdir -p build && cd build -# Download and build u-boot +# Download and build u-boot (use UBOOT_TAG from scripts/config for a compatible release) if [ ! -d u-boot ]; then - git clone --progress --depth=1 -b v2022.01 http://git.denx.de/u-boot.git + if [ -n "$UBOOT_TAG" ]; then + git clone --progress --depth=1 -b "$UBOOT_TAG" https://github.com/u-boot/u-boot.git + else + git clone --progress --depth=1 https://github.com/u-boot/u-boot.git + fi +else + if [ -n "$UBOOT_TAG" ]; then + git -C u-boot fetch origin tag "$UBOOT_TAG" --no-tags 2>/dev/null || true + git -C u-boot checkout "$UBOOT_TAG" 2>/dev/null || true + else + git -C u-boot pull --ff-only + fi fi cd u-boot @@ -39,4 +53,5 @@ make ARCH=arm CROSS_COMPILE=aarch64-linux-gnu- rpi_arm64_defconfig # Compile u-boot binary make ARCH=arm CROSS_COMPILE=aarch64-linux-gnu- -j "$(nproc)" -cp u-boot.bin ../u-boot-rpi-arm64.bin \ No newline at end of file +cp u-boot.bin ../u-boot-rpi-arm64.bin +# Pi 5 uses the same binary (rpi_arm64_defconfig) diff --git a/scripts/config b/scripts/config new file mode 100644 index 0000000..a11974f --- /dev/null +++ b/scripts/config @@ -0,0 +1,7 @@ +# Build profile: "legacy" (Pi 0/3/4/400) or "rpi" (adds Pi 5). +# Switch by setting BUILD_PROFILE or editing the line below. +BUILD_PROFILE="${BUILD_PROFILE:-legacy}" + +CONFIG_DIR="$(dirname -- "$(readlink -f -- "${BASH_SOURCE[0]:-$0}")")" +# shellcheck source=config.legacy +[ -f "$CONFIG_DIR/config.$BUILD_PROFILE" ] && source "$CONFIG_DIR/config.$BUILD_PROFILE" diff --git a/scripts/config.legacy b/scripts/config.legacy new file mode 100644 index 0000000..13404e9 --- /dev/null +++ b/scripts/config.legacy @@ -0,0 +1,7 @@ +# Original build: Pi Zero 2W, Pi 3, Pi 4, Pi 400 (no Pi 5). +# Same kernel/firmware refs as the original ubuntu-raspberry-pi project. + +RPI_RELEASE="${RPI_RELEASE:-1.20220830}" +RPI_FIRMWARE_TAG="${RPI_FIRMWARE_TAG:-1.20220830}" +UBOOT_TAG="${UBOOT_TAG:-v2022.01}" +UBUNTU_RELEASE="${UBUNTU_RELEASE:-focal}" \ No newline at end of file diff --git a/scripts/config.rpi b/scripts/config.rpi new file mode 100644 index 0000000..346b819 --- /dev/null +++ b/scripts/config.rpi @@ -0,0 +1,9 @@ +# RPi build (all 64-bit variants including Pi 5). +# Kernel branch and firmware tag that include Pi 5 (BCM2712) support. +# Pi 5 uses the same U-Boot as other 64-bit boards: rpi_arm64_defconfig (u-boot-rpi-arm64.bin). +# UBUNTU_RELEASE: noble=24.04, jammy=22.04 + +RPI_RELEASE="${RPI_RELEASE:-rpi-6.12.y}" +RPI_FIRMWARE_TAG="${RPI_FIRMWARE_TAG:-1.20250915}" +UBOOT_TAG="${UBOOT_TAG:-v2026.01}" +UBUNTU_RELEASE="${UBUNTU_RELEASE:-noble}"