recoveryboot: chain-load into the recovery partition on BCB request
The RPi firmware can't read the BCB in misc, so 'adb reboot recovery' / factory reset never reached recovery: init writes boot-recovery and reboots, the firmware ignores the reboot arg, and Android just boots normally again. pawlet-recoveryboot is a vendor oneshot (post-fs-data) that reads the BCB command field (misc offset 0 — the HAL's PawletBootControl lives at 4096, no overlap) and, on boot-recovery, reboots with arg '3': the firmware's PM_RSTS partition mechanism (same driver path as the updater's tryboot) boots GPT partition 3 = recovery once. Stock recovery reads its args from the untouched BCB, clears it when done, and the next reboot is normal. A /metadata attempt counter clears the BCB after 2 failed tries so an unbootable recovery can't wedge the device.
This commit is contained in:
@@ -37,3 +37,11 @@ PRODUCT_PACKAGES += \
|
||||
PawletUpdaterRpiOverlay \
|
||||
PawletSettings \
|
||||
SettingsProviderRpiCommonOverlay
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# reboot-to-recovery chain-loader — RPi firmware can't read the BCB in misc,
|
||||
# so a boot-time oneshot detects "boot-recovery" and reboots into the
|
||||
# recovery partition (3) via the firmware's PM_RSTS partition mechanism.
|
||||
# ---------------------------------------------------------------------------
|
||||
PRODUCT_PACKAGES += \
|
||||
pawlet-recoveryboot
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
// Copyright (C) 2026 oxmc / PawletOS
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
sh_binary {
|
||||
name: "pawlet-recoveryboot",
|
||||
src: "pawlet-recoveryboot.sh",
|
||||
vendor: true,
|
||||
init_rc: ["pawlet-recoveryboot.rc"],
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
# Chain-load into the recovery partition when the BCB asks for it — see
|
||||
# pawlet-recoveryboot.sh. post-fs-data: by-name symlinks and /metadata are
|
||||
# guaranteed mounted, and we still reboot before the launcher appears.
|
||||
service pawlet_recoveryboot /vendor/bin/pawlet-recoveryboot.sh
|
||||
user root
|
||||
group root system
|
||||
oneshot
|
||||
disabled
|
||||
|
||||
on post-fs-data
|
||||
exec_start pawlet_recoveryboot
|
||||
@@ -0,0 +1,53 @@
|
||||
#!/vendor/bin/sh
|
||||
#
|
||||
# Copyright (C) 2026 oxmc / PawletOS
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# Boot-time bootloader-message (BCB) watcher — the RPi firmware cannot read
|
||||
# the misc partition, so "reboot recovery" needs an Android-side chain-load:
|
||||
#
|
||||
# adb reboot recovery / Settings factory reset
|
||||
# -> framework+init write "boot-recovery" into the BCB command field
|
||||
# (misc offset 0, 32 bytes) and reboot; the firmware ignores the
|
||||
# "recovery" reboot arg and boots normal Android
|
||||
# -> THIS script (oneshot, early in boot) sees the BCB and reboots with
|
||||
# arg "3": the firmware's PM_RSTS partition mechanism (same driver
|
||||
# path as the updater's "tryboot") boots GPT partition 3 = recovery
|
||||
# -> stock recovery reads its args from the BCB, does its work, clears
|
||||
# the BCB, reboots -> normal boot
|
||||
#
|
||||
# The BCB is left intact for recovery (it carries e.g. --wipe_data). A
|
||||
# bootloop breaker in /metadata clears the BCB after repeated failed
|
||||
# attempts so an unbootable recovery partition can't wedge the device.
|
||||
|
||||
MISC=/dev/block/by-name/misc
|
||||
GUARD_DIR=/metadata/pawlet
|
||||
GUARD=$GUARD_DIR/recoveryboot.attempts
|
||||
TAG=pawlet-recoveryboot
|
||||
|
||||
CMD=$(dd if=$MISC bs=1 count=32 2>/dev/null | tr -d '\0')
|
||||
|
||||
case "$CMD" in
|
||||
boot-recovery*)
|
||||
mkdir -p $GUARD_DIR
|
||||
N=$(cat $GUARD 2>/dev/null)
|
||||
[ -z "$N" ] && N=0
|
||||
if [ "$N" -ge 2 ]; then
|
||||
# Recovery partition isn't coming up — break the loop: clear the BCB
|
||||
# command field and stay in Android.
|
||||
dd if=/dev/zero of=$MISC bs=1 count=32 conv=notrunc 2>/dev/null
|
||||
rm -f $GUARD
|
||||
log -p e -t $TAG "recovery boot failed $N times; BCB cleared, staying in Android"
|
||||
exit 0
|
||||
fi
|
||||
echo $((N + 1)) > $GUARD
|
||||
log -p i -t $TAG "BCB requests recovery — rebooting to partition 3 (attempt $((N + 1)))"
|
||||
setprop sys.powerctl reboot,3
|
||||
;;
|
||||
*)
|
||||
# Normal boot: reset the attempt counter.
|
||||
rm -f $GUARD 2>/dev/null
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
Reference in New Issue
Block a user