QFIL: Factory Flashing
QFIL (Qualcomm Flash Image Loader) is the factory-grade tool for writing raw images to UFS/eMMC when normal boot paths are dead or you need a clean slate. It talks to the SoC in EDL (Emergency Download) mode via USB, using the Firehose protocol and a signed programmer (.elf/.mbn) to execute rawprogram*.xml and patch*.xml from your flash package. QFIL bypasses Android, fastboot, and the running OS entirely. It speaks directly to storage. Use it for first flash, unbrick, partition table rebuild, and milestone re-provision. Use fastboot for iterative dev flashes and OTA for field updates.
When fastboot says FAILED (remote: unknown command) and ADB shows no device, QFIL is the tool that still sees the silicon. This page is the factory flash playbook.
What QFIL Actually Does
Section titled “What QFIL Actually Does”QFIL is not “Android flashing.” It’s low-level storage programming:
- Host PC sends a Firehose programmer into SoC RAM
- Programmer initializes UFS/eMMC controller
- Host sends program/patch commands from XML + image files
- Programmer writes bytes to specific LUN/sector ranges
- Device reboots into whatever boot chain you just wrote
| Layer | Tool | Speaks To |
|---|---|---|
| Application | OTA agent / lb |
Update service over gRPC + SOME/IP |
| OS bootloader | fastboot | ABL in fastboot mode |
| Factory/recovery | QFIL | Firehose programmer in EDL |
| Dead silicon | QFIL + authorized programmer | PBL/ROM loader in EDL |
QFIL loads images before any OS exists to refuse them.
EDL Mode: Emergency Download
Section titled “EDL Mode: Emergency Download”EDL (Emergency Download Mode) is a USB boot path baked into Qualcomm ROM code. The SoC enumerates as a Qualcomm HS-USB QDLoader device (often PID 9008).
How You Enter EDL
Section titled “How You Enter EDL”| Method | When Used | Risk |
|---|---|---|
| Test point / EDL button | Bench boards with exposed pads | Low (hardware intent) |
ADB: reboot edl |
Debug builds with allowed command | Medium (needs working ADB) |
Fastboot: reboot emergency |
Some platforms | Medium |
| Dead boot / blank flash | Automatic; PBL falls to EDL | N/A (you’re already there) |
| Special boot strap pins | Production fixtures | Low (fixture-controlled) |
Consumer phone forums love EDL cable tricks (short D+/D−). Automotive bench boards use test points or fixture control. Don’t assume phone hacks work on your cockpit harness. Wrong entry method can leave the board in an undefined state or trip security fuses on production-fused units.
flowchart TD POWER["Power On / Reset"] --> PBL["PBL (ROM)"] PBL -->|"Valid XBL on UFS"| XBL["Normal Boot → XBL → ABL → OS"] PBL -->|"No valid boot chain / forced EDL"| EDL["EDL Mode<br/>USB QDLoader 9008"] EDL --> QFIL["QFIL sends Firehose programmer"] QFIL --> FH["Firehose running in RAM"] FH --> WRITE["Execute rawprogram + patch XML"] WRITE --> REBOOT["Reboot to new firmware"]Firehose Protocol: The Language QFIL Speaks
Section titled “Firehose Protocol: The Language QFIL Speaks”Once in EDL, the host cannot simply “copy a file to disk.” The SoC needs a programmer: a tiny signed binary loaded into RAM that understands Firehose commands.
| Firehose Concept | Purpose |
|---|---|
| Programmer (.elf / .mbn / .melf) | Chip-specific loader; must match SoC (e.g., SA8155P variant) |
| Configure | Set storage type (UFS), LUN count, sector size |
| Program | Write image data to partition/sector range |
| Patch | Apply small fixups from patch XML |
| Reset | Reboot device after flash complete |
| Digest / signature | Verify programmer authenticity (secure boot enforced on production units) |
Typical QFIL log flow:
Connecting to QDLoader 9008...Sending programmer: prog_firehose_ddr.elfTarget configured: UFS, 2 LUNs, 4096 sector sizeProgramming xbl.elf → LUN 0, partition xbl ... OKProgramming boot.img → LUN 1, partition boot_a ... OKApplying patch0.xml ... OKResetting device...Firehose is a high-pressure stream of sector writes. You’re not mounting filesystems; you’re hosing bytes into raw partitions.
Normal boot is a tenant moving into a furnished apartment — ABL opens the door, Android unpacks into RAM. EDL + Firehose is demolition and reconstruction — the building manager (PBL) lets the construction crew (programmer) strip walls to studs and rebuild from blueprints (rawprogram XML). Nothing inside the apartment matters because you’re not going through the front door.
Step-by-Step QFIL Flash Flow
Section titled “Step-by-Step QFIL Flash Flow”1. Prepare the Flash Package
Section titled “1. Prepare the Flash Package”Your BSP/build drop contains:
flash_package/├── prog_firehose_*.elf # Programmer for your SoC + storage├── rawprogram0.xml # LUN 0 programs├── rawprogram1.xml # LUN 1 programs├── patch0.xml├── patch1.xml├── xbl.elf├── abl.elf├── boot.img├── super.img├── NON-HLOS.bin # modem├── vbmeta.img└── ...Verify: build ID, platform variant, UFS vs eMMC, sparse vs raw image formats.
2. Enter EDL
Section titled “2. Enter EDL”Use test point, ADB, or fixture. Confirm device in Device Manager / lsusb as Qualcomm QDLoader 9008.
3. Launch QFIL (or CLI equivalent)
Section titled “3. Launch QFIL (or CLI equivalent)”- Select Flat Build (most automotive packages)
- Point to prog_firehose programmer
- Load rawprogram0.xml (+ rawprogram1, etc.)
- Load matching patch.xml*
- Ensure image search path includes all referenced
filename=entries
4. Download → Flash
Section titled “4. Download → Flash”QFIL:
- Uploads programmer to RAM
- Sends configure for UFS
- Executes each
<program>entry sequentially - Applies patches
- Resets device
5. Verify Boot
Section titled “5. Verify Boot”First boot after full flash may take longer (file system format, slot init). Check:
- Serial log from XBL/ABL
- ADB availability
- Active slot:
adb shell bootctl get-current-slot - Modem attach if AMSS was flashed
Sparse Images vs Raw Images
Large partitions (system, super) often ship as sparse images, an Android format that encodes “skip these empty blocks.” Firehose understands sparse natively on most programmers. Flashing a sparse image as raw (or vice versa) produces wrong-size writes or corrupt filesystems with no immediate error. Match the format in your XML filename to what the build system generated.
QFIL vs Fastboot vs OTA: Decision Matrix
Section titled “QFIL vs Fastboot vs OTA: Decision Matrix”| Scenario | Tool | Why |
|---|---|---|
| Brand-new board, empty UFS | QFIL | No bootloader exists to enter fastboot |
| Bricked boot / corrupt GPT | QFIL | Must rewrite LUN 0 and partition table |
| Full milestone re-provision | QFIL | Clean, reproducible factory state |
| Iterative kernel/boot test | fastboot | Seconds per flash, OS not required |
Single partition swap (boot, vendor_boot) |
fastboot | Surgical, preserves userdata |
| Field fleet update | OTA (lb / update_engine) |
Signed, staged, rollback-aware |
| Modem-only update (AMSS drop) | fastboot or QFIL | fastboot if partition exposed; QFIL for full NON-HLOS refresh |
| Userdata wipe + reflash OS | QFIL or fastboot -w |
QFIL for total rebuild; fastboot for dev wipe |
flowchart TD Q{"What's the device state?"} Q -->|"No boot at all"| QFIL Q -->|"Fastboot available"| FB["fastboot flash <partition>"] Q -->|"OS running, normal ops"| OTA["OTA / lb campaign"] Q -->|"Need LUN 0 rewrite"| QFIL FB -->|"Need full factory reset"| QFILReach for QFIL when:
- The board doesn’t enumerate in fastboot; only QDLoader 9008 appears
- You need to change partition layout or recover from a wrong XML flash
- You’re doing first article bring-up with a golden flash package
- Someone flashed phone firmware onto an automotive board (yes, it happens)
Don’t reach for QFIL when:
- You’re iterating on
boot.imgfive times an hour: use fastboot - You’re pushing a signed build to 100 fleet vehicles: use OTA
- You only need
adb shelldebug: QFIL is overkill and wipes state
Bench ritual: Before every QFIL session, screenshot the build ID, programmer filename, and rawprogram variant. After every QFIL session, log active slot and first-boot result. Future-you debugging a bricked board will need all three.
Using a programmer or rawprogram from the wrong chip stepping (SA8155P build on SA8295P hardware) often “succeeds” in QFIL then fails silently at first XBL instruction. The flash log shows all green checks. The serial log shows garbage. Programmer + XML + images must be a matched set from one release artifact.
Page 8.1 maps partition names to LUNs, the labels in your rawprogram XML. Page 8.3 covers fastboot for day-to-day dev. Page 8.4 explains why unsigned programmers get rejected on production-fused units. Page 8.6 covers OTA for everything QFIL shouldn’t touch in the field.
What to remember
Section titled “What to remember”- QFIL programs UFS via EDL + Firehose, below Android and below fastboot.
- rawprogram/patch XML + signed programmer + matched images = one atomic flash package.
- Factory/unbrick/first flash → QFIL. Dev iteration → fastboot. Fleet delivery → OTA.
- QFIL success in the log ≠ boot success. Always verify serial, slot, and modem.
Check Your Understanding
1. What transport mode does QFIL use to communicate with a Qualcomm SoC during factory flashing?
2. When is QFIL the correct tool instead of fastboot?
3. In the Firehose flash flow, what is the role of the programmer (.elf)?