Skip to content

The Qualcomm Partition Map

TL;DR

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 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
end

The 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.

Mental Model

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_b
system_a system_b ← inside super (dynamic partitions)
modem_a modem_b
vbmeta_a vbmeta_b

The 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 --> AAOS

After 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.

Common Gotcha

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.

QFIL doesn’t guess offsets. Your flash package includes XML that maps images to partitions:

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.

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 misc or provisioning sectors
  • GPT header updates after partition resize

rawprogram handles bulk loads; patch XML handles precise surgery after the load.

Where You'll See This

Keep a partition cheat sheet pinned next to your bench:

  1. Before QFIL: confirm LUN count in XML matches your storage config
  2. Before fastboot: fastboot getvar all | grep slot to know the active slot
  3. Before OTA test: adb shell bootctl get-current-slot to verify which slot you’re about to overwrite
  4. 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.

Connect the Dots

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.

  1. GPT on UFS LUNs defines every partition; names are your flash vocabulary.
  2. LUN 0 = boot chain (xbl, abl, tz); LUN 1 = OS, modem, data.
  3. A/B slots (_a/_b) apply to updatable firmware; persist, misc, and userdata stay singular.
  4. 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?