Skip to content

Commit 9531348

Browse files
committed
Fix some issues with the auto-flash on the PB2i not working due to modules not being loaded in time
1 parent 6e2dd94 commit 9531348

2 files changed

Lines changed: 87 additions & 9 deletions

File tree

SD/BB64-AutoFlash.sh

Lines changed: 55 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
#script that can be added to kernel init= to have the BB64/PB2 Industrial
44
#flash the eMMC when powered on. It will partition the device, possibly
55
#reboot to get the new patition table, then install FPP onto the eMMC
6-
#and then power attempt to power down. The power down usually will
7-
#fail, but the indicator lights will stop flashing/cycling to
8-
#indicate it's done
6+
#and then power down. The indicator lights also stop flashing/cycling to
7+
#indicate it's done, which is the signal to trust if the board is still powered
8+
#for any reason.
99

1010
mount -o remount,rw /dev/mmcblk1p3 / || true
1111
mkdir -p /proc
@@ -17,6 +17,16 @@ mount -t sysfs sysfs /sys
1717
PATH=$PATH:/bin:/sbin:/usr/bin:/usr/sbin
1818
DEVICE=/dev/mmcblk0
1919

20+
# This runs as init, so udev is never started -- and udev is what loads the driver
21+
# module for an i2c client, off the MODALIAS in its uevent. The kernel creates the
22+
# clients from the device tree either way, so without this the identity EEPROM and
23+
# the ADC beside it sit on the bus with no driver bound and no /sys attributes:
24+
# indistinguishable, from sysfs alone, from an MSPM0 that was never programmed.
25+
# Both are modules in the FPP kernel (CONFIG_EEPROM_AT24=m, CONFIG_AD7291=m).
26+
for mod in at24 ad7291; do
27+
modprobe ${mod} 2>/dev/null || true
28+
done
29+
2030
mount -t vfat /dev/mmcblk1p1 /boot/firmware
2131
mount -t tmpfs /tmp
2232

@@ -40,7 +50,16 @@ fail() {
4050
echo 120 > "$led/delay_on" 2>/dev/null
4151
echo 120 > "$led/delay_off" 2>/dev/null
4252
done
43-
exit 1
53+
# This script IS init, so exiting is a kernel panic ("Attempted to kill init"),
54+
# and with no panic= on the command line the board just wedges -- no reboot, and
55+
# nothing left to ask questions of. Hand the serial console a shell instead: the
56+
# LEDs keep blinking from the kernel's timer trigger either way, so the board
57+
# still reads as failed to anyone who only has the lights.
58+
echo ""
59+
echo "Dropping to a shell on the console. The board stays unflashed."
60+
exec /bin/sh -i < /dev/console > /dev/console 2>&1
61+
# If /dev/console is not usable, hang rather than panic.
62+
while true; do sleep 3600; done
4463
}
4564

4665
echo "---------------------------------------"
@@ -79,17 +98,44 @@ rm -f /mnt/fpp_expand_rootfs
7998
umount /mnt
8099

81100
# Done. A sweep means working and a synchronised blink means failed, so darkness is
82-
# the only remaining state -- and unlike "powered off" it survives the shutdown below
83-
# failing, which in this environment it usually does.
101+
# the only remaining state -- and it is what remains readable if the power off below
102+
# does not take, since a board that never powered down still has to look finished.
84103
for led in /sys/class/leds/*usr[0-9]; do
85104
[ -e "$led/trigger" ] || continue
86105
echo none > "$led/trigger" 2>/dev/null
87106
echo 0 > "$led/brightness" 2>/dev/null
88107
done
89108

109+
# Shut down. Note what is NOT available here: /sbin/{shutdown,halt,poweroff,reboot}
110+
# are all symlinks to systemctl, and this script is PID 1, so there is no systemd for
111+
# any of them to talk to. sysrq is the only route out.
90112
echo 1 > /proc/sys/kernel/sysrq
91-
echo s > /proc/sysrq-trigger
92-
echo u > /proc/sysrq-trigger
93-
echo o > /proc/sysrq-trigger
113+
114+
# sysrq 'o' hands off to orderly_poweroff(), which first runs poweroff_cmd as a
115+
# usermode helper -- /sbin/poweroff, i.e. systemctl again -- and only forces a real
116+
# kernel_power_off() once that fails. Point it at something that cannot exist so it
117+
# fails immediately instead of grinding through that.
118+
echo /nonexistent-force-kernel-poweroff > /proc/sys/kernel/poweroff_cmd 2>/dev/null || true
119+
120+
echo s > /proc/sysrq-trigger # sync
121+
echo u > /proc/sysrq-trigger # remount everything read-only
122+
echo o > /proc/sysrq-trigger # power off
123+
124+
# 'o' is asynchronous -- it queues work and the write returns straight away -- so the
125+
# power off is still being set up when this line is reached. Waiting here is not
126+
# politeness: this script IS init, so running off the end is "Attempted to kill
127+
# init", a kernel panic that beats the shutdown to the finish and lands on a board
128+
# that flashed perfectly.
129+
#
130+
# The power off itself is real on this hardware. The TPS65219 PMIC at i2c 0x30 is
131+
# marked system-power-controller in the device tree, so the tps65219 driver registers
132+
# a SYS_OFF_MODE_POWER_OFF handler and the kernel can actually cut the rails -- there
133+
# is no psci node, but none is needed, the PMIC is the handler. So this loop should
134+
# never get more than a few seconds in. It is the backstop for the case where the
135+
# handler does not fire, where a parked init with everything synced and read-only,
136+
# and the LEDs dark, is still a correct and readable end state.
137+
while true; do
138+
sleep 3600
139+
done
94140

95141

capes/drivers/bb64/check_pb2_eeprom.sh

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@
3939
# not ACK there even on a healthy board, so its silence proves nothing. Whether the
4040
# emulated devices bound is the only signal that means anything.
4141
#
42+
# But "did not bind" only means something once the driver exists to bind. at24 and
43+
# ad7291 are modules, loaded by udev off each client's MODALIAS -- and the boot-time
44+
# flasher runs as init with no udev, where an entirely healthy board presents the
45+
# unprogrammed-MSPM0 signature exactly. Hence the modprobe below, and the separate
46+
# verdict for "the driver is not there" ahead of any verdict about the board.
47+
#
4248
# Usage: check_pb2_eeprom.sh [--quiet]
4349
#
4450
# Exit codes:
@@ -85,6 +91,18 @@ case "${MODEL}" in
8591
;;
8692
esac
8793

94+
# udev is what loads the driver module for an i2c client, off the MODALIAS in its
95+
# uevent. The boot-time flasher runs this script from init= with no udev at all,
96+
# and at24/ad7291 are both modules -- so on that path the clients exist with no
97+
# driver bound, which from sysfs is indistinguishable from an MSPM0 that never came
98+
# up. Load them here so the verdict below is about the board and not about the
99+
# environment the script was called from. A no-op when they are already loaded,
100+
# built in, or when running against fixtures.
101+
if [ -z "${PB2_EEPROM}${PB2_I2CDEV}${PB2_ADCDEV}" ] && command -v modprobe >/dev/null 2>&1; then
102+
modprobe at24 2>/dev/null || true
103+
modprobe ad7291 2>/dev/null || true
104+
fi
105+
88106
# The EEPROM has to be present before anything else can be decided.
89107
i=0
90108
while [ ! -f "${EEPROM}" ] && [ "${i}" -lt "${EEPROM_WAIT}" ]; do
@@ -94,6 +112,20 @@ done
94112
if [ ! -f "${EEPROM}" ]; then
95113
# Both of these end the flash, but they point at different repairs, and the
96114
# message is the only thing whoever picks the board up gets to work from.
115+
#
116+
# Before any of them: if the at24 driver is not even registered, nothing could
117+
# have bound to 0x50 whatever the hardware did, and every verdict below would be
118+
# an accusation against a board that was never asked. That is a broken image or
119+
# a missing module, not a broken board.
120+
if [ -z "${PB2_EEPROM}${PB2_I2CDEV}${PB2_ADCDEV}" ] && [ ! -d /sys/bus/i2c/drivers/at24 ]; then
121+
fatal "the at24 driver is not loaded, so nothing can bind to the EEPROM at 0x50.
122+
123+
This says nothing about the board -- the driver that would read it is missing.
124+
It is a module in the FPP kernel and is normally loaded by udev; check that
125+
/lib/modules/$(uname -r) matches the running kernel.
126+
127+
Re-run this once at24 is loaded before judging the hardware."
128+
fi
97129
if [ -d "${I2CDEV}" ]; then
98130
# The client exists but at24 did not bind, so 0x50 did not ACK its probe
99131
# read. On a PocketBeagle2 that EEPROM is emulated by the on-board

0 commit comments

Comments
 (0)