Skip to content

Commit 44e7649

Browse files
Add Raspberry Pi build script (elementary#343)
* Add Raspberry Pi build script * Optimize build script for Raspberry Pi 4 (elementary#407) * Update README.md * Add oneshot service to resize rootfs on first boot * Fix path * Get firmware directly from RPi foundation Means we can keep the correct kernel version from focal * Run the same hooks as the amd64 image * Fix paths * Fix paths some more * Make sure we have git dependency * Add some multithreading to xz * Rework image size calculation * Fix firmware package install * Make sure we have certificates to verify https from github * Remove old firmware copy * Remove systemd growfs stuff * Fix resize script * Try to make plymouth show * Use SVG as OEM logo * Add Pi 400 support to flash-kernel * Upload images to bucket * Add a workflow file Co-authored-by: Marius Meisenzahl <[email protected]> Co-authored-by: Marius Meisenzahl <[email protected]>
1 parent 3d99738 commit 44e7649

File tree

8 files changed

+458
-0
lines changed

8 files changed

+458
-0
lines changed

.github/workflows/daily-6.0-rpi.yml

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
name: daily-6.0-rpi
2+
3+
on:
4+
push:
5+
branches:
6+
- master
7+
- github-update
8+
schedule:
9+
- cron: "0 0 * * *"
10+
workflow_dispatch: {}
11+
12+
jobs:
13+
build:
14+
runs-on: ubuntu-20.04
15+
16+
steps:
17+
- name: Clone build scripts
18+
uses: actions/checkout@v1
19+
20+
- name: Build and upload image
21+
run: |
22+
sudo ./build-rpi.sh "${{ secrets.key }}" "${{ secrets.secret }}" "${{ secrets.endpoint }}" "${{ secrets.bucket }}"

README.md

+11
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,17 @@ The following example uses Docker and assumes you have Docker correctly installe
4545
4646
4) When done, your image will be in the `builds` folder.
4747
48+
## Raspberry Pi 4
49+
50+
```
51+
docker run --privileged -i -v /proc:/proc \
52+
-v ${PWD}:/working_dir \
53+
-w /working_dir \
54+
debian:unstable \
55+
./build-rpi.sh
56+
```
57+
58+
4859
## Further Information
4960
5061
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).

build-rpi.sh

+261
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,261 @@
1+
#!/bin/bash
2+
3+
set -e
4+
5+
# Install dependencies in host system
6+
apt-get update
7+
apt-get install -y --no-install-recommends ubuntu-keyring ca-certificates debootstrap git qemu-user-static qemu-utils qemu-system-arm binfmt-support parted kpartx rsync dosfstools xz-utils
8+
9+
# Make sure cross-running ARM ELF executables is enabled
10+
update-binfmts --enable
11+
12+
rootdir=`pwd`
13+
basedir=`pwd`/artifacts/elementary-rpi
14+
15+
# Free space on rootfs in MiB
16+
free_space="500"
17+
18+
export packages="elementary-minimal elementary-desktop elementary-standard"
19+
export architecture="arm64"
20+
export codename="focal"
21+
export channel="daily"
22+
23+
version=6.0
24+
YYYYMMDD="$(date +%Y%m%d)"
25+
imagename=elementaryos-$version-$channel-rpi-$YYYYMMDD
26+
27+
mkdir -p ${basedir}
28+
cd ${basedir}
29+
30+
# Bootstrap an ubuntu minimal system
31+
debootstrap --foreign --arch $architecture $codename elementary-$architecture http://ports.ubuntu.com/ubuntu-ports
32+
33+
# Add the QEMU emulator for running ARM executables
34+
cp /usr/bin/qemu-arm-static elementary-$architecture/usr/bin/
35+
36+
# Run the second stage of the bootstrap in QEMU
37+
LANG=C chroot elementary-$architecture /debootstrap/debootstrap --second-stage
38+
39+
# Copy Raspberry Pi specific files
40+
cp -r ${rootdir}/rpi/rootfs/writable/* elementary-${architecture}/
41+
42+
# Add the rest of the ubuntu repos
43+
cat << EOF > elementary-$architecture/etc/apt/sources.list
44+
deb http://ports.ubuntu.com/ubuntu-ports $codename main restricted universe multiverse
45+
deb http://ports.ubuntu.com/ubuntu-ports $codename-updates main restricted universe multiverse
46+
EOF
47+
48+
# Copy in the elementary PPAs/keys/apt config
49+
for f in ${rootdir}/etc/config/archives/*.list; do cp -- "$f" "elementary-$architecture/etc/apt/sources.list.d/$(basename -- $f)"; done
50+
for f in ${rootdir}/etc/config/archives/*.key; do cp -- "$f" "elementary-$architecture/etc/apt/trusted.gpg.d/$(basename -- $f).asc"; done
51+
for f in ${rootdir}/etc/config/archives/*.pref; do cp -- "$f" "elementary-$architecture/etc/apt/preferences.d/$(basename -- $f)"; done
52+
53+
# Set codename/channel in added repos
54+
sed -i "s/@CHANNEL/$channel/" elementary-$architecture/etc/apt/sources.list.d/*.list*
55+
sed -i "s/@BASECODENAME/$codename/" elementary-$architecture/etc/apt/sources.list.d/*.list*
56+
57+
# Set codename in added preferences
58+
sed -i "s/@BASECODENAME/$codename/" elementary-$architecture/etc/apt/preferences.d/*.pref*
59+
60+
echo "elementary" > elementary-$architecture/etc/hostname
61+
62+
cat << EOF > elementary-${architecture}/etc/hosts
63+
127.0.0.1 elementary localhost
64+
::1 localhost ip6-localhost ip6-loopback
65+
fe00::0 ip6-localnet
66+
ff00::0 ip6-mcastprefix
67+
ff02::1 ip6-allnodes
68+
ff02::2 ip6-allrouters
69+
EOF
70+
71+
# Configure mount points
72+
cat << EOF > elementary-${architecture}/etc/fstab
73+
# <file system> <mount point> <type> <options> <dump> <pass>
74+
proc /proc proc nodev,noexec,nosuid 0 0
75+
LABEL=writable / ext4 defaults 0 0
76+
LABEL=system-boot /boot/firmware vfat defaults 0 1
77+
EOF
78+
79+
export LC_ALL=C
80+
export DEBIAN_FRONTEND=noninteractive
81+
# Config to stop flash-kernel trying to detect the hardware in chroot
82+
export FK_MACHINE=none
83+
84+
mount -t proc proc elementary-$architecture/proc
85+
mount -o bind /dev/ elementary-$architecture/dev/
86+
mount -o bind /dev/pts elementary-$architecture/dev/pts
87+
88+
# Make a third stage that installs all of the metapackages
89+
cat << EOF > elementary-$architecture/third-stage
90+
#!/bin/bash
91+
apt-get update
92+
apt-get --yes upgrade
93+
apt-get --yes install $packages
94+
95+
rm -f /third-stage
96+
EOF
97+
98+
chmod +x elementary-$architecture/third-stage
99+
LANG=C chroot elementary-$architecture /third-stage
100+
101+
102+
# Install Raspberry Pi specific packages
103+
cat << EOF > elementary-$architecture/hardware
104+
#!/bin/bash
105+
106+
# Make a dummy folder for the boot partition so packages install properly,
107+
# we'll recreate it on the actual partition later
108+
mkdir -p /boot/firmware
109+
110+
apt-get --yes install linux-image-raspi linux-firmware-raspi2
111+
112+
rm -rf /boot/firmware
113+
114+
rm -f hardware
115+
EOF
116+
117+
chmod +x elementary-$architecture/hardware
118+
LANG=C chroot elementary-$architecture /hardware
119+
120+
# Copy in any file overrides
121+
cp -r ${rootdir}/etc/config/includes.chroot/* elementary-$architecture/
122+
123+
mkdir elementary-$architecture/hooks
124+
cp ${rootdir}/etc/config/hooks/live/*.chroot elementary-$architecture/hooks
125+
126+
for f in elementary-$architecture/hooks/*
127+
do
128+
base=`basename ${f}`
129+
LANG=C chroot elementary-$architecture "/hooks/${base}"
130+
done
131+
132+
rm -r "elementary-$architecture/hooks"
133+
134+
# Add a oneshot service to grow the rootfs on first boot
135+
install -m 755 -o root -g root ${rootdir}/rpi/files/resizerootfs "elementary-$architecture/usr/sbin/resizerootfs"
136+
install -m 644 -o root -g root ${rootdir}/pinebookpro/files/resizerootfs.service "elementary-$architecture/etc/systemd/system"
137+
mkdir -p "elementary-$architecture/etc/systemd/system/systemd-remount-fs.service.requires/"
138+
ln -s /etc/systemd/system/resizerootfs.service "elementary-$architecture/etc/systemd/system/systemd-remount-fs.service.requires/resizerootfs.service"
139+
140+
141+
# Support for kernel updates on the Pi 400
142+
cat << EOF >> elementary-$architecture/etc/flash-kernel/db
143+
144+
Machine: Raspberry Pi 400 Rev 1.0
145+
Method: pi
146+
Kernel-Flavors: raspi raspi2
147+
DTB-Id: bcm2711-rpi-4-b.dtb
148+
U-Boot-Script-Name: bootscr.rpi
149+
Required-Packages: u-boot-tools
150+
EOF
151+
152+
# Calculate the space to create the image.
153+
root_size=$(du -s -B1K elementary-$architecture | cut -f1)
154+
raw_size=$(($((${free_space}*1024))+${root_size}))
155+
156+
# Create the disk and partition it
157+
echo "Creating image file"
158+
159+
# Sometimes fallocate fails if the filesystem or location doesn't support it, fallback to slower dd in this case
160+
if ! fallocate -l $(echo ${raw_size}Ki | numfmt --from=iec-i --to=si --format=%.1f) ${basedir}/${imagename}.img
161+
then
162+
dd if=/dev/zero of=${basedir}/${imagename}.img bs=1024 count=${raw_size}
163+
fi
164+
165+
parted ${imagename}.img --script -- mklabel msdos
166+
parted ${imagename}.img --script -- mkpart primary fat32 0 256
167+
parted ${imagename}.img --script -- mkpart primary ext4 256 -1
168+
169+
# Set the partition variables
170+
loopdevice=`losetup -f --show ${basedir}/${imagename}.img`
171+
device=`kpartx -va $loopdevice| sed -E 's/.*(loop[0-9])p.*/\1/g' | head -1`
172+
device="/dev/mapper/${device}"
173+
bootp=${device}p1
174+
rootp=${device}p2
175+
176+
# Create file systems
177+
mkfs.vfat -n system-boot $bootp
178+
mkfs.ext4 -L writable $rootp
179+
180+
# Create the dirs for the partitions and mount them
181+
mkdir -p ${basedir}/bootp ${basedir}/root
182+
mount -t vfat $bootp ${basedir}/bootp
183+
mount $rootp ${basedir}/root
184+
185+
mkdir -p elementary-$architecture/boot/firmware
186+
mount -o bind ${basedir}/bootp/ elementary-$architecture/boot/firmware
187+
188+
# Copy Raspberry Pi specific files
189+
cp -r ${rootdir}/rpi/rootfs/system-boot/* elementary-${architecture}/boot/firmware/
190+
191+
# Copy kernels and firemware to boot partition
192+
cat << EOF > elementary-$architecture/hardware
193+
#!/bin/bash
194+
195+
cp /boot/vmlinuz /boot/firmware/vmlinuz
196+
cp /boot/initrd.img /boot/firmware/initrd.img
197+
198+
# Copy device-tree blobs to fat32 partition
199+
cp -r /lib/firmware/*-raspi/device-tree/broadcom/* /boot/firmware/
200+
cp -r /lib/firmware/*-raspi/device-tree/overlays /boot/firmware/
201+
202+
rm -f hardware
203+
EOF
204+
205+
chmod +x elementary-$architecture/hardware
206+
LANG=C chroot elementary-$architecture /hardware
207+
208+
# Grab some updated firmware from the Raspberry Pi foundation
209+
git clone -b '1.20201022' --single-branch --depth 1 https://github.com/raspberrypi/firmware raspi-firmware
210+
cp raspi-firmware/boot/*.elf ${basedir}/bootp/
211+
cp raspi-firmware/boot/*.dat ${basedir}/bootp/
212+
cp raspi-firmware/boot/bootcode.bin ${basedir}/bootp/
213+
214+
umount elementary-$architecture/dev/pts
215+
umount elementary-$architecture/dev/
216+
umount elementary-$architecture/proc
217+
umount elementary-$architecture/boot/firmware
218+
219+
echo "Rsyncing rootfs into image file"
220+
rsync -HPavz -q ${basedir}/elementary-$architecture/ ${basedir}/root/
221+
222+
# Unmount partitions
223+
umount $bootp
224+
umount $rootp
225+
kpartx -dv $loopdevice
226+
losetup -d $loopdevice
227+
228+
echo "Compressing ${imagename}.img"
229+
xz -T0 -z ${basedir}/${imagename}.img
230+
231+
cd "${basedir}"
232+
233+
md5sum ${imagename}.img.xz > ${imagename}.md5.txt
234+
sha256sum ${imagename}.img.xz > ${imagename}.sha256.txt
235+
236+
cd "${rootdir}"
237+
238+
KEY="$1"
239+
SECRET="$2"
240+
ENDPOINT="$3"
241+
BUCKET="$4"
242+
IMGPATH="${basedir}"/${imagename}.img.xz
243+
IMGNAME=${channel}-rpi/$(basename "$IMGPATH")
244+
245+
apt-get install -y curl python3 python3-distutils
246+
247+
curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
248+
python3 get-pip.py
249+
pip install boto3
250+
251+
python3 upload.py "$KEY" "$SECRET" "$ENDPOINT" "$BUCKET" "$IMGPATH" "$IMGNAME" || exit 1
252+
253+
CHECKSUMPATH="${basedir}"/${imagename}.md5.txt
254+
CHECKSUMNAME=${channel}-rpi/$(basename "$CHECKSUMPATH")
255+
256+
python3 upload.py "$KEY" "$SECRET" "$ENDPOINT" "$BUCKET" "$CHECKSUMPATH" "$CHECKSUMNAME" || exit 1
257+
258+
CHECKSUMPATH="${basedir}"/${imagename}.sha256.txt
259+
CHECKSUMNAME=${channel}-rpi/$(basename "$CHECKSUMPATH")
260+
261+
python3 upload.py "$KEY" "$SECRET" "$ENDPOINT" "$BUCKET" "$CHECKSUMPATH" "$CHECKSUMNAME" || exit 1

rpi/files/resizerootfs

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#!/bin/sh
2+
3+
rootpart="$(findmnt -n -o SOURCE /)"
4+
rootdev="/dev/$(lsblk -no pkname "$rootpart")"
5+
6+
flock $rootdev sfdisk -f $rootdev -N 2 <<EOF
7+
,+
8+
EOF
9+
10+
sleep 5
11+
12+
udevadm settle
13+
14+
sleep 5
15+
16+
flock $rootdev partprobe $rootdev
17+
18+
mount -o remount,rw $rootpart
19+
20+
resize2fs $rootpart
21+
22+
exit 0

rpi/rootfs/system-boot/cmdline.txt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
net.ifnames=0 dwc_otg.lpm_enable=0 console=ttyAMA0,115200 console=tty1 root=LABEL=writable rootfstype=ext4 elevator=deadline rootwait fixrtc quiet splash plymouth.ignore-serial-consoles

rpi/rootfs/system-boot/config.txt

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
[pi4]
2+
max_framebuffers=2
3+
4+
[all]
5+
arm_64bit=1
6+
kernel=vmlinuz
7+
cmdline=cmdline.txt
8+
initramfs initrd.img followkernel
9+
10+
# Enable the audio output, I2C and SPI interfaces on the GPIO header
11+
dtparam=audio=on
12+
dtparam=i2c_arm=on
13+
dtparam=spi=on
14+
15+
# Enable the FKMS ("Fake" KMS) graphics overlay, enable the camera firmware
16+
# and allocate 128Mb to the GPU memory
17+
dtoverlay=vc4-fkms-v3d
18+
gpu_mem=128
19+
start_x=1
20+
21+
# Comment out the following line if the edges of the desktop appear outside
22+
# the edges of your display
23+
disable_overscan=1
24+
25+
# If you have issues with audio, you may try uncommenting the following line
26+
# which forces the HDMI output into HDMI mode instead of DVI (which doesn't
27+
# support audio output)
28+
#hdmi_drive=2
29+
30+
# If you have a CM4, uncomment the following line to enable the USB2 outputs
31+
# on the IO board (assuming your CM4 is plugged into such a board)
32+
#dtoverlay=dwc2,dr_mode=host

rpi/rootfs/writable/etc/oem.conf

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[OEM]
2+
Manufacturer=Raspberry Pi Foundation
3+
Product=Raspberry Pi
4+
Logo=/etc/oem/logo.svg
5+
URL=https://www.raspberrypi.org/

0 commit comments

Comments
 (0)