3.7. Base kernel device tree (the SoC boot contract)

artifacts/boot_a/board.dts is the decompiled base device tree carried inside boot_a (dtb.img, 407,904 B). It is the SoC-level description the kernel is handed at EL1 — before the board-specific overlay is applied. ABL reads this base DTB, selects one of the three PCB overlays and applies it on top (DTBO overlays), fixes up /chosen and /memory, then enters the kernel with x0 = physical FDT (Below UEFI — execution state and hardware register surface, Kernel/DTB/ramdisk load and the kernel hand-off).

This page documents the DTB’s structural / boot-contract nodes — the machine the kernel is told it is running on, and the interfaces it uses to talk to the firmware below it: SoC identity, CPU topology, the PSCI/EL3 power interface, the physical reserved-memory carve-out map, the IMEM boot-handshake cells, /chosen, the Android verified-boot firmware node, and the GIC/timer/ apps-SMMU interfaces the kernel inherits live from XBL. It deliberately does not re-enumerate the UFS, GENI/QUP or clocks/pins register surface — that is Storage controllers — UFS, ICE, and SDCC, QUP/GENI serial-engine bus map (what is wired where), Clock tree — GCC, domain CCs, RPMh and Pin control — TLMM and the PMIC GPIOs. Nor does it cover what the overlays add — that is DTBO overlays. Everything below is read directly from the decompiled DTB.

3.7.1. SoC identity

The root node fixes the silicon this DTB targets:

model       = "Qualcomm Technologies, Inc. Lagoon SoC";
compatible  = "qcom,lagoon";
qcom,msm-id    = <0x1b2 0x10000  0x1cb 0x10000>;
qcom,board-id  = <0x00 0x00>;
  • qcom,msm-id is a list of (soc-id, hw-version) pairs: 0x1b2 (434) and 0x1cb (459), both hw-version 0x10000 (major 1, minor 0). SoC-ID 434 is lagoon (the SM6350 / Snapdragon 690 platform, confirmed by model and compatible); 459 is a sibling ID in the same lagoon family, so this single base DTB serves more than one SoC-ID. ABL matches the running SoC’s fused soc-id/hw-version against this list before accepting the DTB.

  • qcom,board-id = <0 0> here is the generic base; the real board/PCB identity (onyx,pcbver-id v10/v20/v30) is carried by the overlays and is how ABL picks one (DTBO overlays). The platform (“Bitra”) vs SoC-codename (“lagoon”) relationship is covered in Onyx Boox Note Air5 C (Qualcomm SM6350).

3.7.2. CPU topology and DVFS

Eight cores in two clusters, all compatible = "arm,armv8", all enable-method = "psci" (no spin-table fallback, below):

Cores

reg (MPIDR)

capacity-dmips-mhz

dynamic-power-coefficient

qcom,freq-domain / LMh

cluster0 — cpu@0…@500 (6 cores)

0x00x500

0x400 = 1024

0x64 = 100

domain 0, 6 cores; lmh-dcvs phandle 0x05

cluster1 — cpu@600, cpu@700 (2 cores)

0x600, 0x700

0x766 = 1894

0x2bf = 703

domain 1, 2 cores; lmh-dcvs phandle 0x0d

This is the standard SM6350 Kryo 660 configuration: a 6-core efficiency cluster (Silver, Cortex-A55 class — the 1024 unit-capacity, low-leakage cores) and a 2-core performance cluster (Gold, Cortex-A77 class — capacity 1894, 7× the dynamic-power coefficient). The 6+2 split, capacities and power coefficients are read from the DTB; the Silver/Gold ↔ A55/A77 mapping is the known SM6350 core assignment, not something the generic arm,armv8 compatible encodes.

Cache hierarchy (from the cpu sub-nodes): per-core L1 I/D and L2, with a shared L3 (arm,arch-cache cache-level 3, phandle 0x06) that every core’s L2 chains to via next-level-cache. cpu-map groups the cores into cluster0/cluster1 for the scheduler.

DVFS/thermal hardware backing the two domains (in the RPMh MMIO band):

  • qcom,cpufreq-hw @ ``0x18323000`` (freq-domain0, little) + ``0x18325800`` (freq-domain1, big) — the EPSS/OSM hardware frequency-domain controller; clocks are the RPMh xo (phandle 0x1e) and a GCC alternate (0x1f).

  • qcom,limits-dcvs (qcom,msm-hw-limits, LMh) @ ``0x18358800`` (affinity 0 = little) and ``0x18350800`` (affinity 1 = big) — the Limits Management hardware that throttles each cluster’s frequency under current/thermal limit, coordinated with the AOP/RPMh (AOP — the Always-On Processor (RPMh / power back-end)). The on-flash LMh limit table is the tiny limits partition (limits.bin — a small binary header, e.g. 12 98 34 20, then zero pad); the companion limits-cdsp partition is blank (Partition map and checksums).

3.7.3. PSCI — the kernel↔EL3 power interface

psci {
    compatible = "arm,psci-1.0";
    method     = "smc";
};

Every CPU carries enable-method = "psci", so all CPU power operations — releasing the secondary cores at boot (CPU_ON), idle/suspend (CPU_SUSPEND), hotplug-down (CPU_OFF) and SYSTEM_RESET/SYSTEM_OFF — are issued as SMC calls trapping to EL3. On this SoC EL3 is owned by the resident TZ/QSEE monitor (tz_a at entry 0x14680000, Secure world and coprocessors (TZ, HYP, trustlets)), so PSCI is the concrete, DTB-declared channel through which the EL1 kernel drives the secure-world power manager. There is no spin-table; a kernel (or a bootloader replacement) that wants the secondary CPUs online must speak PSCI-over-SMC to the stock EL3 monitor. This is the runtime counterpart to the boot-chain EL ladder in Boot chain and exception-level hand-off (PBL → XBL → ABL).

3.7.4. Physical reserved-memory carve-out map

The /reserved-memory node is the DTB’s physical DRAM carve-out map. DRAM base is ``0x80000000`` (2 GiB), and two bands of no-map / removed-dma-pool regions sit at the bottom of RAM — a low band at the DRAM base and the large PIL band from 0x86000000 — followed by reusable (shared-dma-pool / CMA) pools and the display framebuffers. Each fixed region maps to a firmware image or coprocessor documented elsewhere:

Fixed (no-map) regions

Region

Base

Size

Consumer

hyp_region

0x80000000

0x600000 (6 MiB)

HYP / QHEE runtime (hyp_a entry 0x8004a000 lands here) — Secure world and coprocessors (TZ, HYP, trustlets)

xbl_aop_mem

0x80700000

0x160000 (1.375 MiB)

XBL↔AOP shared/message RAM (aop_a)

reserved-memory (cmd-db)

0x80860000

0x20000 (128 KiB)

RPMh Command DB (qcom,cmd-db), published by AOP, read by the AP RPMh driver

sec_apps_region

0x808ff000

0x1000 (4 KiB)

secure-apps hand-off page

smem

0x80900000

0x200000 (2 MiB)

SMEM — inter-subsystem shared memory

cdsp_sec_regions

0x80b00000

0x1e00000 (30 MiB)

CDSP secure region

camera_region

0x86000000

0x500000 (5 MiB)

camera (present; no camera on this e-reader)

pil_npu_region

0x86500000

0x500000 (5 MiB)

NPU PIL (NPU.FW.2.3 in modem_a) — ADSP and CDSP firmware

pil_video_region

0x86a00000

0x500000 (5 MiB)

Venus video PIL

cdsp_regions

0x86f00000

0x1e00000 (30 MiB)

CDSP (CDSP.VT.2.6, dsp_a) — ADSP and CDSP firmware

pil_adsp_region

0x88d00000

0x2800000 (40 MiB)

ADSP PIL (ADSP.VT.5.6 in modem_a) — ADSP and CDSP firmware

wlan_fw_region

0x8b500000

0x200000 (2 MiB)

WLAN firmware (WLAN.HL.3.3.1 in core_nhlos_a)

ipa_fw_region / ipa_gsi_region

0x8b700000

0x10000 + 0x5400

IPA (IP Accelerator) FW + GSI

gpu_region

0x8b715400

0x2000 (8 KiB)

GPU (Adreno) microcode scratch

modem_region

0x8b800000

0xf800000 (248 MiB)

MPSS modem (MPSS.HI.2.5.1) — the large, dormant baseband carve-out

removed_region

0xc0000000

0x3900000 (57 MiB)

generic removed pool

Reusable (shared-dma-pool / CMA) and display regions

Region

Size / base

Purpose

qseecom_region

0x1400000 (20 MiB)

QSEECom shared buffers (TZ command path)

qseecom_ta_region

0x1000000 (16 MiB)

QSEE trustlet (TA) working memory — Secure world and coprocessors (TZ, HYP, trustlets)

secure_display_region

0x8c00000 (140 MiB)

secure display / protected buffers (Widevine, CDSP SecurePD — ADSP and CDSP firmware)

mem_dump_region

0x2800000 (40 MiB)

RAM-dump capture buffer

adsp_region / linux,cma

0x800000 / 0x2000000

generic ADSP DMA pool (8 MiB) and the default 32 MiB CMA

cont_splash_region

0xa0000000 0x2300000 (35 MiB)

continuous-splash framebuffer (Splash partition)

disp_rdump_region

0xa0000000 0x2300000

display RAM-dump — overlaps the splash region (reused after splash)

dfps_data_region

0xa2300000 0x100000 (1 MiB)

dynamic-FPS panel data

Cross-check with XBL: the DTB’s PIL band 0x860000000x9b000000 (modem_region end) sits inside XBL’s single coarse PIL Reserved window 0x86000000 size 0x15800000 (→ 0x9b800000) from XBL → ABL hand-off contract (bounded) Q4 — i.e. XBL reserves one block and the DTB subdivides it into the named pil_* / modem / cdsp regions. The gap above modem_region (0x9b0000000xa0000000) is where XBL’s ABOOT FV (0x9FA00000) and MMU page-tables (0x9FF8D000) live (Below UEFI — execution state and hardware register surface); the OS load window 0xA2400000 sits just above the splash/dfps regions.

The /memory node itself is a placeholder (reg = <0 0 0 0>); how the actual DRAM base/size gets filled in at runtime is in Below UEFI — execution state and hardware register surface. A separate mem-offline node (qcom,mem-offline, granule 0x200) declares which DDR banks may be power-collapsed offline.

3.7.5. IMEM boot-handshake cells

qcom,msm-imem@146aa000 (reg = <0x146aa000 0x1000>) is the always-on SoC IMEM cookie page shared across boot stages — the same 0x146xxxxx on-chip SRAM band that holds the TZ EL3 stub (0x14680000) and XBL Sec (0x14950000, Boot chain and exception-level hand-off (PBL → XBL → ABL)). Its offsets are the software hand-shake between the kernel, the bootloader and PBL:

Cell

Offset

Role

dload_type

+0x1c

download-mode cookie — a magic written here requests EDL/download at the next reset; read by the loader/PBL (the software path complementing the hardware EDL entry, EDL / 9008 entry and the deep-flash cable)

diag_dload

+0xc8

diag download-mode config block

restart_reason

+0x65c

reboot-reason cookie — the kernel writes it (reboot bootloader / recovery / edl …); the bootloader reads it to branch (distinct from the misc BCB in Partition map and checksums)

boot_stats

+0x6b0

boot-timing counters (XO ticks) captured across stages

kaslr_offset

+0x6d0

where the kernel publishes its KASLR slide (for RAM-dump tooling)

pil

+0x94c

PIL subsystem state/status table

mem_dump_table

+0x10

pointer to the mem-dump descriptor table (RAM-dump collection)

3.7.6. /chosen and early boot config

chosen {
    bootargs = "rcupdate.rcu_expedited=1 rcu_nocbs=0-7
                earlycon=msm_geni_serial,0x98c000 kpti=off";
};
  • earlycon=msm_geni_serial,0x98c000 — the early console is the GENI/QUP serial engine at ``0x98c000`` (the serial0 alias, qcom,qup_uart@98c000). This is the debug UART referenced in Below UEFI — execution state and hardware register surface.

  • kpti=off — kernel page-table isolation disabled (the A55/A77 cores are not affected by the Meltdown variant KPTI mitigates).

  • rcu_nocbs=0-7 + rcu_expedited=1 — RCU callback offload across all 8 cores, expedited grace periods.

ABL overwrites/extends bootargs at boot (androidboot.* slot, serialno, verifiedbootstate, …) before entering the kernel — see Kernel/DTB/ramdisk load and the kernel hand-off.

3.7.7. Android verified-boot firmware node

firmware { android {
    compatible = "android,firmware";
    vbmeta { compatible = "android,vbmeta";
             parts = "vbmeta,boot,system,vendor,dtbo"; };
    fstab  { compatible = "android,fstab";
             vendor { dev  = ".../soc/1d84000.ufshc/by-name/vendor";
                      type = "ext4";
                      mnt_flags   = "ro,barrier=1,discard";
                      fsmgr_flags = "wait,slotselect,avb"; }; };
}; };

This is the device-tree side of Android Verified Boot. vbmeta/parts names the partitions chained from the top-level vbmeta descriptor (vbmeta,boot,system,vendor,dtbo) — the same chain proven test-key-signed in AVB enforcement code path (LoadImageAndAuth / libavb). The fstab entry declares vendor as an early-mount ext4 volume, read-only, with slotselect (A/B, resolved from the GPT slot bits in Partition map and checksums) and avb (dm-verity / AVB enforced). Only vendor is early-mounted from the DT here; system and the rest are dynamic partitions inside super mounted later by first-stage init.

3.7.8. Core firmware-facing infrastructure

Beyond the GIC/timer/SMMU interfaces above, three more nodes are the kernel’s structural interfaces to the always-on/secure firmware:

  • qcom,rpmh-rsc @ ``0x18200000`` (drv-0/1/2 at 0x18200000 / 0x18210000 / 0x18220000, qcom,drv-id = 2 = the APSS DRV, tcs-offset 0xd00) — the AP-side RPMh Resource State Coordinator: the kernel votes for clocks, regulators and bus/DDR states through TCS command slots that the AOP services (AOP — the Always-On Processor (RPMh / power back-end)). The large RPMh regulator tree and qcom,lagoon-rpmh-clk hang off this node.

  • qcom,cmd-db (reserved-memory@80860000) — the command DB that resolves RPMh resource names to addresses, populated by AOP (see the carve-out table above).

  • arm,gic-v3 @ ``0x17a00000`` (redistributors @ 0x17a60000, stride 0x20000 × 8 cores), interrupt-controller@b220000 (the PDC wakeup/power-domain controller) and arm,armv8-timer (clock-frequency 0x124f800 = 19.2 MHz, the XO rate) — the interrupt and time base the kernel inherits live from XBL (Below UEFI — execution state and hardware register surface).

  • apps-SMMU @ ``0x15000000`` size 0x100000 (NS_DEVICE in XBL’s map; a second tcu-base window at 0x15182000 size 0x20) — UFS, QUP and most NoC masters issue DMA as IOVAs through this SMMU and its TBUs (anoc_1_tbu@15185000, anoc_2_tbu@15189000); the GPU has its own, separate SMMU (arm,smmu-kgsl@3d40000, GPU — Adreno A619, the GMU, and the zap shader). XBL configures the UFS stream (UfsSmmuConfigForOtherBootDev = 1); the state of other streams below the OS is not characterised here (Below UEFI — execution state and hardware register surface).

3.7.9. Provenance

Source:

artifacts/boot_a/board.dts — the decompiled base DTB extracted from boot_a (dtb.img). All node names, addresses, sizes, reg values, capacities and property strings are quoted directly from that file.

Method:

Structural read of the root, cpus/cpu-map, psci, reserved-memory, qcom,msm-imem, chosen, firmware and the cpufreq-hw / rpmh-rsc / GIC / timer nodes; hex sizes converted to binary units; carve-out bases cross-checked against XBL’s memory map. No code executed.

Cross-refs:

Below UEFI — execution state and hardware register surface (execution state at hand-off), GPU — Adreno A619, the GMU, and the zap shader (the separate GPU SMMU), DTBO overlays (PCB overlays applied over this base), XBL → ABL hand-off contract (bounded) (XBL PIL Reserved window, kernel load window), Secure world and coprocessors (TZ, HYP, trustlets) (EL3 PSCI target, trustlet memory), ADSP and CDSP firmware (coprocessor images ↔ carve-outs), Platform state partitions: cdt, ddr, uefivarstore (board identity), Partition map and checksums (A/B slotselect), AVB enforcement code path (LoadImageAndAuth / libavb) (vbmeta chain), EDL / 9008 entry and the deep-flash cable (dload_type cookie), Kernel/DTB/ramdisk load and the kernel hand-off (bootargs fix-up, kernel entry).