Skip to content

Commit fae8b3f

Browse files
authored
fix: fix firstboot issue (#214)
1 parent b82137c commit fae8b3f

File tree

6 files changed

+316
-5
lines changed

6 files changed

+316
-5
lines changed

config/raspberry/default

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ BASE_IMAGE_RESIZEROOT=600
99
# Compress not needed due compression done in workflow
1010
BASE_RELEASE_COMPRESS=no
1111
# Modules are valid for 32bit and 64bit images
12-
MODULES="base,pkgupgrade,mainsailos(net,piconfig,klipper,is_req_preinstall,moonraker,timelapse,mainsail,crowsnest,sonar,password-for-sudo),postrename"
12+
MODULES="base,pkgupgrade,rpi_firstb_fix,mainsailos(net,piconfig,klipper,is_req_preinstall,moonraker,timelapse,mainsail,crowsnest,sonar,password-for-sudo),postrename"
1313

1414
# export Variables
1515
export BASE_IMAGE_ENLARGEROOT

src/modules/mainsailos/start_chroot_script

+5-3
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ fi
2222
source /common.sh
2323
install_cleanup_trap
2424

25-
# Create mainsailos release file
25+
## Step 1: Create mainsailos release file
2626
if [ -f "/etc/mainsailos_version" ]; then
2727
sudo rm -f /etc/mainsailos_version
2828
fi
@@ -31,8 +31,10 @@ function get_parent {
3131
}
3232

3333
echo "${DIST_NAME} release ${DIST_VERSION} ($(get_parent))" > /etc/"${DIST_NAME,,}"-release
34+
## END Step 1
3435

35-
### Install CANBoot Dependency
36-
apt update
36+
## Step 2: Install CANBoot Dependency
37+
apt-get update --allow-releaseinfo-change
3738
# shellcheck disable=SC2086
3839
check_install_pkgs ${MAINSAILOS_DEPS}
40+
## END Step 2

src/modules/rpi_firstb_fix/config

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#!/usr/bin/env bash
2+
# Shebang for better file detection
3+
#### rpi_firstb_fix module
4+
####
5+
#### Written by Stephan Wendel aka KwadFan <[email protected]>
6+
#### Copyright 2023 - till today
7+
#### https://github.com/mainsail-crew/MainsailOS
8+
####
9+
#### This File is distributed under GPLv3
10+
####
11+
12+
# Intentionally left blank
13+
# See start_chroot_script for information
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,264 @@
1+
#!/bin/bash
2+
# shellcheck disable=all
3+
4+
5+
reboot_pi () {
6+
umount /boot
7+
mount / -o remount,ro
8+
sync
9+
if [ "$NOOBS" = "1" ]; then
10+
if [ "$NEW_KERNEL" = "1" ]; then
11+
reboot -f "$BOOT_PART_NUM"
12+
sleep 5
13+
else
14+
echo "$BOOT_PART_NUM" > "/sys/module/${BCM_MODULE}/parameters/reboot_part"
15+
fi
16+
fi
17+
reboot -f
18+
sleep 5
19+
exit 0
20+
}
21+
22+
check_noobs () {
23+
if [ "$BOOT_PART_NUM" = "1" ]; then
24+
NOOBS=0
25+
else
26+
NOOBS=1
27+
fi
28+
}
29+
30+
get_variables () {
31+
ROOT_PART_DEV=$(findmnt / -o source -n)
32+
ROOT_PART_NAME=$(echo "$ROOT_PART_DEV" | cut -d "/" -f 3)
33+
ROOT_DEV_NAME=$(echo /sys/block/*/"${ROOT_PART_NAME}" | cut -d "/" -f 4)
34+
ROOT_DEV="/dev/${ROOT_DEV_NAME}"
35+
ROOT_PART_NUM=$(cat "/sys/block/${ROOT_DEV_NAME}/${ROOT_PART_NAME}/partition")
36+
37+
BOOT_PART_DEV=$(findmnt /boot -o source -n)
38+
BOOT_PART_NAME=$(echo "$BOOT_PART_DEV" | cut -d "/" -f 3)
39+
BOOT_DEV_NAME=$(echo /sys/block/*/"${BOOT_PART_NAME}" | cut -d "/" -f 4)
40+
BOOT_PART_NUM=$(cat "/sys/block/${BOOT_DEV_NAME}/${BOOT_PART_NAME}/partition")
41+
42+
OLD_DISKID=$(fdisk -l "$ROOT_DEV" | sed -n 's/Disk identifier: 0x\([^ ]*\)/\1/p')
43+
44+
check_noobs
45+
46+
ROOT_DEV_SIZE=$(cat "/sys/block/${ROOT_DEV_NAME}/size")
47+
TARGET_END=$((ROOT_DEV_SIZE - 1))
48+
49+
PARTITION_TABLE=$(parted -m "$ROOT_DEV" unit s print | tr -d 's')
50+
51+
LAST_PART_NUM=$(echo "$PARTITION_TABLE" | tail -n 1 | cut -d ":" -f 1)
52+
53+
ROOT_PART_LINE=$(echo "$PARTITION_TABLE" | grep -e "^${ROOT_PART_NUM}:")
54+
ROOT_PART_START=$(echo "$ROOT_PART_LINE" | cut -d ":" -f 2)
55+
ROOT_PART_END=$(echo "$ROOT_PART_LINE" | cut -d ":" -f 3)
56+
57+
if [ "$NOOBS" = "1" ]; then
58+
EXT_PART_LINE=$(echo "$PARTITION_TABLE" | grep ":::;" | head -n 1)
59+
EXT_PART_NUM=$(echo "$EXT_PART_LINE" | cut -d ":" -f 1)
60+
EXT_PART_START=$(echo "$EXT_PART_LINE" | cut -d ":" -f 2)
61+
EXT_PART_END=$(echo "$EXT_PART_LINE" | cut -d ":" -f 3)
62+
fi
63+
}
64+
65+
fix_partuuid() {
66+
mount -o remount,rw "$ROOT_PART_DEV"
67+
mount -o remount,rw "$BOOT_PART_DEV"
68+
MAJOR="$(uname -r | cut -f1 -d.)"
69+
if [[ "$MAJOR" -eq "6" ]] && [[ -c /dev/hwrng ]]; then
70+
dd if=/dev/hwrng of=/dev/urandom count=1 bs=256 status=none
71+
fi
72+
DISKID="$(tr -dc 'a-f0-9' < /dev/urandom | dd bs=1 count=8 2>/dev/null)"
73+
fdisk "$ROOT_DEV" > /dev/null <<EOF
74+
x
75+
i
76+
0x$DISKID
77+
r
78+
w
79+
EOF
80+
if [ "$?" -eq 0 ]; then
81+
sed -i "s/${OLD_DISKID}/${DISKID}/g" /etc/fstab
82+
sed -i "s/${OLD_DISKID}/${DISKID}/" /boot/cmdline.txt
83+
sync
84+
fi
85+
86+
mount -o remount,ro "$ROOT_PART_DEV"
87+
mount -o remount,ro "$BOOT_PART_DEV"
88+
}
89+
90+
fix_wpa() {
91+
if [ -e /boot/firstrun.sh ] \
92+
&& ! grep -q 'imager_custom set_wlan' /boot/firstrun.sh \
93+
&& grep -q wpa_supplicant.conf /boot/firstrun.sh; then
94+
mount -o remount,rw "$ROOT_PART_DEV"
95+
modprobe rfkill
96+
REGDOMAIN=$(sed -n 's/^\s*country=\(..\)$/\1/p' /boot/firstrun.sh)
97+
[ -n "$REGDOMAIN" ] && raspi-config nonint do_wifi_country "$REGDOMAIN"
98+
if systemctl -q is-enabled NetworkManager; then
99+
systemctl disable NetworkManager
100+
fi
101+
mount -o remount,ro "$ROOT_PART_DEV"
102+
fi
103+
}
104+
105+
check_variables () {
106+
if [ "$NOOBS" = "1" ]; then
107+
if [ "$EXT_PART_NUM" -gt 4 ] || \
108+
[ "$EXT_PART_START" -gt "$ROOT_PART_START" ] || \
109+
[ "$EXT_PART_END" -lt "$ROOT_PART_END" ]; then
110+
FAIL_REASON="Unsupported extended partition\n$FAIL_REASON"
111+
return 1
112+
fi
113+
fi
114+
115+
if [ "$ROOT_PART_NUM" -ne "$LAST_PART_NUM" ]; then
116+
# Skip resize if root partition is not last
117+
return 1
118+
fi
119+
120+
if [ "$ROOT_PART_END" -gt "$TARGET_END" ]; then
121+
FAIL_REASON="Root partition runs past the end of device\n$FAIL_REASON"
122+
return 1
123+
fi
124+
125+
if [ ! -b "$ROOT_DEV" ] || [ ! -b "$ROOT_PART_DEV" ] || [ ! -b "$BOOT_PART_DEV" ] ; then
126+
FAIL_REASON="Could not determine partitions\n$FAIL_REASON"
127+
return 1
128+
fi
129+
if [ "$ROOT_PART_END" -eq "$TARGET_END" ]; then
130+
# Root partition already the expected size
131+
return 1
132+
fi
133+
}
134+
135+
check_kernel () {
136+
MAJOR="$(uname -r | cut -f1 -d.)"
137+
MINOR="$(uname -r | cut -f2 -d.)"
138+
if [ "$MAJOR" -eq "4" ] && [ "$MINOR" -lt "9" ]; then
139+
return 0
140+
fi
141+
if [ "$MAJOR" -lt "4" ]; then
142+
return 0
143+
fi
144+
NEW_KERNEL=1
145+
}
146+
147+
do_resize () {
148+
check_kernel
149+
150+
if [ "$NOOBS" = "1" ] && [ "$NEW_KERNEL" != "1" ]; then
151+
BCM_MODULE=$(grep -e "^Hardware" /proc/cpuinfo | cut -d ":" -f 2 | tr -d " " | tr '[:upper:]' '[:lower:]')
152+
if ! modprobe "$BCM_MODULE"; then
153+
FAIL_REASON="Couldn't load BCM module $BCM_MODULE\n$FAIL_REASON"
154+
return 1
155+
fi
156+
fi
157+
158+
whiptail --infobox "Resizing root filesystem...\n\nDepending on storage size and speed, this may take a while." 20 60
159+
if [ "$NOOBS" = "1" ]; then
160+
if ! printf "resizepart %s\nyes\n%ss\n" "$EXT_PART_NUM" "$TARGET_END" | parted "$ROOT_DEV" ---pretend-input-tty; then
161+
FAIL_REASON="Extended partition resize failed\n$FAIL_REASON"
162+
return 1
163+
fi
164+
fi
165+
166+
if ! parted -m "$ROOT_DEV" u s resizepart "$ROOT_PART_NUM" "$TARGET_END"; then
167+
FAIL_REASON="Partition table resize of the root partition ($ROOT_PART_DEV) failed\n$FAIL_REASON"
168+
return 1
169+
fi
170+
171+
mount -o remount,rw /
172+
resize2fs "$ROOT_PART_DEV" > /dev/null 2>&1
173+
RET="$?"
174+
if [ "$RET" -ne 0 ]; then
175+
FAIL_REASON="Root partition resize failed\n$FAIL_REASON"
176+
fi
177+
178+
mount -o remount,ro /
179+
return "$RET"
180+
}
181+
182+
regenerate_ssh_host_keys () {
183+
mount -o remount,rw /
184+
/usr/lib/raspberrypi-sys-mods/regenerate_ssh_host_keys
185+
RET="$?"
186+
mount -o remount,ro /
187+
return "$RET"
188+
}
189+
190+
apply_custom () {
191+
CONFIG_FILE="$1"
192+
mount -o remount,rw /
193+
mount -o remount,rw /boot
194+
if ! python3 -c "import toml" 2> /dev/null; then
195+
FAIL_REASON="custom.toml provided, but python3-toml is not installed\n$FAIL_REASON"
196+
else
197+
set -o pipefail
198+
/usr/lib/raspberrypi-sys-mods/init_config "$CONFIG_FILE" |& tee /run/firstboot.log | while read -r line; do
199+
MSG="$MSG\n$line"
200+
whiptail --infobox "$MSG" 20 60
201+
done
202+
if [ "$?" -ne 0 ]; then
203+
mv /run/firstboot.log /var/log/firstboot.log
204+
FAIL_REASON="Failed to apply customisations from custom.toml\n\nLog file saved as /var/log/firstboot.log\n$FAIL_REASON"
205+
fi
206+
set +o pipefail
207+
fi
208+
rm -f "$CONFIG_FILE"
209+
mount -o remount,ro /boot
210+
mount -o remount,ro /
211+
}
212+
213+
main () {
214+
get_variables
215+
216+
if check_variables; then
217+
do_resize
218+
fi
219+
220+
# Switch to dhcpcd here if Imager < v1.7.3 was used to generate firstrun.sh
221+
fix_wpa > /dev/null 2>&1
222+
223+
whiptail --infobox "Generating SSH keys..." 20 60
224+
regenerate_ssh_host_keys
225+
226+
if [ -f "/boot/custom.toml" ]; then
227+
MSG="Applying customisations from custom.toml...\n"
228+
whiptail --infobox "$MSG" 20 60
229+
apply_custom "/boot/custom.toml"
230+
fi
231+
232+
whiptail --infobox "Fix PARTUUID..." 20 60
233+
fix_partuuid
234+
235+
return 0
236+
}
237+
238+
mount -t proc proc /proc
239+
mount -t sysfs sys /sys
240+
mount -t tmpfs tmp /run
241+
mkdir -p /run/systemd
242+
243+
mount /boot
244+
mount / -o remount,ro
245+
246+
sed -i 's| init=/usr/lib/raspberrypi-sys-mods/firstboot||' /boot/cmdline.txt
247+
sed -i 's| sdhci\.debug_quirks2=4||' /boot/cmdline.txt
248+
249+
if ! grep -q splash /boot/cmdline.txt; then
250+
sed -i "s/ quiet//g" /boot/cmdline.txt
251+
fi
252+
mount /boot -o remount,ro
253+
sync
254+
255+
main
256+
257+
if [ -z "$FAIL_REASON" ]; then
258+
whiptail --infobox "Rebooting in 5 seconds..." 20 60
259+
sleep 5
260+
else
261+
whiptail --msgbox "Failed running firstboot:\n${FAIL_REASON}" 20 60
262+
fi
263+
264+
reboot_pi
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#!/usr/bin/env bash
2+
#### rpi_firstb_fix module
3+
####
4+
#### Written by Stephan Wendel aka KwadFan <[email protected]>
5+
#### Copyright 2023 - till today
6+
#### https://github.com/mainsail-crew/MainsailOS
7+
####
8+
#### This File is distributed under GPLv3
9+
####
10+
11+
#### Description:
12+
#### This is intended to patch behaviour of raspberry's firstboot script.
13+
#### Related to https://github.com/mainsail-crew/MainsailOS/issues/213
14+
15+
# shellcheck enable=require-variable-braces
16+
## Source error handling, leave this in place
17+
set -Ee
18+
19+
# Set DEBIAN_FRONTEND to noninteractive
20+
if [[ "${DEBIAN_FRONTEND}" != "noninteractive" ]]; then
21+
export DEBIAN_FRONTEND=noninteractive
22+
fi
23+
24+
## Source CustomPIOS common.sh
25+
# shellcheck disable=SC1091
26+
source /common.sh
27+
install_cleanup_trap
28+
29+
## Step 1: Patch firstboot issue
30+
echo_green "Patch firstboot issue..."
31+
unpack filesystem/root /
32+
## END Step 1

src/version

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1.1.0
1+
1.1.1-RC1

0 commit comments

Comments
 (0)