Skip to content

The Qualcomm Partition Map

Advanced11 min read
Assumes: 0.3 Memory & Boot Media
Module Progress0/6 pages mastered

Prerequisites: Module 5 (boot chain), Module 6 (OS layers), Module 7 (modem) What you’ll learn: Qualcomm partition map, QFIL factory flashing, fastboot and ADB, secure boot, OTA architecture, OTA in practice with gRPC and SOME/IP.

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 XBL and ABL do not. Each partition has its own lease, its own security clearance, and very strong opinions about who writes where.

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

* Some programs slot abl; most automotive BSPs keep ABL singular and let it select between slotted OS partitions.

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.

GPT is the address book. Each partition is a room. LUN is the floor. rawprogram.xml is the moving instructions.

Think About It

You run ‘fastboot flash boot boot.img’. The command succeeds but the board doesn’t boot. What partition-level mistake could cause this?

Reveal Answer

The most common mistake is flashing the wrong A/B slot — fastboot flash boot writes to the current slot’s partition, but ABL may boot the other slot, or you updated boot without matching vbmeta for that slot. Run fastboot getvar current-slot and adb shell bootctl get-current-slot before flashing; target the inactive slot explicitly (fastboot flash boot_b boot.img) and always pair boot + vbmeta from the same signed build.

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

If you flash system.img directly when your platform uses dynamic partitions inside super, you’ll fail or corrupt the 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?

Applied

2. In rawprogram.xml, what does physical_partition_number="0" typically indicate?

Recall

3. Why are persist and misc NOT A/B slotted?

Recall

4. You are running slot A. An OTA campaign applies to the inactive slot. Which partition set receives the write?

Applied

5. A flash log shows `FAILED (remote: partition table doesn't exist)` when programming `modem` on LUN 2, but your colleague's package uses LUN 1. What UFS concept explains the mismatch?

Synthesis

Connects to: Module 0 — Memory & Storage

6. After OTA, ABL must boot slot B. Which LUN 0 component selects the slot without being A/B-duplicated itself?

Synthesis

Connects to: Module 5 — Boot Chain

Further Reading
  • Android Partitions Overview — Official AOSP guide to system, vendor, boot, and dynamic partition layout inside super, matching the partition names you flash weekly.
  • A/B System Updates — How Android names and manages _a/_b slot pairs, bootctrl metadata, and the inactive-slot write model this page maps to GPT entries.
  • Dynamic Partitions — Explains the super container, logical sub-partitions, and why rawprogram flashes one blob instead of individual system.img files.
  • UEFI Specification (GPT) — The GUID Partition Table standard that defines how LUN sector ranges, partition labels, and GUIDs are stored on UFS.
  • Qualcomm Developer Portal — Entry point for platform-specific flash packages, programmer binaries, and BSP documentation tied to automotive SoCs like SA8155P.
  • JEDEC UFS Standard — The Universal Flash Storage specification underlying multi-LUN automotive storage and sector-addressed programming.