install.sh: one-command modem-preserving installer
erase dtbo + flash userdata + RAM-boot + dd boot_a from Linux + verify modem NV and report honestly. Shipped in dist/ with every release; README points at it. The one believed-safe-but-unisolated step (userdata flash) is self-verified by the script's final check. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
0763481e9b
commit
ccf23abf81
3 changed files with 110 additions and 12 deletions
21
README.md
21
README.md
|
|
@ -29,22 +29,19 @@ carriers are very welcome.
|
||||||
Download `boot.img` and `fairphone-fp6.img` from the latest release and unlock
|
Download `boot.img` and `fairphone-fp6.img` from the latest release and unlock
|
||||||
the bootloader ([Fairphone's official process](https://support.fairphone.com/hc/en-us/articles/10492476238737)).
|
the bootloader ([Fairphone's official process](https://support.fairphone.com/hc/en-us/articles/10492476238737)).
|
||||||
|
|
||||||
**Recommended — modem-preserving install** (`fastboot boot` streams the
|
**Recommended — modem-preserving install**: with the phone in fastboot mode,
|
||||||
kernel to RAM without writing; all writes then happen from Linux, which the
|
run [`install.sh`](install.sh) (also attached to every release) from the
|
||||||
bootloader's boot-flash NV-wipe never sees — see the warning below):
|
directory holding the two images:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
fastboot boot boot.img
|
sh install.sh
|
||||||
# wait ~60s; the phone comes up on the USB network as 172.16.42.1
|
|
||||||
# (fresh devices land in the initramfs debug shell; telnet 172.16.42.1)
|
|
||||||
# then write both images through Linux, e.g. over the USB network:
|
|
||||||
ssh user@172.16.42.1 # or the debug shell on virgin devices
|
|
||||||
# on the phone: fetch/receive the images and
|
|
||||||
# dd of=/dev/disk/by-partlabel/boot_a for boot.img
|
|
||||||
# dd of=/dev/disk/by-partlabel/userdata for fairphone-fp6.img
|
|
||||||
fastboot erase dtbo # one-time, on the next fastboot visit (safe: verified)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
It erases dtbo, flashes the rootfs, **RAM-boots** the kernel (`fastboot
|
||||||
|
boot` — verified to write nothing), writes the boot partition from inside
|
||||||
|
Linux where the bootloader's NV-wipe cannot see it, then reads the modem NV
|
||||||
|
back and reports the result. The bootloader never writes `boot`.
|
||||||
|
|
||||||
**Classic install** (simpler, but `fastboot flash boot` **zeroes the modem's
|
**Classic install** (simpler, but `fastboot flash boot` **zeroes the modem's
|
||||||
NV** — cellular will be dead until you restore your `modemst` backup):
|
NV** — cellular will be dead until you restore your `modemst` backup):
|
||||||
|
|
||||||
|
|
|
||||||
1
build.sh
1
build.sh
|
|
@ -185,6 +185,7 @@ cp -L "$EXPORT/fairphone-fp6.img" dist/fairphone-fp6.img
|
||||||
echo "imsd: $IMSD_REPO @ $IMSD_COMMIT (0.3.0)"
|
echo "imsd: $IMSD_REPO @ $IMSD_COMMIT (0.3.0)"
|
||||||
} > dist/build-info.txt
|
} > dist/build-info.txt
|
||||||
cp README.md dist/README.md
|
cp README.md dist/README.md
|
||||||
|
cp install.sh dist/install.sh
|
||||||
|
|
||||||
(cd dist && sha256sum -- * > sha256sums.txt)
|
(cd dist && sha256sum -- * > sha256sums.txt)
|
||||||
ls -la dist/
|
ls -la dist/
|
||||||
|
|
|
||||||
100
install.sh
Executable file
100
install.sh
Executable file
|
|
@ -0,0 +1,100 @@
|
||||||
|
#!/bin/sh -eu
|
||||||
|
# fp6-img modem-preserving installer for the Fairphone 6.
|
||||||
|
#
|
||||||
|
# Why this exists: this device's bootloader ZEROES the modem's NV storage
|
||||||
|
# (modemst1/modemst2) whenever the boot partition is written over fastboot —
|
||||||
|
# after a classic `fastboot flash boot`, cellular (incl. eSIM access) is dead
|
||||||
|
# until restored. Isolated by experiment, 2026-08-09 (fp6 journal/modem).
|
||||||
|
#
|
||||||
|
# This installer never lets the bootloader write boot:
|
||||||
|
# 1. fastboot erase dtbo (verified safe)
|
||||||
|
# 2. fastboot flash userdata (rootfs; not a boot write - believed safe,
|
||||||
|
# final isolation pending; step 5 verifies)
|
||||||
|
# 3. fastboot boot boot.img (RAM boot - writes nothing; verified safe)
|
||||||
|
# 4. dd boot.img to boot_a from the booted Linux over USB networking
|
||||||
|
# (kernel block layer - the bootloader never sees it)
|
||||||
|
# 5. read back the modem NV and tell you the truth either way
|
||||||
|
#
|
||||||
|
# Requirements on this machine: fastboot, ssh. Phone: bootloader unlocked,
|
||||||
|
# in fastboot mode (Vol-down + Power), connected over USB.
|
||||||
|
# Run from a directory containing boot.img and fairphone-fp6.img.
|
||||||
|
|
||||||
|
PHONE=172.16.42.1
|
||||||
|
BOOT=${BOOT:-boot.img}
|
||||||
|
ROOTFS=${ROOTFS:-fairphone-fp6.img}
|
||||||
|
|
||||||
|
say() { printf '\n== %s ==\n' "$*"; }
|
||||||
|
die() { printf 'ERROR: %s\n' "$*" >&2; exit 1; }
|
||||||
|
|
||||||
|
# --- preflight ---------------------------------------------------------------
|
||||||
|
command -v fastboot >/dev/null || die "fastboot not found (install android-tools)"
|
||||||
|
command -v ssh >/dev/null || die "ssh not found"
|
||||||
|
[ -f "$BOOT" ] || die "$BOOT not found (download it from the release)"
|
||||||
|
[ -f "$ROOTFS" ] || die "$ROOTFS not found (download it from the release)"
|
||||||
|
fastboot devices 2>/dev/null | grep -q fastboot || \
|
||||||
|
die "no device in fastboot mode (Vol-down + Power, USB connected)"
|
||||||
|
|
||||||
|
cat <<'EOF'
|
||||||
|
This will REPLACE the operating system on the connected Fairphone 6
|
||||||
|
(userdata + boot). The modem's NV storage is preserved - that is the point
|
||||||
|
of this installer. Press Enter to continue, Ctrl-C to abort.
|
||||||
|
EOF
|
||||||
|
read -r _
|
||||||
|
|
||||||
|
# --- 1+2: safe fastboot writes -------------------------------------------------
|
||||||
|
say "erasing dtbo (one-time; safe - does not touch modem NV)"
|
||||||
|
fastboot erase dtbo
|
||||||
|
|
||||||
|
say "flashing rootfs to userdata (this is the big one, be patient)"
|
||||||
|
fastboot flash userdata "$ROOTFS"
|
||||||
|
|
||||||
|
# --- 3: RAM-boot the kernel, no write -----------------------------------------
|
||||||
|
say "RAM-booting the new system (nothing is written)"
|
||||||
|
fastboot boot "$BOOT"
|
||||||
|
|
||||||
|
say "waiting for the phone to come up on the USB network ($PHONE)"
|
||||||
|
i=0
|
||||||
|
until (exec 3<>"/dev/tcp/$PHONE/22") 2>/dev/null; do
|
||||||
|
i=$((i+1)); [ $i -gt 40 ] && die "phone did not appear on $PHONE after 400s"
|
||||||
|
sleep 10
|
||||||
|
done
|
||||||
|
exec 3<&- 3>&- 2>/dev/null || true
|
||||||
|
sleep 8
|
||||||
|
|
||||||
|
# --- 4: write boot from Linux ---------------------------------------------------
|
||||||
|
say "writing boot.img to boot_a from inside Linux (password: 147147)"
|
||||||
|
cat <<'EOF'
|
||||||
|
You will be asked for a password up to twice (ssh login, then sudo).
|
||||||
|
On a fresh image both are: 147147
|
||||||
|
EOF
|
||||||
|
SSHOPTS="-o StrictHostKeyChecking=accept-new -o UserKnownHostsFile=/dev/null"
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
cat "$BOOT" | ssh $SSHOPTS "user@$PHONE" \
|
||||||
|
'sudo dd of=/dev/disk/by-partlabel/boot_a bs=1M conv=fsync status=none && sync && echo BOOT-WRITTEN'
|
||||||
|
|
||||||
|
say "verifying modem NV survived"
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
Z=$(ssh $SSHOPTS "user@$PHONE" \
|
||||||
|
'sudo od -An -tx1 -N4096 /dev/disk/by-partlabel/modemst1 | sort -u | wc -l' 2>/dev/null || echo 0)
|
||||||
|
if [ "$Z" -gt 2 ]; then
|
||||||
|
echo "modem NV intact - cellular will work."
|
||||||
|
else
|
||||||
|
cat <<'EOF'
|
||||||
|
WARNING: the modem NV reads empty. If this device previously ran stock
|
||||||
|
Android, its factory copy (fsg) is still on the device but postmarketOS
|
||||||
|
cannot restore from it yet - see the README's modem section. If you have a
|
||||||
|
modemst backup, dd it back now.
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
|
||||||
|
say "rebooting into the installed system"
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
ssh $SSHOPTS "user@$PHONE" \
|
||||||
|
'sudo setsid sh -c "sleep 2; /sbin/reboot" </dev/null >/dev/null 2>&1 & sleep 5' || true
|
||||||
|
|
||||||
|
cat <<'EOF'
|
||||||
|
|
||||||
|
DONE. The phone reboots into postmarketOS from its own boot partition.
|
||||||
|
Log in as user / 147147 (change it!). For VoLTE, write your carrier's
|
||||||
|
P-CSCF into /etc/imsd.env and restart imsd - see the README.
|
||||||
|
EOF
|
||||||
Loading…
Reference in a new issue