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

fix: fix firstboot issue #214

Merged
merged 3 commits into from
Mar 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion config/raspberry/default
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ BASE_IMAGE_RESIZEROOT=600
# Compress not needed due compression done in workflow
BASE_RELEASE_COMPRESS=no
# Modules are valid for 32bit and 64bit images
MODULES="base,pkgupgrade,mainsailos(net,piconfig,klipper,is_req_preinstall,moonraker,timelapse,mainsail,crowsnest,sonar,password-for-sudo),postrename"
MODULES="base,pkgupgrade,rpi_firstb_fix,mainsailos(net,piconfig,klipper,is_req_preinstall,moonraker,timelapse,mainsail,crowsnest,sonar,password-for-sudo),postrename"

# export Variables
export BASE_IMAGE_ENLARGEROOT
Expand Down
8 changes: 5 additions & 3 deletions src/modules/mainsailos/start_chroot_script
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ fi
source /common.sh
install_cleanup_trap

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

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

### Install CANBoot Dependency
apt update
## Step 2: Install CANBoot Dependency
apt-get update --allow-releaseinfo-change
# shellcheck disable=SC2086
check_install_pkgs ${MAINSAILOS_DEPS}
## END Step 2
13 changes: 13 additions & 0 deletions src/modules/rpi_firstb_fix/config
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/usr/bin/env bash
# Shebang for better file detection
#### rpi_firstb_fix module
####
#### Written by Stephan Wendel aka KwadFan <me@stephanwe.de>
#### Copyright 2023 - till today
#### https://github.com/mainsail-crew/MainsailOS
####
#### This File is distributed under GPLv3
####

# Intentionally left blank
# See start_chroot_script for information
Original file line number Diff line number Diff line change
@@ -0,0 +1,264 @@
#!/bin/bash
# shellcheck disable=all


reboot_pi () {
umount /boot
mount / -o remount,ro
sync
if [ "$NOOBS" = "1" ]; then
if [ "$NEW_KERNEL" = "1" ]; then
reboot -f "$BOOT_PART_NUM"
sleep 5
else
echo "$BOOT_PART_NUM" > "/sys/module/${BCM_MODULE}/parameters/reboot_part"
fi
fi
reboot -f
sleep 5
exit 0
}

check_noobs () {
if [ "$BOOT_PART_NUM" = "1" ]; then
NOOBS=0
else
NOOBS=1
fi
}

get_variables () {
ROOT_PART_DEV=$(findmnt / -o source -n)
ROOT_PART_NAME=$(echo "$ROOT_PART_DEV" | cut -d "/" -f 3)
ROOT_DEV_NAME=$(echo /sys/block/*/"${ROOT_PART_NAME}" | cut -d "/" -f 4)
ROOT_DEV="/dev/${ROOT_DEV_NAME}"
ROOT_PART_NUM=$(cat "/sys/block/${ROOT_DEV_NAME}/${ROOT_PART_NAME}/partition")

BOOT_PART_DEV=$(findmnt /boot -o source -n)
BOOT_PART_NAME=$(echo "$BOOT_PART_DEV" | cut -d "/" -f 3)
BOOT_DEV_NAME=$(echo /sys/block/*/"${BOOT_PART_NAME}" | cut -d "/" -f 4)
BOOT_PART_NUM=$(cat "/sys/block/${BOOT_DEV_NAME}/${BOOT_PART_NAME}/partition")

OLD_DISKID=$(fdisk -l "$ROOT_DEV" | sed -n 's/Disk identifier: 0x\([^ ]*\)/\1/p')

check_noobs

ROOT_DEV_SIZE=$(cat "/sys/block/${ROOT_DEV_NAME}/size")
TARGET_END=$((ROOT_DEV_SIZE - 1))

PARTITION_TABLE=$(parted -m "$ROOT_DEV" unit s print | tr -d 's')

LAST_PART_NUM=$(echo "$PARTITION_TABLE" | tail -n 1 | cut -d ":" -f 1)

ROOT_PART_LINE=$(echo "$PARTITION_TABLE" | grep -e "^${ROOT_PART_NUM}:")
ROOT_PART_START=$(echo "$ROOT_PART_LINE" | cut -d ":" -f 2)
ROOT_PART_END=$(echo "$ROOT_PART_LINE" | cut -d ":" -f 3)

if [ "$NOOBS" = "1" ]; then
EXT_PART_LINE=$(echo "$PARTITION_TABLE" | grep ":::;" | head -n 1)
EXT_PART_NUM=$(echo "$EXT_PART_LINE" | cut -d ":" -f 1)
EXT_PART_START=$(echo "$EXT_PART_LINE" | cut -d ":" -f 2)
EXT_PART_END=$(echo "$EXT_PART_LINE" | cut -d ":" -f 3)
fi
}

fix_partuuid() {
mount -o remount,rw "$ROOT_PART_DEV"
mount -o remount,rw "$BOOT_PART_DEV"
MAJOR="$(uname -r | cut -f1 -d.)"
if [[ "$MAJOR" -eq "6" ]] && [[ -c /dev/hwrng ]]; then
dd if=/dev/hwrng of=/dev/urandom count=1 bs=256 status=none
fi
DISKID="$(tr -dc 'a-f0-9' < /dev/urandom | dd bs=1 count=8 2>/dev/null)"
fdisk "$ROOT_DEV" > /dev/null <<EOF
x
i
0x$DISKID
r
w
EOF
if [ "$?" -eq 0 ]; then
sed -i "s/${OLD_DISKID}/${DISKID}/g" /etc/fstab
sed -i "s/${OLD_DISKID}/${DISKID}/" /boot/cmdline.txt
sync
fi

mount -o remount,ro "$ROOT_PART_DEV"
mount -o remount,ro "$BOOT_PART_DEV"
}

fix_wpa() {
if [ -e /boot/firstrun.sh ] \
&& ! grep -q 'imager_custom set_wlan' /boot/firstrun.sh \
&& grep -q wpa_supplicant.conf /boot/firstrun.sh; then
mount -o remount,rw "$ROOT_PART_DEV"
modprobe rfkill
REGDOMAIN=$(sed -n 's/^\s*country=\(..\)$/\1/p' /boot/firstrun.sh)
[ -n "$REGDOMAIN" ] && raspi-config nonint do_wifi_country "$REGDOMAIN"
if systemctl -q is-enabled NetworkManager; then
systemctl disable NetworkManager
fi
mount -o remount,ro "$ROOT_PART_DEV"
fi
}

check_variables () {
if [ "$NOOBS" = "1" ]; then
if [ "$EXT_PART_NUM" -gt 4 ] || \
[ "$EXT_PART_START" -gt "$ROOT_PART_START" ] || \
[ "$EXT_PART_END" -lt "$ROOT_PART_END" ]; then
FAIL_REASON="Unsupported extended partition\n$FAIL_REASON"
return 1
fi
fi

if [ "$ROOT_PART_NUM" -ne "$LAST_PART_NUM" ]; then
# Skip resize if root partition is not last
return 1
fi

if [ "$ROOT_PART_END" -gt "$TARGET_END" ]; then
FAIL_REASON="Root partition runs past the end of device\n$FAIL_REASON"
return 1
fi

if [ ! -b "$ROOT_DEV" ] || [ ! -b "$ROOT_PART_DEV" ] || [ ! -b "$BOOT_PART_DEV" ] ; then
FAIL_REASON="Could not determine partitions\n$FAIL_REASON"
return 1
fi
if [ "$ROOT_PART_END" -eq "$TARGET_END" ]; then
# Root partition already the expected size
return 1
fi
}

check_kernel () {
MAJOR="$(uname -r | cut -f1 -d.)"
MINOR="$(uname -r | cut -f2 -d.)"
if [ "$MAJOR" -eq "4" ] && [ "$MINOR" -lt "9" ]; then
return 0
fi
if [ "$MAJOR" -lt "4" ]; then
return 0
fi
NEW_KERNEL=1
}

do_resize () {
check_kernel

if [ "$NOOBS" = "1" ] && [ "$NEW_KERNEL" != "1" ]; then
BCM_MODULE=$(grep -e "^Hardware" /proc/cpuinfo | cut -d ":" -f 2 | tr -d " " | tr '[:upper:]' '[:lower:]')
if ! modprobe "$BCM_MODULE"; then
FAIL_REASON="Couldn't load BCM module $BCM_MODULE\n$FAIL_REASON"
return 1
fi
fi

whiptail --infobox "Resizing root filesystem...\n\nDepending on storage size and speed, this may take a while." 20 60
if [ "$NOOBS" = "1" ]; then
if ! printf "resizepart %s\nyes\n%ss\n" "$EXT_PART_NUM" "$TARGET_END" | parted "$ROOT_DEV" ---pretend-input-tty; then
FAIL_REASON="Extended partition resize failed\n$FAIL_REASON"
return 1
fi
fi

if ! parted -m "$ROOT_DEV" u s resizepart "$ROOT_PART_NUM" "$TARGET_END"; then
FAIL_REASON="Partition table resize of the root partition ($ROOT_PART_DEV) failed\n$FAIL_REASON"
return 1
fi

mount -o remount,rw /
resize2fs "$ROOT_PART_DEV" > /dev/null 2>&1
RET="$?"
if [ "$RET" -ne 0 ]; then
FAIL_REASON="Root partition resize failed\n$FAIL_REASON"
fi

mount -o remount,ro /
return "$RET"
}

regenerate_ssh_host_keys () {
mount -o remount,rw /
/usr/lib/raspberrypi-sys-mods/regenerate_ssh_host_keys
RET="$?"
mount -o remount,ro /
return "$RET"
}

apply_custom () {
CONFIG_FILE="$1"
mount -o remount,rw /
mount -o remount,rw /boot
if ! python3 -c "import toml" 2> /dev/null; then
FAIL_REASON="custom.toml provided, but python3-toml is not installed\n$FAIL_REASON"
else
set -o pipefail
/usr/lib/raspberrypi-sys-mods/init_config "$CONFIG_FILE" |& tee /run/firstboot.log | while read -r line; do
MSG="$MSG\n$line"
whiptail --infobox "$MSG" 20 60
done
if [ "$?" -ne 0 ]; then
mv /run/firstboot.log /var/log/firstboot.log
FAIL_REASON="Failed to apply customisations from custom.toml\n\nLog file saved as /var/log/firstboot.log\n$FAIL_REASON"
fi
set +o pipefail
fi
rm -f "$CONFIG_FILE"
mount -o remount,ro /boot
mount -o remount,ro /
}

main () {
get_variables

if check_variables; then
do_resize
fi

# Switch to dhcpcd here if Imager < v1.7.3 was used to generate firstrun.sh
fix_wpa > /dev/null 2>&1

whiptail --infobox "Generating SSH keys..." 20 60
regenerate_ssh_host_keys

if [ -f "/boot/custom.toml" ]; then
MSG="Applying customisations from custom.toml...\n"
whiptail --infobox "$MSG" 20 60
apply_custom "/boot/custom.toml"
fi

whiptail --infobox "Fix PARTUUID..." 20 60
fix_partuuid

return 0
}

mount -t proc proc /proc
mount -t sysfs sys /sys
mount -t tmpfs tmp /run
mkdir -p /run/systemd

mount /boot
mount / -o remount,ro

sed -i 's| init=/usr/lib/raspberrypi-sys-mods/firstboot||' /boot/cmdline.txt
sed -i 's| sdhci\.debug_quirks2=4||' /boot/cmdline.txt

if ! grep -q splash /boot/cmdline.txt; then
sed -i "s/ quiet//g" /boot/cmdline.txt
fi
mount /boot -o remount,ro
sync

main

if [ -z "$FAIL_REASON" ]; then
whiptail --infobox "Rebooting in 5 seconds..." 20 60
sleep 5
else
whiptail --msgbox "Failed running firstboot:\n${FAIL_REASON}" 20 60
fi

reboot_pi
32 changes: 32 additions & 0 deletions src/modules/rpi_firstb_fix/start_chroot_script
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#!/usr/bin/env bash
#### rpi_firstb_fix module
####
#### Written by Stephan Wendel aka KwadFan <me@stephanwe.de>
#### Copyright 2023 - till today
#### https://github.com/mainsail-crew/MainsailOS
####
#### This File is distributed under GPLv3
####

#### Description:
#### This is intended to patch behaviour of raspberry's firstboot script.
#### Related to https://github.com/mainsail-crew/MainsailOS/issues/213

# shellcheck enable=require-variable-braces
## Source error handling, leave this in place
set -Ee

# Set DEBIAN_FRONTEND to noninteractive
if [[ "${DEBIAN_FRONTEND}" != "noninteractive" ]]; then
export DEBIAN_FRONTEND=noninteractive
fi

## Source CustomPIOS common.sh
# shellcheck disable=SC1091
source /common.sh
install_cleanup_trap

## Step 1: Patch firstboot issue
echo_green "Patch firstboot issue..."
unpack filesystem/root /
## END Step 1
2 changes: 1 addition & 1 deletion src/version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.1.0
1.1.1-RC1