mirror of
https://github.com/kuhyx/testsAndMisc.git
synced 2026-11-10 21:07:03 +01:00
Prep for a Ulefone Armor X12 Pro (MediaTek MT6765) that has not arrived, validated read-only against the Pixel 6a that has. Partition discovery never hardcodes boot vs init_boot. It reads /dev/block/by-name/, derives the slot scheme from observed _a suffixes, and picks the ramdisk carrier by preference order init_boot then boot over what is actually present. The AOSP launch-version rule explains why that ordering is right; the code consults the filesystem, not the API level. One path therefore serves both a Pixel (no init_boot, falls to boot_a) and a 13-launch MediaTek device (init_boot_a taken). Patching the wrong one yields a phone that will not boot. Classification refuses rather than guesses: ULEFONE needs a positive MediaTek signal AND a vendor match, with no "not a Pixel therefore Ulefone" fallback. Carrier lock is always reported UNDETERMINED, because sys.oem_unlock_allowed, ro.oem_unlock_supported and settings global oem_unlock_allowed read identically whether a device is carrier-locked or merely has the toggle off; asserting a negative would wrongly rule out a path. No flashing script, deliberately. Automating irreversible partition writes defeats the confirmation steps that catch a wrong partition or missing slot suffix. Three bugs found by running the code rather than only linting it: - SIGPIPE: `adb version | head -1` under pipefail exited 141 and killed 00-preflight.sh mid-run - 20-dump-stock.sh exited silently when no recon had run, because find on a nonexistent cache dir fails under set -e - the read-only static scan had a hole: stripping all quoted strings to avoid false positives on printf text also hid `adb shell "reboot bootloader"`. Now only printf/echo/cat arguments are stripped, and a negative self-test asserts the scan fails on injected commands Also narrowed a world-writable udev catch-all (idVendor=="*", MODE="0666") that granted every local process read/write access to every USB device; commented with a backup, adb connectivity re-verified afterwards. Validated: 58/58 offline fixture tests; 00-preflight.sh HOST READY (12/12); 10-recon.sh read-only against the Pixel reports PIXEL, boot_a, A/B, no init_boot, path C-or-D indeterminate, with the device unchanged afterwards. Untested and labelled as such in READY.md: the init_boot branch on real hardware, mtkclient over BROM, and the whole flash/verify sequence. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018ReVsw7qovYkkGbqcU9tn7
223 lines
6.6 KiB
Bash
Executable File
223 lines
6.6 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# ============================================================================
|
|
# 00-preflight.sh - Verify the host toolkit is intact. No device required.
|
|
#
|
|
# Run this first on the day the phone arrives, to confirm nothing rotted while
|
|
# it was in transit. Every check reports independently; the script exits
|
|
# non-zero if any FAIL, so it is usable as a gate.
|
|
#
|
|
# This checks the HOST only. It cannot confirm that udev actually grants
|
|
# access to a MediaTek device in BROM mode - that needs the hardware.
|
|
# ============================================================================
|
|
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"
|
|
readonly SCRIPT_DIR
|
|
readonly SCRIPT_NAME="${0##*/}"
|
|
|
|
# shellcheck source=../lib/mtk_common.sh
|
|
source "$SCRIPT_DIR/../lib/mtk_common.sh"
|
|
|
|
readonly UDEV_RULES_FILE="/etc/udev/rules.d/60-mtk-root.rules"
|
|
|
|
PASS=0
|
|
FAIL=0
|
|
WARN=0
|
|
|
|
pass() {
|
|
PASS=$((PASS + 1))
|
|
printf ' \033[0;32m[PASS]\033[0m %-34s %s\n' "$1" "${2:-}"
|
|
}
|
|
|
|
fail() {
|
|
FAIL=$((FAIL + 1))
|
|
printf ' \033[0;31m[FAIL]\033[0m %-34s %s\n' "$1" "${2:-}"
|
|
}
|
|
|
|
warn() {
|
|
WARN=$((WARN + 1))
|
|
printf ' \033[0;33m[WARN]\033[0m %-34s %s\n' "$1" "${2:-}"
|
|
}
|
|
|
|
usage() {
|
|
cat <<EOF
|
|
Usage: $SCRIPT_NAME [--help]
|
|
|
|
Verifies host tooling for the mtk_root toolkit. No device needed.
|
|
Exits non-zero if any check fails.
|
|
EOF
|
|
exit 0
|
|
}
|
|
|
|
check_tools() {
|
|
mtk_heading "Tools"
|
|
|
|
local -a required=(adb fastboot python3 git sha256sum)
|
|
local tool="" version=""
|
|
|
|
for tool in "${required[@]}"; do
|
|
if ! command -v "$tool" >/dev/null 2>&1; then
|
|
fail "$tool" "not installed - run install.sh"
|
|
continue
|
|
fi
|
|
# Invoke it, don't just locate it: a binary on PATH that cannot run is a
|
|
# failure mode `command -v` reports as success.
|
|
#
|
|
# Each capture is wrapped in `|| true` and reads the whole stream before
|
|
# slicing. Piping straight into `head -1` closes the pipe early, and under
|
|
# `set -o pipefail` the resulting SIGPIPE kills this script outright.
|
|
version=""
|
|
case "$tool" in
|
|
adb) version="$(adb version 2>/dev/null || true)" ;;
|
|
fastboot) version="$(fastboot --version 2>/dev/null || true)" ;;
|
|
python3) version="$(python3 -V 2>&1 || true)" ;;
|
|
git) version="$(git --version 2>/dev/null || true)" ;;
|
|
*) version="$("$tool" --version 2>/dev/null || true)" ;;
|
|
esac
|
|
version="${version%%$'\n'*}"
|
|
if [[ -z $version ]]; then
|
|
fail "$tool" "present but did not respond to a version query"
|
|
else
|
|
pass "$tool" "$version"
|
|
fi
|
|
done
|
|
}
|
|
|
|
check_groups() {
|
|
mtk_heading "Group membership"
|
|
|
|
local -a wanted=(plugdev adbusers)
|
|
local group="" active_groups=""
|
|
active_groups=" $(id -nG) "
|
|
|
|
for group in "${wanted[@]}"; do
|
|
if ! getent group "$group" >/dev/null 2>&1; then
|
|
warn "$group" "group does not exist on this system"
|
|
continue
|
|
fi
|
|
if [[ $active_groups == *" $group "* ]]; then
|
|
pass "$group" "active in this session"
|
|
elif id -nG "$USER" 2>/dev/null | grep -qw "$group"; then
|
|
# Membership that the current login session predates. The rule is real
|
|
# but will not take effect until re-login, and USB access will fail in
|
|
# a way that looks like a udev problem.
|
|
warn "$group" "member, but not in this session - log out and back in"
|
|
else
|
|
fail "$group" "not a member - run install.sh"
|
|
fi
|
|
done
|
|
}
|
|
|
|
check_udev() {
|
|
mtk_heading "udev rules"
|
|
|
|
if [[ -f $UDEV_RULES_FILE ]]; then
|
|
if command -v udevadm >/dev/null 2>&1 && udevadm verify --help >/dev/null 2>&1; then
|
|
# A real syntax verdict. `udevadm control --reload` exits 0 regardless,
|
|
# so it cannot be used to validate anything.
|
|
if udevadm verify "$UDEV_RULES_FILE" >/dev/null 2>&1; then
|
|
pass "60-mtk-root.rules" "present, udevadm verify clean"
|
|
else
|
|
fail "60-mtk-root.rules" "present but udevadm verify REJECTED it"
|
|
fi
|
|
else
|
|
warn "60-mtk-root.rules" "present; udevadm verify unavailable, syntax unchecked"
|
|
fi
|
|
else
|
|
fail "60-mtk-root.rules" "missing - run install.sh"
|
|
fi
|
|
|
|
# A wildcard-vendor world-writable rule is a genuine finding, not a nit: it
|
|
# applies to every USB device attached to this machine, not just phones.
|
|
local catchall=""
|
|
catchall="$(mtk_udev_catchall_files)"
|
|
if [[ -n $catchall ]]; then
|
|
fail "no world-writable catch-all" "found in: $(tr '\n' ' ' <<<"$catchall")"
|
|
printf ' A rule matching idVendor=="*" with MODE="0666" grants every\n'
|
|
printf ' local process read/write access to EVERY USB device, including\n'
|
|
printf ' storage and security keys. Narrow it: install.sh --fix-udev\n'
|
|
else
|
|
pass "no world-writable catch-all" "no wildcard 0666 rule found"
|
|
fi
|
|
}
|
|
|
|
check_venv() {
|
|
mtk_heading "mtkclient"
|
|
|
|
local venv_status=""
|
|
if venv_status="$(mtk_check_venv)"; then
|
|
pass "venv importable" "$venv_status"
|
|
else
|
|
fail "venv importable" "$venv_status"
|
|
printf ' The venv existing is not enough - it must be able to import\n'
|
|
printf ' usb/serial. A Python upgrade orphans a venv while leaving it\n'
|
|
printf ' looking complete. Rebuild: install.sh\n'
|
|
fi
|
|
|
|
local clone_dir=""
|
|
clone_dir="$(mtk_mtkclient_dir)"
|
|
if [[ -d "$clone_dir/.git" ]]; then
|
|
local rev=""
|
|
rev="$(git -C "$clone_dir" rev-parse --short HEAD 2>/dev/null || echo unknown)"
|
|
pass "mtkclient checkout" "rev ${rev}"
|
|
else
|
|
fail "mtkclient checkout" "not a git clone at ${clone_dir} - run install.sh"
|
|
fi
|
|
}
|
|
|
|
check_cache() {
|
|
mtk_heading "Workspace"
|
|
|
|
local cache_dir=""
|
|
cache_dir="$(mtk_cache_dir)"
|
|
|
|
if [[ ! -d $cache_dir ]]; then
|
|
fail "cache dir" "missing: ${cache_dir} - run install.sh"
|
|
return
|
|
fi
|
|
if [[ -w $cache_dir ]]; then
|
|
pass "cache dir writable" "$cache_dir"
|
|
else
|
|
fail "cache dir writable" "not writable: ${cache_dir}"
|
|
fi
|
|
}
|
|
|
|
main() {
|
|
printf '\033[1m%s - host readiness for the mtk_root toolkit\033[0m\n' "$SCRIPT_NAME"
|
|
|
|
check_tools
|
|
check_groups
|
|
check_udev
|
|
check_venv
|
|
check_cache
|
|
|
|
mtk_heading "Result"
|
|
printf ' %d passed, %d failed, %d warnings\n\n' "$PASS" "$FAIL" "$WARN"
|
|
|
|
if [[ $FAIL -gt 0 ]]; then
|
|
printf '\033[0;31mNOT READY\033[0m - resolve the failures above (usually: ./install.sh)\n'
|
|
return 1
|
|
fi
|
|
if [[ $WARN -gt 0 ]]; then
|
|
printf '\033[0;33mREADY, with warnings\033[0m - read them before trusting a USB connection.\n'
|
|
return 0
|
|
fi
|
|
printf '\033[0;32mHOST READY\033[0m - udev access to a real MediaTek device remains unverified\n'
|
|
printf 'until hardware is attached; that cannot be checked without the phone.\n'
|
|
return 0
|
|
}
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
-h | --help) usage ;;
|
|
*)
|
|
mtk_error "Unknown option: $1"
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
main
|