# Boot flow and architecture overview

A cold boot refers to the process of starting the system from a power-off state. The cold boot process involves the following steps:

1. Cold boot starts the execution from the primary boot loader (PBL) that sets up the initial system for the eXtensible Boot Loader (XBL).
2. The XBL performs wider system initialization including DDR initialization and loads a UEFI image.
3. UEFI provides a rich firmware interface that loads systemd-boot as a boot manager on Qualcomm Linux to manage the OS images.

For more information, see [Cold boot
architecture](https://docs.qualcomm.com/bundle/publicresource/topics/80-80022-4/bootloader-architecture.html).

## UEFI boot managers

Qualcomm Linux supports systemd-boot as the Universal extensible firmware interface (UEFI) boot manager to load and boot the Linux kernel. The Qualcomm Linux kernel, in this case, is built as an EFI stub.

## Systemd-boot

Systemd-boot is a UEFI boot manager that executes EFI images, provides
boot entries, and supports unified kernel images (UKI). Systemd-boot supports
the following components:

- Boot entries: The type 1 boot loader specification entries are in the
`loader/entries/` directory on the ESP. These files describe the Qualcomm^®^ Linux
kernel images with the associated initrd images and other EFI binaries.
- UKI: The type 2 boot loader
specification EFI unified kernel images are executable EFI binaries located in the `/EFI/Linux/` directory on the ESP.

    For more information about the boot entries and unified kernel images, see
[The Boot Loader Specification](https://uapi-group.org/specifications/specs/boot_loader_specification/).

Systemd-boot is a part of the systemd package of the meta
Yocto layer. The Yocto recipe uses the
`recipes-kernel/images/esp-qcom-image.bb` recipe file to handle the ESP image generation.

For more information about systemd-boot, see
[Configure and secure boot with systemd-boot and UKI](https://docs.qualcomm.com/bundle/publicresource/topics/80-80022-27/configure_and_secure_boot_with_systemd_boot_and_uki.html).

## Qualcomm Linux kernel as the EFI stub

The EFI boot stub allows booting the Qualcomm Linux kernel directly without a
conventional EFI boot loader.

The boot firmware can load the EFI image as an executable file when the
Qualcomm Linux kernel is compiled with the `CONFIG_EFI_STUB` kernel
configuration option. In this case, the firmware loader navigates to the
`EFI boot stub` location in the EFI image
`drivers/firmware/efi/libstub/` to boot the kernel.

For Arm^®^ (Arm64), where compressed kernel support is not available, the
kernel image functions as a portable executable (PE) file format or common
object file format (COFF) image, and the EFI stub is linked into the
kernel.

For more information about booting the Linux kernel as an EFI image, see
[The EFI Boot
Stub](https://docs.kernel.org/admin-guide/efi-stub.html).

## Boot images and ESP or boot partition

The ESP or boot partition serves as a storage location for the `efi.bin` image that packages
systemd-boot and UKI. The UKI includes kernel image, initramfs,
and kernel command-line arguments.

The UEFI firmware launches the UEFI boot loader and loads the kernel
boot images. The ESP is formatted with the file allocation table (FAT)
file system supported in the UEFI specification. For more information about the
UKI image format and the corresponding support in base Qualcomm^®^ Linux^®^ meta layers, see
[Configure and secure boot with systemd-boot and UKI](https://docs.qualcomm.com/bundle/publicresource/topics/80-80022-27/configure_and_secure_boot_with_systemd_boot_and_uki.html).

## Device tree blob selection

Qualcomm Linux supports multiple SoCs and boards within a single software
release binary. Device tree blobs (DTBs) are packaged into one
Flattened image tree (FIT) image (`qclinux_fit.img`) and stored in the
`dtb_a` partition. At boot, UEFI firmware selects the correct DTB by matching
hardware-detected identifiers against the `compatible` string of each FIT
configuration entry.

### FIT DTB packaging and configuration

The FIT image is described by an Image Tree Source (`.its`) file and built
with `mkimage`. It has two top-level sections:

- `images` — declares every binary blob: DTBs, DTBOs, and the metadata
binary.
- `configurations` — declares every platform configuration, each
referencing one or more images.

A minimal ITS skeleton:

/dts-v1/;
    / {
        images {
            /* meta data helps map config compatible to actual h/w values */
            fdt-qcom-metadata.dtb {
                data = /incbin/("./qcom-metadata.dtb");
                type = "qcom_metadata";
            };
            fdt-<soc>-<board>.dtb {
                data = /incbin/("./arch/arm64/boot/dts/qcom/<soc>-<board>.dtb");
                type = "flat_dt";
            };
        };
        configurations {
            conf-1 {
                compatible = "qcom,<soc>-<board>";
                fdt = "fdt-<soc>-<board>.dtb";
            };
            /* e.g. Base DTB + software overlay (CamX) + hardware overlay */
            conf-2 {
                compatible = "qcom,qcs9075-iot-camx-el2kvm";
                fdt = "fdt-lemans-evk.dtb",
                      "fdt-lemans-evk-camx.dtbo",
                      "fdt-lemans-el2.dtbo";
            };
        };
    };
    Copy to clipboard

### Qualcomm DTB metadata

The [Qualcomm DTB metadata](https://github.com/qualcomm-linux/qcom-dtb-metadata)
is a public GitHub project that provides:

- A specification for FIT-based DTB packaging and selection.
- `qcom-metadata.dts` source, which compiles into a metadata DTB, and used by
firmware to match hardware identifiers with a FIT configuration.

The metadata DTS groups allowable `compatible` string suffix tokens into
nodes: `soc`, `soc-sku`, `socver`, `board`, `boardrev`,
`board-subtype-*`, `softsku`, and `oem`. Each FIT configuration
explicitly declares the required values for these nodes.

- A `compatible` string of the form `qcom,<soc>-<...suffixes...>`.
- The base DTB and optional overlays to apply in order.

At boot, UEFI reads the hardware IDs (chip ID/version, CDT board data,
detected storage type, DDR size), parses the compiled metadata DTB, and
iterates FIT configurations to find the first one whose `compatible` tokens
all match what the hardware reports.

### Boot-Time Selection Flow

1. UEFI loads `qclinux_fit.img` from the `dtb_a` partition.
2. The embedded `qcom-metadata.dtb` (`type = "qcom_metadata"`) is parsed to
build a table mapping hardware numeric IDs to the symbolic token names used
in `compatible` strings.
3. Hardware identifiers are read:

    - SoC chip ID and version — from SoC registers.
    - Board type, board revision, peripheral subtype — from the
Configuration Data Table (CDT) in board persistent memory.
    - Storage type — boot device detected by UEFI.
    - DDR size — memory size detected by UEFI.
4. FIT configurations are iterated in order (`conf-1`, `conf-2`, …).
5. For each configuration, every token in its `compatible` string is matched
exactly against the hardware-derived values. If all tokens match, that
configuration is selected. If any token fails, the configuration is skipped.
6. The first matching configuration’s DTB(s) are loaded and passed to the
High-level OS (HLOS) through EFI boot.
7. If no configuration matches, boot fails.

### Compatible string format

Each FIT configuration carries a `compatible` string that encodes the
platform identity as a sequence of dash-separated tokens:

qcom,<soc>[-<soc-sku>][-<socver>]-<board>[-<boardrev>]
              [-<peripheral-subtype>][-<storage-type>][-<memory-size>]
              [-<softsku>][-<oem>]
    Copy to clipboard

The system includes only the tokens that apply to the platform. Each token must
exactly match a subnode name in the corresponding metadata node. The system
matches tokens in the order in which they appear; if the `compatible` string
omits a token, that dimension remains unconstrained and matches any hardware
value for that field.

**Examples:**

qcom,qcm6490-idp                    # SoC + board only (matches all revisions)
    qcom,qcs9100-qam-r1.0               # SoC + board + explicit board revision
    qcom,qcs6490-iot-subtype2           # SoC + board + peripheral subtype
    Copy to clipboard

### Yocto support

Yocto provides easy to configure wrappers around dtb packaging with earlier
described format to let user easily add and extend configuration.

A FIT image is generated containing all DTB and DTBO files listed in
`KERNEL_DEVICETREE` and `LINUX_QCOM_KERNEL_DEVICETREE`.  These files are
packed into the `images` section of the FIT image. DTB overlays are applied
at boot time by UEFI.

# Upstream DTBs and DTBOs
    KERNEL_DEVICETREE ?= " \
        qcom/qcs6490-rb3gen2.dtb \
        qcom/qcs6490-rb3gen2-industrial-mezzanine.dtbo \
        qcom/qcs6490-rb3gen2-vision-mezzanine.dtbo \
        "
    
    # Downstream-only DTBOs (not yet upstreamed)
    LINUX_QCOM_KERNEL_DEVICETREE ?= " \
        qcom/qcs6490-rb3gen2-vision-mezzanine-camx.dtbo \
        "
    Copy to clipboard

The `configurations` section of the FIT image is generated from
`FIT_DTB_COMPATIBLE` entries defined in
`conf/machine/include/fit-dtb-compatible.inc`.

Each `FIT_DTB_COMPATIBLE` entry maps a DTB (or DTB+DTBO combination) key to
one or more `compatible` strings. UEFI matches these strings against
hardware-derived identifiers at boot time to select the correct configuration.

**Single DTB — no overlay:**

FIT_DTB_COMPATIBLE[qcs6490-rb3gen2] = " \
        qcom,qcs5430-iot \
        qcom,qcs6490-iot \
        "
    Copy to clipboard

**DTB + DTBO combination:**

The key uses a `+` separator between the base DTB name and the overlay name.
The firmware applies the overlay on top of the base DTB at boot time:

FIT_DTB_COMPATIBLE[qcs6490-rb3gen2+qcs6490-rb3gen2-vision-mezzanine] = " \
        qcom,qcs5430-iot-subtype2 \
        qcom,qcs6490-iot-subtype2 \
        "
    Copy to clipboard

**Multiple DTB+DTBO combinations for the same platform:**

FIT_DTB_COMPATIBLE[qcs6490-rb3gen2] = " \
        qcom,qcs5430-iot \
        qcom,qcs6490-iot \
        "
    FIT_DTB_COMPATIBLE[qcs6490-rb3gen2+qcs6490-rb3gen2-industrial-mezzanine] = " \
        qcom,qcs5430-iot-subtype9 \
        qcom,qcs6490-iot-subtype9 \
        "
    FIT_DTB_COMPATIBLE[qcs6490-rb3gen2+qcs6490-rb3gen2-vision-mezzanine] = " \
        qcom,qcs5430-iot-subtype2 \
        qcom,qcs6490-iot-subtype2 \
        "
    FIT_DTB_COMPATIBLE[qcs6490-rb3gen2+qcs6490-rb3gen2-vision-mezzanine-camx] = " \
        qcom,qcs6490-iot-camx \
        qcom,qcs6490-iot-subtype2-camx \
        "
    Copy to clipboard

These entries produce the following `configurations` block in the generated
FIT image:

configurations {
        conf-1 {
            description = "FDT Blob";
            fdt = "fdt-qcs6490-rb3gen2.dtb";
            compatible = "qcom,qcs6490-iot";
        };
        conf-2 {
            description = "FDT Blob";
            fdt = "fdt-qcs6490-rb3gen2.dtb",
                  "fdt-qcs6490-rb3gen2-industrial-mezzanine.dtbo";
            compatible = "qcom,qcs6490-iot-subtype9";
        };
        conf-3 {
            description = "FDT Blob";
            fdt = "fdt-qcs6490-rb3gen2.dtb",
                  "fdt-qcs6490-rb3gen2-vision-mezzanine.dtbo";
            compatible = "qcom,qcs6490-iot-subtype2";
        };
    };
    Copy to clipboard

Last Published: Apr 27, 2026

[Previous Topic
Get started with the Qualcomm Linux kernel](https://docs.qualcomm.com/bundle/publicresource/80-80022-3/topics/getting_started_chapter2.md) [Next Topic
Develop the kernel](https://docs.qualcomm.com/bundle/publicresource/80-80022-3/topics/kernel-development.md)