Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimize build script for Raspberry Pi 4 #407

Merged
merged 15 commits into from
Nov 13, 2020
Merged
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,16 @@ The following example uses Docker and assumes you have Docker correctly installe

4) When done, your image will be in the `builds` folder.

## Raspberry Pi 4

```
docker run --privileged -i -v /proc:/proc \
-v ${PWD}:/working_dir \
-w /working_dir \
debian:unstable \
./build-rpi.sh
```

## Further Information

More information about the concepts behind `live-build` and the technical decisions made to arrive at this set of tools to build an .iso can be found [on the wiki](https://github.com/elementary/os/wiki/Building-iso-Images).
77 changes: 44 additions & 33 deletions build-rpi.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,27 @@

# Install dependencies in host system
apt-get update
apt-get install -y --no-install-recommends ubuntu-keyring debootstrap qemu-user-static qemu-utils qemu-system-arm binfmt-support parted kpartx rsync dosfstools
apt-get install -y --no-install-recommends ubuntu-keyring debootstrap qemu-user-static qemu-utils qemu-system-arm binfmt-support parted kpartx rsync dosfstools xz-utils

# Make sure cross-running ARM ELF executables is enabled
update-binfmts --enable

rootdir=`pwd`
basedir=`pwd`/elementary-rpi
basedir=`pwd`/artifacts/elementary-rpi

# Size of .img file to build in MB. Approx 4GB required at this time, the rest is free space on /
size=5000
size=8000

export packages="elementary-minimal elementary-desktop elementary-standard"
export architecture="armhf"
export architecture="arm64"
export codename="focal"
export codename_latest="groovy"
export channel="daily"

version=6.0
YYYYMMDD="$(date +%Y%m%d)"
imagename=elementaryos-$version-$channel-rpi-$YYYYMMDD

mkdir -p ${basedir}
cd ${basedir}

Expand All @@ -30,6 +35,9 @@ cp /usr/bin/qemu-arm-static elementary-$architecture/usr/bin/
# Run the second stage of the bootstrap in QEMU
LANG=C chroot elementary-$architecture /debootstrap/debootstrap --second-stage

# Copy Raspberry Pi specific files
cp -r ${rootdir}/rpi/rootfs/writable/* elementary-${architecture}/

# Add the rest of the ubuntu repos
cat << EOF > elementary-$architecture/etc/apt/sources.list
deb http://ports.ubuntu.com/ubuntu-ports $codename main restricted universe multiverse
Expand All @@ -44,6 +52,11 @@ for f in ${rootdir}/etc/config/archives/*.pref; do cp -- "$f" "elementary-$archi
# Set codename/channel in added repos
sed -i "s/@CHANNEL/$channel/" elementary-$architecture/etc/apt/sources.list.d/*.list*
sed -i "s/@BASECODENAME/$codename/" elementary-$architecture/etc/apt/sources.list.d/*.list*
sed -i "s/@LATESTCODENAME/$codename_latest/" elementary-$architecture/etc/apt/sources.list.d/*.list*

# Set codename in added preferences
sed -i "s/@BASECODENAME/$codename/" elementary-$architecture/etc/apt/preferences.d/*.pref*
sed -i "s/@LATESTCODENAME/$codename_latest/" elementary-$architecture/etc/apt/preferences.d/*.pref*

echo "elementary" > elementary-$architecture/etc/hostname

Expand All @@ -60,8 +73,8 @@ EOF
cat << EOF > elementary-${architecture}/etc/fstab
# <file system> <mount point> <type> <options> <dump> <pass>
proc /proc proc nodev,noexec,nosuid 0 0
/dev/mmcblk0p2 / ext4 errors=remount-ro 0 1
/dev/mmcblk0p1 /boot/firmware vfat noauto 0 0
LABEL=writable / ext4 defaults,x-systemd.growfs 0 0
LABEL=system-boot /boot/firmware vfat defaults 0 1
EOF

export LC_ALL=C
Expand All @@ -88,21 +101,21 @@ LANG=C chroot elementary-$architecture /third-stage

# Create the disk and partition it
echo "Creating image file for Raspberry Pi"
dd if=/dev/zero of=${basedir}/elementary-rpi.img bs=1M count=$size
parted elementary-rpi.img --script -- mklabel msdos
parted elementary-rpi.img --script -- mkpart primary fat32 0 128
parted elementary-rpi.img --script -- mkpart primary ext4 128 -1
dd if=/dev/zero of=${basedir}/${imagename}.img bs=1M count=$size
parted ${imagename}.img --script -- mklabel msdos
parted ${imagename}.img --script -- mkpart primary fat32 0 256
parted ${imagename}.img --script -- mkpart primary ext4 256 -1

# Set the partition variables
loopdevice=`losetup -f --show ${basedir}/elementary-rpi.img`
loopdevice=`losetup -f --show ${basedir}/${imagename}.img`
device=`kpartx -va $loopdevice| sed -E 's/.*(loop[0-9])p.*/\1/g' | head -1`
device="/dev/mapper/${device}"
bootp=${device}p1
rootp=${device}p2

# Create file systems
mkfs.vfat $bootp
mkfs.ext4 $rootp
mkfs.vfat -n system-boot $bootp
mkfs.ext4 -L writable $rootp

# Create the dirs for the partitions and mount them
mkdir -p ${basedir}/bootp ${basedir}/root
Expand All @@ -112,36 +125,27 @@ mount $rootp ${basedir}/root
mkdir -p elementary-$architecture/boot/firmware
mount -o bind ${basedir}/bootp/ elementary-$architecture/boot/firmware

# RPi specific config files to configure bootloader
cat << EOF > elementary-$architecture/boot/firmware/config.txt
kernel=vmlinuz
initramfs initrd.img followkernel

enable_uart=1
dtparam=i2c_arm=on
dtparam=spi=on
EOF
# Copy Raspberry Pi specific files
cp -r ${rootdir}/rpi/rootfs/system-boot/* elementary-${architecture}/boot/firmware/

cat << EOF > elementary-$architecture/boot/firmware/cmdline.txt
net.ifnames=0 dwc_otg.lpm_enable=0 console=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait fixrtc
EOF

# Install an RPi kernel and firmware
cat << EOF > elementary-$architecture/kernel
# Install Raspberry Pi specific packages
cat << EOF > elementary-$architecture/hardware
#!/bin/bash
apt-get --yes install linux-image-raspi linux-firmware-raspi2 u-boot-rpi
apt-get --yes install linux-image-raspi linux-firmware-raspi2 u-boot-rpi grub-efi-arm64 rpi-eeprom ubuntu-raspi-settings

cp /boot/vmlinuz /boot/firmware/vmlinuz
cp /boot/initrd.img /boot/firmware/initrd.img

# Copy device-tree blobs to fat32 partition
cp -r /lib/firmware/*-raspi/device-tree/* /boot/firmware/
cp -r /lib/firmware/*-raspi/device-tree/broadcom/* /boot/firmware/
cp -r /lib/firmware/*-raspi/device-tree/overlays /boot/firmware/
cp -r /usr/lib/*-raspi2/* /boot/firmware/

rm -f kernel
rm -f hardware
EOF

chmod +x elementary-$architecture/kernel
LANG=C chroot elementary-$architecture /kernel
chmod +x elementary-$architecture/hardware
LANG=C chroot elementary-$architecture /hardware

# Copy in any file overrides
cp -r ${rootdir}/etc/config/includes.chroot/* elementary-$architecture/
Expand Down Expand Up @@ -194,3 +198,10 @@ umount $rootp
kpartx -dv $loopdevice
losetup -d $loopdevice

echo "Compressing ${imagename}.img"
xz -z ${basedir}/${imagename}.img

cd "${basedir}"

md5sum ${imagename}.img.xz > ${imagename}.md5.txt
sha256sum ${imagename}.img.xz > ${imagename}.sha256.txt
1 change: 1 addition & 0 deletions rpi/rootfs/system-boot/cmdline.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
net.ifnames=0 dwc_otg.lpm_enable=0 console=ttyAMA0,115200 console=tty1 root=LABEL=writable rootfstype=ext4 elevator=deadline rootwait fixrtc
32 changes: 32 additions & 0 deletions rpi/rootfs/system-boot/config.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
[pi4]
max_framebuffers=2

[all]
arm_64bit=1
kernel=vmlinuz
cmdline=cmdline.txt
initramfs initrd.img followkernel

# Enable the audio output, I2C and SPI interfaces on the GPIO header
dtparam=audio=on
dtparam=i2c_arm=on
dtparam=spi=on

# Enable the FKMS ("Fake" KMS) graphics overlay, enable the camera firmware
# and allocate 128Mb to the GPU memory
dtoverlay=vc4-fkms-v3d
gpu_mem=128
start_x=1

# Comment out the following line if the edges of the desktop appear outside
# the edges of your display
disable_overscan=1

# If you have issues with audio, you may try uncommenting the following line
# which forces the HDMI output into HDMI mode instead of DVI (which doesn't
# support audio output)
#hdmi_drive=2

# If you have a CM4, uncomment the following line to enable the USB2 outputs
# on the IO board (assuming your CM4 is plugged into such a board)
#dtoverlay=dwc2,dr_mode=host
37 changes: 37 additions & 0 deletions rpi/rootfs/writable/etc/apt/preferences.d/rpi.pref
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
Package: linux-firmware-raspi2
Pin: release n=@LATESTCODENAME
Pin-Priority: 990

Package: linux*-raspi*
Pin: release n=@LATESTCODENAME
Pin-Priority: 990

Package: ubuntu-raspi-settings
Pin: release n=@LATESTCODENAME
Pin-Priority: 990

Package: rpi-eeprom
Pin: release n=@LATESTCODENAME
Pin-Priority: 990

Package: libraspberrypi*
Pin: release n=@LATESTCODENAME
Pin-Priority: 990

Package: u-boot-rpi
Pin: release n=@LATESTCODENAME
Pin-Priority: 990

Package: grub*
Pin: release n=@LATESTCODENAME
Pin-Priority: 990

Explanation: Uninstall or do not install any Ubuntu-originated
Explanation: package versions other than those in the @BASECODENAME release
Package: *
Pin: release n=@BASECODENAME
Pin-Priority: 900

Package: *
Pin: release o=Ubuntu
Pin-Priority: -10
2 changes: 2 additions & 0 deletions rpi/rootfs/writable/etc/apt/sources.list.d/ubuntu-latest.list
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
deb http://ports.ubuntu.com/ubuntu-ports @LATESTCODENAME main restricted universe multiverse
deb http://ports.ubuntu.com/ubuntu-ports @LATESTCODENAME-updates main restricted universe multiverse
5 changes: 5 additions & 0 deletions rpi/rootfs/writable/etc/oem.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[OEM]
Manufacturer=Raspberry Pi Foundation
Product=Raspberry Pi
Logo=/etc/oem/logo.png
URL=https://www.raspberrypi.org/
Binary file added rpi/rootfs/writable/etc/oem/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.