7.1. Storage controllers — UFS, ICE, and SDCC¶
The boot medium and the two SD/eMMC controllers, from the device tree, the XBL
uefiplat.cfg config, and the kernel config. This is the standing subsystem
view — the controller, the PHY, the inline crypto engine, and the two SDCC
instances — with the clock and regulator wiring a replacement bootloader
would have to reproduce, and what XBL hands ABL under Where the boot loader
touches storage below.
There are three storage controllers on the die and one boot device:
Controller |
Node / base |
Role here |
State in the shipped tree |
|---|---|---|---|
UFS host |
|
the boot device (SK Hynix UFS) |
base |
SDCC1 |
|
8-bit eMMC-class + CQE + ICE |
present, |
SDCC2 |
|
4-bit removable microSD |
enabled by |
7.1.1. UFS host controller¶
ufshc@1d84000, compatible = "qcom,ufshc" — the Qualcomm UFS host wrapping
a standard UFSHCI core.
- Register windows:
two, named
ufs_memandufs_ice:ufs_mem0x1D84000 size 0x3000 — the UFSHCI register block (UTRLBA/UTRLDBR doorbells, UPIU host/response, capability registers).ufs_ice0x1D90000 size 0x8000 — the inline crypto register block (see Inline crypto (ICE) below).
The XBL MMAP names the whole span
"UFS UFS REGS" 0x01D80000 size 0x20000, so both windows live inside one 128 KiB device page (UNCACHEABLE/NS_DEVICEinuefiplat.cfg). ICE is a sub-block of the UFS controller on this SoC, not a separate crypto core.- Interrupt:
SPI
0x109(265), level.- Link:
lanes-per-direction = 2— a 2-lane M-PHY.dev-ref-clk-freq = 0selects the 19.2 MHz device reference clock.spm-level = 5is the deepest UFS low-power (hibern8 + clock-gating) level allowed.- Reset:
resets = <gcc 0x04>,core_reset— the GCC UFS BCR. Adev-reset-assert/dev-reset-deassertpinctrl pair drives the device HW-reset line.
Clocks (nine, resolved against the GCC / RPMh providers in Clock tree — GCC, domain CCs, RPMh):
|
Provider : id |
|
What it feeds |
|---|---|---|---|
|
gcc : |
50 – 200 MHz |
UFS host core (SYS clock) |
|
gcc : |
RPMh-managed |
aggregate NoC bus clock |
|
gcc : |
RPMh-managed |
AHB config interface |
|
gcc : |
37.5 – 150 MHz |
UniPro link core |
|
gcc : |
75 – 300 MHz |
inline-crypto core clock |
|
rpmh : |
RPMh-managed |
M-PHY reference ( |
|
gcc : |
symbol clock |
TX lane-0 symbol |
|
gcc : |
symbol clock |
RX lane-0 symbol |
|
gcc : |
symbol clock |
RX lane-1 symbol |
The freq-table-hz pairs are {min, max} per clock; the four with
{0, 0} are not scaled by the host driver (they are gated on/off or voted
through RPMh). core_clk_ice topping out at 300 MHz matches the ICE clock rate
tables on SDCC1 (below).
Bus / power-mode scaling. qcom,msm-bus,num-cases = 0x16 (22) named
vectors run MIN → PWM_G1_L1 … PWM_G4_L2 → HS_RA_G1_L1 …
HS_RB_G3_L2 → MAX. That is the full UniPro power-mode ladder: PWM (slow
mode) gears 1–4 and HS (high-speed) Rate-A / Rate-B gears 1–3, each at 1 or 2
lanes, each mapping to a NoC bandwidth vote (paths 0x7b→0x200 and
0x01→0x2f5, i.e. the two UFS master ports). The controller renegotiates the
UniPro mode and re-votes bus bandwidth as gear changes.
7.1.2. UFS PHY¶
ufsphy_mem@1d87000 — the M-PHY, register window phy_mem 0x1D87000
size 0xE00, #phy-cells = 0, lanes-per-direction = 2. The base node
carries no compatible; the dtbo overlay adds it and its supplies:
compatible = "qcom,ufs-phy-qmp-v3"— a QMP V3 UFS PHY.PHY reference clocks:
ref_clk_src= rpmh0x14,ref_clk= gcc0x6e,ref_aux_clk= gcc0x74.Supplies (overlay):
vdda-phy(max 62 900 µA) andvdda-pll(max 18 300 µA).vdd-hba(host-controller rail),vcc(2.95 V,0x2D0370–0x2D2A80) andvccq2(1.8 V) come in on the controller fragment, withvccq2-pwr-collapse-supand avddp-ref-clkrail (1.15–1.2 V) for the reference clock.
Bring-up order for a from-scratch bootloader would therefore be: vote the GCC
UFS gates + RPMh ref_clk, raise vdda-phy / vdda-pll and vcc /
vccq2, release core_reset, initialise the QMP V3 PHY, bring UniPro up
in PWM G1 and gear-switch to HS (an engineering inference from the DTB/regulator
map, not a sequence tested against actual from-scratch bootloader code). XBL
already did all of this — the UFS link is up at ABL
hand-off (Below UEFI — execution state and hardware register surface).
7.1.3. Inline crypto (ICE)¶
The ufs_ice window at 0x1D90000 (0x8000) is the UFS Inline Crypto Engine:
AES-XTS applied to data on the DMA path between the controller and the UFS
device, per-request keyed from a keyslot, so file-based encryption costs no extra
copy. It is the storage arm of the three-way crypto split — distinct from the
general-purpose Crypto Engine (QCE) at 0x1de0000 and from
KeyMaster/QSEE key storage in TrustZone (Crypto engine (QCE) and hardware RNG,
Secure world and coprocessors (TZ, HYP, trustlets)).
Kernel wiring (from kernel_config.txt):
CONFIG_SCSI_UFSHCD=y+CONFIG_SCSI_UFSHCD_PLATFORM=y+CONFIG_SCSI_UFS_QCOM=y— the platform UFS host driver.CONFIG_SCSI_UFS_CRYPTO=yandCONFIG_SCSI_UFS_CRYPTO_QTI=y— the UFSHCI crypto extension plus Qualcomm’s QTI variant, which programs keys through the vendor keyslot / hardware-key-manager (HWKM) path rather than the generic standard-register path.CONFIG_BLK_INLINE_ENCRYPTION=y+CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK=y— the block-layer inline-crypto framework that FBE plugs into, with a software fallback when a keyslot is unavailable.The old standalone
CONFIG_CRYPTO_DEV_QCOM_ICEis not set — storage crypto is done through the UFS-integrated ICE, not the legacy separate driver. (# CONFIG_ICE is not setin the config is the unrelated Intel Ethernet driver, not this ICE.)
So the encryption stack is: fscrypt (FBE) → blk-crypto →
SCSI_UFS_CRYPTO(_QTI) → the ufs_ice register block; metadata
encryption uses DM_DEFAULT_KEY on the same engine (Boot image: kernel, DTB, ramdisk, config).
Assumption, inferred from the HWKM/ICE wrapped-key design described above,
not directly observed: the plaintext key material should not leave the
secure world, since HWKM wraps it and ICE consumes only the wrapped key in
a slot. What was actually checked is narrower — no plaintext key material
was found in any partition in the dump — which is consistent with, but does
not itself prove, that design holding at runtime.
Static end. The register offsets inside ufs_ice (the CCAP capability
register that reports algorithm/keysize support, the number of keyslots, the
config-enable registers) follow the UFSHCI-crypto spec and Qualcomm’s HWKM
addendum; the slot count and installed capabilities are runtime values in a
region that is XPU-limited and not dumped through Firehose. Confirming them needs
a live register read (Open questions and limits of analysis). The design — UFS-integrated
ICE, QTI/HWKM key path, AES-XTS FBE — is fully pinned from the tree and config.
7.1.4. SDCC1 — sdhci@7c4000¶
An 8-bit eMMC-class controller with command-queueing and its own ICE, present in the tree but with no device populated (the product’s mass storage is UFS).
- Compatible:
qcom,sdhci-msm-v5,qcom,sdhci-msm-cqe— SDHCI-MSM v5 with the command-queue engine (CQE / CQHCI).- Register windows:
hc_mem0x7C4000 (0x1000),cqhci_mem0x7C5000 (0x1000),cqhci_ice0x7C8000 (0x8000) — a second integrated ICE, on the SD/eMMC side. XBL MMAP:"SDC1_REG" 0x007C0000 size 0x20000.- Interrupts:
hc_irq0x281(641),pwr_irq0x284(644).- Bus / modes:
qcom,bus-width = 8;HS400_1p8v,HS200_1p8v,DDR_1p8v— 1.8 V eMMC HS400.qcom,clk-rates400 kHz → 384 MHz;qcom,ice-clk-rates = {300 MHz, 100 MHz}.- Clocks:
iface_clkgcc0x65,core_clkgcc0x66,ice_core_clkgcc0x68.- State:
qcom,nonremovable; base DTBdisabled. Adtbofragment sets a 2.95 Vvdd+ 1.8 Vvdd-ioandstatus = "ok", but the fixed 1.8 V HS400 profile andnon-removableflag mark this as the internal-eMMC slot of the reference design, unused on a UFS-boot device.
7.1.5. SDCC2 — sdhci@8804000 (removable microSD)¶
- Compatible:
qcom,sdhci-msm-v5(no CQE, no ICE window).- Register window:
hc_mem0x8804000 (0x1000). Sits in thePERIPH_SSMMAP span (0x08800000).- Interrupts:
hc_irq0xCC(204),pwr_irq0xDE(222).- Bus / modes:
qcom,bus-width = 4;SDR12,SDR25,SDR50,DDR50,SDR104— a UHS-I SD card.qcom,clk-rates400 kHz → ~202 MHz (SDR104).- Clocks:
iface_clkgcc0x6a,core_clkgcc0x6b.- Enablement:
base DTB
disabled; adtbofragment sets a 2.95 Vvdd, a switchable 1.8–2.95 Vvdd-io(the UHS voltage switch),status = "ok", and ``cd-gpios = <tlmm 94 active-low>`` — a card-detect line on TLMM GPIO 94. The switchable I/O rail plus the card-detect GPIO are the signature of a real removable SD socket (contrast SDCC1’s fixed 1.8 V,non-removable).
XBL SDCC configuration (uefiplat.cfg): EnableSDHCSwitch = 0x1 (SDHC mode,
not legacy), and per-slot GPIO drive configs Sdc1GpioConfigOn = 0x1E92 /
Sdc2GpioConfigOn = 0x1E92 (active) and …Off = 0xA00 (parked). Whether the
XBL SD path is exercised depends on boot config; the boot device is UFS.
7.1.6. Where the boot loader touches storage¶
Reads its own images from UFS. XBL brings up the UFS PHY + link and selects a boot LUN (
UFS Boot LUN: %dinxbl_a.bin); the images live on the boot LUNs and the general partitions on the data LUNs (Partition map and checksums).Hands the live UFS host to ABL.
EFI_BLOCK_IOstays functional untilExitBootServices(Below UEFI — execution state and hardware register surface), so ABL and fastboot read/write through the same initialised controller.A replacement bootloader must either inherit XBL’s initialised UFS (stay in the ABL slot) or redo PHY + UniPro + clock/regulator bring-up (the sequence above) to reach the boot LUNs. SDCC is not on the boot path.
7.1.7. Provenance¶
- Source:
artifacts/boot_a/board.dts(ufshc@1d84000,ufsphy_mem@1d87000,sdhci@7c4000,sdhci@8804000— registers, IRQs, clock indices, freq/bus tables),artifacts/dtbo_a/overlay_0.dts(UFS PHY/HBA + SDCC enable fragments,cd-gpios),_READONLY/lun1/xbl_a.bin(uefiplat.cfgMMAP +## UFS ##/## SDCC ##config keys), andartifacts/boot_a/kernel_config.txt(UFS / ICE / SDHCI / inline-encryption selection).- Method:
DTB + overlay node reading, config-text carve, kernel-config cross-check. Clock ids resolved against the GCC (phandle
0x1f) and RPMh (phandle0x1e) providers. No code executed.- Cross-refs:
Below UEFI — execution state and hardware register surface (execution state at hand-off), Base kernel device tree (the SoC boot contract) (apps-SMMU / DMA path), Boot image: kernel, DTB, ramdisk, config (FBE /
DM_DEFAULT_KEY/ metadata), Crypto engine (QCE) and hardware RNG (QCE vs ICE vs KeyMaster), Secure world and coprocessors (TZ, HYP, trustlets) (HWKM / KeyMaster), Clock tree — GCC, domain CCs, RPMh (GCC/RPMh clock ids), Pin control — TLMM and the PMIC GPIOs (SDCC and UFS-reset pin states), Partition map and checksums (LUN layout).