# Pixel 10a "stallion" - safe flash manual (self-built GrapheneOS, bootloader stays UNLOCKED) A validation flash of a self-built userdebug/test-keys image. The bootloader **stays UNLOCKED** - we are deliberately NOT locking it (locking on test keys is the one real brick). The procedure was verified against the actual build artifacts on 2026-07-09; the facts that make it safe: - Always use the **build-matched** `fastboot`/`adb` from the tree that produced the image you're flashing: `/out/host/linux-x86/bin/`. On this build box that's `/build/grapheneos/out/…` (the 2026-07 full-image build lives at `/scratch/graphene-out/…`). No system platform-tools are installed, on purpose. - `fastboot-info.txt` contains NO `flash bootloader` or `flash radio` line → `flashall` never touches firmware → no anti-rollback brick vector from this flash. - `android-info.txt` is the require gate (`board=stallion` plus exact `version-bootloader` / `version-baseband` strings - the 2026-07 build required `stallion-17.0-15199480` / `g5400i-260317-260429-B-15308590`). The match is exact string equality and aborts safely on any mismatch, older or newer. Read your build's own file before flashing. - Flash sequence driven by `fastboot-info.txt`: boot/init_boot/dtbo/vendor_kernel_boot/pvmfw/ vendor_boot → vbmeta → reboot fastbootd → update-super → system/system_dlkm/system_ext/product/ vendor/vendor_dlkm. This is written for two people: **[YOU]** is whoever holds the phone and presses its buttons; **[ME]** is whoever drives the terminal on the build box. Fine if that's the same person, or a human and an assistant. --- ## Before we start - what YOU need All items below are **phone-side [YOU] actions** unless noted. - [ ] **[YOU] Charge the phone** to a comfortable level (ideally 50%+). A power loss mid-flash can hard-brick it. - [ ] **[YOU] A known-good USB-C DATA cable** - the one that shipped with the device is safest. Connect it **directly** to a rear/motherboard USB port on the build box. **No USB hub, no front-panel port.** Bad cables/hubs are the single most common cause of flashing failures. ([grapheneos.org/install/cli](https://grapheneos.org/install/cli)) - [ ] **[YOU] Headset splitter UNPLUGGED** for the entire session. The Pixel 10a has one USB-C port; a headset splitter puts it in audio-accessory mode and fastboot/adb will **not enumerate at all** (the CC pins carry analog audio, not USB). ([source.android.com/docs/core/interaction/accessories/headset/usb-adapter](https://source.android.com/docs/core/interaction/accessories/headset/usb-adapter)) - [ ] **[YOU] Enable Developer options:** Settings → About phone → tap **Build number** 7 times. - [ ] **[YOU] Enable USB debugging:** Settings → System → Developer options → **USB debugging** ON. (When you first plug in, tap **Allow** on the RSA-key prompt.) - [ ] **[YOU] Enable OEM unlocking:** Settings → System → Developer options → **OEM unlocking** ON. This requires internet (the stock OS checks the device wasn't sold carrier-locked). Without it, `fastboot flashing unlock` is refused. ([grapheneos.org/install/cli](https://grapheneos.org/install/cli), [source.android.com/.../locking_unlocking](https://source.android.com/docs/core/architecture/bootloader/locking_unlocking)) - [ ] **[YOU] Back up anything you care about.** Unlocking the bootloader triggers a **mandatory factory data reset - ALL data is erased**, including photos, videos, and app data. This is unavoidable and expected. ([source.android.com/.../locking_unlocking](https://source.android.com/docs/core/architecture/bootloader/locking_unlocking)) - [ ] **[ME] (PC-side, no phone action) Rescue kit staged locally** - I will pre-download and verify the **official Google stock stallion factory image + full-OTA zip** and the **official GrapheneOS stallion release** before we begin, so recovery needs no network. --- ## Golden rules (don't brick it) 1. **NEVER run `fastboot flashing lock`.** These images are signed with the AVB **public test key**; a locked bootloader can't verify them and drops to AVB RED = unbootable = brick. Stay UNLOCKED (orange). ([grapheneos.org/build](https://grapheneos.org/build), [source.android.com/.../boot-flow](https://source.android.com/docs/security/features/verifiedboot/boot-flow)) 2. **NEVER turn the OEM-unlocking toggle OFF.** If it's off while the OS is unbootable, `fastboot flashing unlock` is refused = hard brick with no recovery. Keep it ON throughout. ([grapheneos.org/install/cli](https://grapheneos.org/install/cli)) 3. **NEVER downgrade firmware.** Do **not** flash an older bootloader/radio than the phone already has. Tensor anti-rollback is eFuse-enforced and permanent, **even while unlocked**. For this flash we leave stock firmware alone (see rule 4). ([developers.google.com/android/images](https://developers.google.com/android/images)) 4. **`flashall` does NOT flash firmware - and we do NOT flash the self-built firmware.** We flash only the OS + vbmeta, leaving Google's stock bootloader/radio in place. (Our `fastboot-info.txt` contains no `flash bootloader`/`flash radio` line, confirming this.) 5. **NEVER interrupt a flash.** No unplugging, no button presses, no Ctrl-C, no host sleep. A partial firmware/`update-super` write is a classic brick. Never run `snapshot-update cancel`. ([grapheneos.org/install/cli](https://grapheneos.org/install/cli)) 6. **NEVER use `--force`** to push past a `requirements not met!` abort. That check is a real guardrail (exact string match on bootloader/baseband); forcing past a firmware mismatch can leave the device non-booting. --- ## The procedure I will use the build-matched tools (`fastboot` **37.0.0-2026070800**) at `/scratch/graphene-out/host/linux-x86/bin/` - no system platform-tools are installed, and these exactly match the build. udev/permissions may require me to run `fastboot` under `sudo`. ### Step 1 - [YOU] Complete the "Before we start" checklist Confirm: phone charged, headset splitter unplugged, USB-C data cable direct to a rear port, Developer options + **USB debugging** + **OEM unlocking** all ON, data backed up. Tell me when done. ### Step 2 - [ME] Prepare the PC environment and verify tools ```bash # point at the out/ of the tree that built the image you're flashing: export OUT_TREE=/build/grapheneos/out # or /scratch/graphene-out for the 2026-07 image export PATH=$OUT_TREE/host/linux-x86/bin:$PATH export ANDROID_PRODUCT_OUT=$OUT_TREE/target/product/stallion fastboot --version # must report the version your build shipped (2026-07 image: 37.0.0-2026070800) ``` ### Step 3 - [ME] Reboot the phone to the bootloader With the phone booted and USB debugging authorized: ```bash adb reboot bootloader ``` (Alternative if adb isn't authorized - **[YOU]** power off, then hold **Volume-Down** while powering on.) ### Step 4 - [YOU] Confirm bootloader mode on screen The screen shows a **red warning triangle** and the words **"Fastboot Mode"**. Tell me you see it. ([grapheneos.org/install/cli](https://grapheneos.org/install/cli)) ### Step 5 - [ME] Confirm the PC sees the phone ```bash fastboot devices # must list a serial - if blank, I'll retry under sudo fastboot getvar product # must return the stallion product string ``` If no serial appears, we STOP and fix the USB link (cable/port/permissions) before anything else. ### Step 6 - [ME] Read current device state (read-only, non-destructive) - **MANDATORY pre-flash check** ```bash fastboot getvar unlocked fastboot flashing get_unlock_ability fastboot getvar current-slot fastboot getvar version-bootloader fastboot getvar version-baseband ``` **What I check (this is the anti-rollback / mismatch gate):** - This build requires **exactly** `version-bootloader=stallion-17.0-15199480` and `version-baseband=g5400i-260317-260429-B-15308590` (from `android-info.txt`). The require check is **exact string equality** - it aborts on *any* mismatch, older **or** newer, and does **not** do version math. - Because we are **not** flashing firmware, the requirement is that the phone's current stock firmware **matches** these strings. If it differs in either direction, we **STOP** and reconcile firmware from the official Google stallion factory image before flashing the OS - we do **not** `--force`. - **Anti-rollback STOP condition:** if the phone's current bootloader/baseband is **newer** than this build's, do **not** proceed to flash anything firmware-related; downgrading Tensor firmware is a permanent brick. ([developers.google.com/android/images](https://developers.google.com/android/images)) - `unlocked` should read `yes` and `get_unlock_ability` should confirm unlockable. Tell me what the **on-screen "Device state"** line says as a cross-check. ### Step 7 - [ME/YOU] Unlock the bootloader **only if not already unlocked** - **DATA WIPE POINT** If Step 6 already shows `unlocked: yes`, **skip this step** (no-op). Otherwise **[ME]** runs: ```bash fastboot flashing unlock ``` **[YOU]** - the phone shows a warning prompt. Use a **Volume** button to move the selection to **"UNLOCK THE BOOTLOADER"**, then press **Power** to confirm. **This wipes ALL data (factory reset).** ([grapheneos.org/install/cli](https://grapheneos.org/install/cli), [source.android.com/.../locking_unlocking](https://source.android.com/docs/core/architecture/bootloader/locking_unlocking)) ### Step 8 - [ME] Flash the OS via `flashall` - **DATA WIPE POINT (`-w`)** This is the correct path for our raw `m` output (there is **no** signed factory zip / `flash-all.sh`). `flashall` reads `fastboot-info.txt` and drives the exact sequence: flash `boot`/`init_boot`/`dtbo`/`vendor_kernel_boot`/`pvmfw`/`vendor_boot` → `flash --apply-vbmeta vbmeta` → **auto-reboots into fastbootd** → `update-super` (repartitions `super` from `super_empty.img`) → flash the six logical partitions (`system`, `system_dlkm`, `system_ext`, `product`, `vendor`, `vendor_dlkm`) → erase userdata/metadata. **This does NOT flash bootloader or radio.** ([source.android.com/docs/setup/build/running](https://source.android.com/docs/setup/build/running)) ```bash fastboot flashall -w ``` - `-w` wipes userdata/metadata - correct for a first validation flash. - **[YOU] Do NOT touch the phone, cable, or terminal** until it finishes. The phone will reboot itself into **fastbootd** mid-sequence - **that is normal**, do not interrupt it. ([grapheneos.org/install/cli](https://grapheneos.org/install/cli)) - On this A/B device, `flashall` sets the flashed slot active and by default also populates the secondary slot - desirable so both slots hold this build. I will **not** pass `--skip-secondary`, and will **not** manually mark the other slot active. - If it aborts with `requirements not met!`, we **STOP** (see rule 6 / Step 6) - I will not `--force`. ### Step 9 - [ME] Trigger first boot ```bash fastboot reboot ``` ### Step 10 - [YOU] Confirm first boot and verified-boot state - The phone shows the **orange "device is unlocked / can't be verified"** warning for ~10 seconds, then boots. **This is the expected, supported state** for an unlocked test-keys build - **not** an error, and **not** a reason to lock. (It is strictly ORANGE, not yellow.) ([source.android.com/.../boot-flow](https://source.android.com/docs/security/features/verifiedboot/boot-flow), [grapheneos.org/build](https://grapheneos.org/build)) - Let it reach the setup wizard / home screen. Tell me it booted. - **[YOU] IMPORTANT:** if the setup wizard offers a final toggle that would **disable OEM unlocking** (often checked by default), **leave OEM unlocking ENABLED** - do not accept disabling it. ([grapheneos.org/install/cli](https://grapheneos.org/install/cli)) ### Step 11 - [ME] Verify the running build Once booted with USB debugging re-authorized (**[YOU]** tap **Allow** on the RSA prompt): ```bash adb shell getprop ro.build.fingerprint # expect: google/stallion/stallion:17/CP2A.260605.012/2026070800:userdebug/test-keys ``` Match confirms the self-built image is running. Done. --- ## If something goes wrong **Why you're safe:** the bootloader is **UNLOCKED** and OEM-unlocking is **ON**. That means `fastboot` still works even when Android won't boot, so essentially every bad flash here is a recoverable **soft brick** - you just re-flash a known-good image. An unlocked + OEM-unlock-on device is recoverable in software. ([grapheneos.org/install/cli](https://grapheneos.org/install/cli)) **Recovery path, in order:** 1. **[YOU]** Power off, hold **Volume-Down** while powering on → back to Fastboot Mode (red triangle). 2. **[ME]** Re-run the OS flash: `fastboot flashall -w` (drives `update-super` + fastbootd correctly - never hand-flash `system`/`vendor` from bootloader mode; they only flash in fastbootd). 3. **[ME/YOU]** If the flashed slot won't boot, prefer **re-flashing the good image to the active slot** over switching slots. (Slot-switching can trigger an anti-rollback fallback if the other slot holds older firmware.) 4. **Rescue to stock:** flash the pre-staged official **Google stallion factory image / full-OTA** ([developers.google.com/android/images](https://developers.google.com/android/images)), or use **flash.android.com** (Android Flash Tool, works from Fastboot Mode even when the OS won't boot - needs OEM unlocking, which we have). ([source.android.com/docs/setup/test/flash](https://source.android.com/docs/setup/test/flash)) Then re-flash the self-built image. 5. **Only if truly hard-bricked** (no display, no fastboot, no charge): Tensor SoCs have **no public EDL/unbrick route** → Google RMA. This is why rules 1-5 above matter more than any recovery step. **Do NOT, during recovery:** run `fastboot flashing lock`, disable OEM unlocking, flash older firmware, or interrupt a write. --- ## Known unknowns (confirm live before/at the relevant step) - **[Step 6, CRITICAL] Device anti-rollback / firmware match for the 10a specifically.** Google's May-2026 ARB advisory names Pixel 10 / 10 Pro / 10 Pro XL / 10 Pro Fold - the **10a "stallion" is NOT on that published list**, so its ARB status is **unverified from docs**. The controlling fact is the **on-device value**, not the press release. We must read `version-bootloader`/`version-baseband` (both slots if in doubt) at Step 6 and confirm the phone is **not newer** than this build before proceeding. If newer → STOP. - **[Step 6] `fastboot getvar unlocked` exact behavior on stallion** is unverified; that's why Step 6 also uses `flashing get_unlock_ability` and the on-screen "Device state" readout as cross-checks. - **[Step 6/8] Firmware string match.** Since we don't flash firmware, the stock bootloader/radio on the phone must equal the `android-info.txt` require strings. If they don't match, `flashall` will abort (correctly). We confirm live and, if needed, reconcile via the official Google factory image - **never** `--force`. - **[Step 8] Secondary-slot / vendor_kernel_boot handling** on stallion - `flashall` populates both slots by default; before executing I'll cross-check the sequence against `fastboot-info.txt` (already read: no firmware lines present) and, if a firmware reconcile is ever needed, against the official stallion factory `flash-all` command list. - **[Out of scope now - future relock only] AVB vbmeta rollback index enforcement while unlocked** is documented for LOCKED but ambiguous for UNLOCKED. We stay unlocked and use `flash --apply-vbmeta vbmeta` (verity/verification stay enabled, matching the build's `Flags:0`); we do **not** add `--disable-verity`/`--disable-verification`, and we do **not** flash a vbmeta with a lower rollback index than the device stored. Relock is a separate, deferred, higher-risk step requiring your own release/AVB keys - **not this pass**. --- The files that decide everything above live in the build output: `fastboot-info.txt` (the flash sequence; confirms no firmware lines) and `android-info.txt` (the require gate) under `$OUT_TREE/target/product/stallion/`, with the matching tools in `$OUT_TREE/host/linux-x86/bin/`. Read them for the tree you're about to flash; don't trust a manual older than your build.