The Qualcomm Partition Map
Qualcomm automotive platforms store everything on UFS, partitioned by GPT (GUID Partition Table), the same scheme as PC disks but with automotive-specific names. LUN 0 holds the boot chain (xbl, abl, tz); LUN 1+ holds OS images, modem firmware, and data. Updatable partitions use A/B slots (_a / _b) so OTA can write the inactive slot while the active slot keeps running. Your QFIL flash package ships rawprogram*.xml (what to write, where) and patch*.xml (post-write fixups). Learn the partition names: they’re the vocabulary of every flash log, fastboot command, and OTA failure you’ll debug.
You flash boot.img and super.img weekly. This page is the map on the wall: what each partition is, which LUN it lives on, and why some have _a/_b suffixes while others don’t.
GPT on UFS: The Address Book
Section titled “GPT on UFS: The Address Book”GPT is a partition table format stored at the start of each UFS LUN (Logical Unit). It defines named regions with start sector, size, and GUID.
| Concept | What It Means | Your Context |
|---|---|---|
| UFS | Universal Flash Storage — the physical chip | 64–256 GB on cockpit boards |
| LUN | Logical Unit — virtual disk on one UFS chip | LUN 0 = boot, LUN 1 = OS/firmware |
| GPT | Partition table on each LUN | Defines boot_a, modem, userdata, etc. |
| Partition | Named byte range within a LUN | What QFIL, fastboot, and OTA target by name |
| Image | File that fills a partition | boot.img, NON-HLOS.bin, super.img |
Every flash command resolves a name → LUN → sector offset via GPT.
flowchart TB subgraph UFS["UFS Chip"] subgraph LUN0["LUN 0 — Boot Chain"] GPT0["GPT Header"] XBL["xbl / xbl_config"] ABL["abl"] TZ["tz / devcfg / hyp"] end subgraph LUN1["LUN 1 — OS & Firmware"] GPT1["GPT Header"] BOOT["boot_a / boot_b"] SUPER["super"] MODEM["modem_a / modem_b"] PERSIST["persist"] USER["userdata"] end endThe Partition Table: Know These Names Cold
Section titled “The Partition Table: Know These Names Cold”Below is a representative Qualcomm automotive layout. Exact sizes vary by platform (SA8155P vs SA8295P) and program. Always trust your programmer XML, not this table’s byte counts.
Boot Chain Partitions (LUN 0, Typically Not A/B Slotted)
Section titled “Boot Chain Partitions (LUN 0, Typically Not A/B Slotted)”| Partition | Full Name / Role | Updated How Often | A/B? |
|---|---|---|---|
| xbl | eXtensible Boot Loader — first code from UFS after ROM | Rarely (BSP milestone) | No |
| xbl_config | XBL configuration / DDR training data | Rarely | No |
| abl | Android Boot Loader — loads kernel, picks A/B slot | Occasionally | No* |
| hyp | Hypervisor image (QHEE) — loads before guest OSes | Milestone | No |
| tz | TrustZone / QSEE — secure world firmware | Milestone | No |
| aop | Always-On Processor firmware — PMIC, sensors, low-power wake | Rarely | No |
| devcfg | Device configuration for TZ / security policies | Milestone | No |
| vbmeta | Verified Boot metadata (AVB descriptors, hash roots) | Every OS build | Sometimes slotted† |
* Some programs slot abl; most automotive BSPs keep ABL singular and let it select between slotted OS partitions.
† On Virtual A/B and newer AAOS, vbmeta_a/b may exist; legacy layouts use a single vbmeta.
OS & Firmware Partitions (LUN 1, A/B Slotted)
Section titled “OS & Firmware Partitions (LUN 1, A/B Slotted)”| Partition | Role | A/B? | Why Slotted |
|---|---|---|---|
| boot | Kernel + ramdisk (and sometimes dtb) | Yes | OTA swaps kernel without touching XBL |
| super | Dynamic partition container (system, vendor, product, …) |
Yes | Largest OS payload; primary OTA target |
| modem | AMSS / modem firmware (NON-HLOS) | Yes | Modem updates independent of Android |
| vbmeta | AVB signing metadata for boot/super | Yes | Must match the slot being activated |
| dtbo | Device Tree Overlays (display/camera variants) | Yes | Hardware variant without full reflash |
| vendor_boot | Vendor ramdisk/modules (GKI era) | Yes | Decouples vendor kernel modules from boot |
| persist | Calibration, Wi-Fi/BT MAC, factory tuning | No | Must survive slot switches (shared state) |
| misc | Bootloader message, recovery command, wipe flags | No | Communication channel for recovery/OTA |
| userdata | Apps, settings, maps, logs | No | User data survives OS updates |
| metadata | Encryption metadata, filesystem hints | No | Tied to userdata encryption state |
| frp | Factory Reset Protection token storage | No | Security; not slot-specific |
Partitions that change every sprint usually get _a/_b suffixes. Partitions that must survive a slot flip stay singular: persist, misc, userdata.
Think of UFS as a multi-story parking garage. LUN 0 is the ground floor with the elevator controls — XBL, ABL, TZ. You almost never remodel it. LUN 1 is two identical upper floors — Slot A and Slot B. OTA parks the new build on the empty floor while cars still drive on the other. persist and userdata are the lobby and tenant storage — they don’t duplicate per floor; everyone shares them regardless of which upper floor is active.
A/B Slot Naming: _a, _b, and the Active Slot
Section titled “A/B Slot Naming: _a, _b, and the Active Slot”Android A/B OTA maintains two copies of updatable firmware. Partition names encode the slot:
boot_a boot_bsystem_a system_b ← inside super (dynamic partitions)modem_a modem_bvbmeta_a vbmeta_bThe bootloader (ABL) reads slot metadata (often in misc or dedicated bootctrl metadata) to decide which slot to boot:
| Property | Meaning |
|---|---|
| Current slot | The slot that booted this session (a or b) |
| Active / successful | Slot marked bootable after successful boot |
| Unbootable | Slot failed verification; skipped until repaired |
| Retry count | Attempts remaining before marking slot bad |
flowchart LR ABL["ABL reads slot metadata"] ABL -->|"slot A active"| BOOT_A["boot_a → super (system_a)"] ABL -->|"slot B active"| BOOT_B["boot_b → super (system_b)"] BOOT_A --> AAOS["AAOS / QNX guests"] BOOT_B --> AAOSAfter OTA, the roles swap: whichever slot was inactive becomes the one you boot.
The super Partition: Dynamic Partitions Inside One Blob
Section titled “The super Partition: Dynamic Partitions Inside One Blob”Modern AAOS uses dynamic partitions: logical partitions (system, vendor, product, odm) live inside a single physical super partition rather than each having fixed GPT entries.
Inside super |
Typical Contents |
|---|---|
| system | AOSP framework, core apps |
| vendor | HALs, proprietary blobs, QTI extensions |
| product | Product-specific apps and overlays |
| odm | OEM/device-specific customization |
QFIL flashes super.img as one write; lpmake / lpdump (or your build system) defines the internal layout. OTA updates often patch sub-partitions via delta payloads against the inactive slot’s super.
Flashing system.img directly when your platform uses dynamic partitions inside super will fail or corrupt layout. Match your flash package to the partition scheme: flat GPT partitions vs super-hosted dynamic partitions. Check BoardConfig.mk and your rawprogram XML, not a generic phone flash guide.
rawprogram*.xml and patch*.xml
Section titled “rawprogram*.xml and patch*.xml”QFIL doesn’t guess offsets. Your flash package includes XML that maps images to partitions:
rawprogram*.xml
Section titled “rawprogram*.xml”Defines bulk programming operations: write this file to this partition on this LUN.
<!-- Simplified example — real files have many entries --><program SECTOR_SIZE_IN_BYTES="4096" file_sector_offset="0" filename="xbl.elf" label="xbl" num_partition_sectors="512" physical_partition_number="0" start_sector="256"/>| XML Attribute | Meaning |
|---|---|
filename |
Image file on your host PC |
label |
GPT partition name |
physical_partition_number |
LUN index (0 = boot LUN) |
start_sector / num_partition_sectors |
Byte range via sector math |
SECTOR_SIZE_IN_BYTES |
Usually 4096 on UFS |
Multiple files exist for multi-LUN flashes: rawprogram0.xml (LUN 0), rawprogram1.xml (LUN 1), etc.
patch*.xml
Section titled “patch*.xml”Defines post-write patches, small fixups that can’t be expressed as a full image write:
- Zeroing/unlocking regions
- Writing partition-table metadata after bulk program
- Setting flags in
miscor provisioning sectors - GPT header updates after partition resize
rawprogram handles bulk loads; patch XML handles precise surgery after the load.
Keep a partition cheat sheet pinned next to your bench:
- Before QFIL: confirm LUN count in XML matches your storage config
- Before fastboot:
fastboot getvar all | grep slotto know the active slot - Before OTA test:
adb shell bootctl get-current-slotto verify which slot you’re about to overwrite - After failed flash: check whether LUN 0 (xbl/abl) was touched. That determines your recovery path.
When a log says FAILED (remote: partition table doesn't exist), you’re targeting a partition name that isn’t in GPT for that LUN. Wrong XML variant or wrong platform build.
Which Partitions Are A/B Slotted (and Why)
Section titled “Which Partitions Are A/B Slotted (and Why)”| Category | Examples | Slotted? | Reason |
|---|---|---|---|
| Boot chain root of trust | xbl, tz, hyp, aop | No | Small, tightly coupled, verified as a chain; brick risk too high to duplicate blindly |
| OS runtime | boot, super, vendor_boot | Yes | Large, frequent updates; need seamless OTA |
| Co-processor firmware | modem, adsp, cdsp | Yes | Independent version streams from Android |
| Verification metadata | vbmeta | Yes | Must match the OS slot being activated |
| Shared persistent state | persist, misc, userdata | No | Must survive slot switches; not versioned as A/B pairs |
| Factory/security | frp, devinfo | No | Tied to device identity, not OS version |
Partition Map Variants Across Programs
The names stay remarkably consistent across SA8155P programs; the sizes and LUN assignment do not. A rear-seat-only variant may shrink super and grow userdata. A telematics-heavy variant enlarges modem. Always flash with the XML set from the exact build ID you’re deploying. Mixing XML from Build A with images from Build B is the fastest path to a bench brick.
Module 0.3 (Memory & Storage) introduced LUNs and why boot lives separately from OS. Module 5.2 (Boot Chain) walks XBL → ABL execution order. Page 8.2 (QFIL) uses these XML files. Page 8.5 (OTA Architecture) explains how the inactive slot gets written during updates.
Takeaways
Section titled “Takeaways”- GPT on UFS LUNs defines every partition; names are your flash vocabulary.
- LUN 0 = boot chain (xbl, abl, tz); LUN 1 = OS, modem, data.
- A/B slots (
_a/_b) apply to updatable firmware; persist, misc, and userdata stay singular. - rawprogram*.xml handles bulk writes; patch*.xml handles post-flash fixups. Always match the platform variant.
Check Your Understanding
1. Which partition is the primary reason A/B OTA can update the OS without rewriting XBL on LUN 0?
2. In rawprogram.xml, what does physical_partition_number="0" typically indicate?
3. Why are persist and misc NOT A/B slotted?