diff --git a/Makefile b/Makefile index a6a6d54..14b132f 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ QCOM_PTOOL ?= qcom-ptool # optional build_id for Axiom contents.xml files BUILD_ID ?= -.PHONY: all check check-checksums clean generate-checksums install lint integration +.PHONY: all check check-checksums check-partitions clean generate-checksums install lint integration all: $(PLATFORMS) $(PARTITIONS_XML) $(CONTENTS_XML) @@ -29,10 +29,14 @@ lint: ruff check qcom_ptool mypy qcom_ptool -integration: all +integration: all check-partitions # make sure generated output has created expected files tests/integration/check-missing-files platforms/*/*/*.xml +check-partitions: + # validate partitions.conf for duplicate names and missing required fields + tests/integration/check-partitions + check-checksums: all # verify generated artifacts match tests/integration/checksums.sha256 # (requires PTOOL_SEED to match the seed used to produce the manifest) diff --git a/platforms/iq-x7181-evk/spinor/partitions.conf b/platforms/iq-x7181-evk/spinor/partitions.conf index 5290860..c0f3ba2 100644 --- a/platforms/iq-x7181-evk/spinor/partitions.conf +++ b/platforms/iq-x7181-evk/spinor/partitions.conf @@ -88,6 +88,6 @@ --partition --name=dtb_a --size=4096KB --type-guid=2A1A52FC-AA0B-401C-A808-5EA0F91068F8 --filename=dtb.bin --partition --name=dtb_b --size=4096KB --type-guid=A166F11A-2B39-4FAA-B7E7-F8AA080D0587 --filename=dtb.bin --partition --name=uefi_dtb_a --size=64KB --type-guid=C84D3B5E-EF34-4FA4-8118-30EAE18D3FA6 --filename=uefi_dtbs.xz ---partition --name=uefi_dtb_a --size=64KB --type-guid=5F7D760A-3EF5-4AA5-B915-69A4ECAAE662 --filename=uefi_dtbs.xz +--partition --name=uefi_dtb_b --size=64KB --type-guid=5F7D760A-3EF5-4AA5-B915-69A4ECAAE662 --filename=uefi_dtbs.xz --partition --name=uefisecapp_a --size=220KB --type-guid=BE8A7E08-1B7A-4CAE-993A-D5B7FB55B3C2 --filename=uefi_sec.mbn --partition --name=uefisecapp_b --size=220KB --type-guid=538CBDBA-D4A4-4438-A466-D7B356FAC165 --filename=uefi_sec.mbn diff --git a/tests/integration/check-partitions b/tests/integration/check-partitions new file mode 100755 index 0000000..af576de --- /dev/null +++ b/tests/integration/check-partitions @@ -0,0 +1,89 @@ +#!/usr/bin/env python3 +# Copyright (c) 2026 Qualcomm Innovation Center, Inc. All rights reserved. +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# Validate platforms/*/*/partitions.conf files for common authoring mistakes: +# +# - duplicate --name within the same physical partition (LUN) +# - --partition entry missing --name or --size + +import re +import sys +from pathlib import Path + +# Files with pre-existing duplicates not addressed by this check. Remove +# entries as the underlying configurations are corrected. +DUP_NAME_ALLOWLIST = { + # Pending separate fix for the SYSFW_VERSION duplicate around line 74. + "platforms/glymur-crd/spinor/partitions.conf", +} + + +def parse(path: Path): + """Yield (lineno, lun, name, size) for each --partition line.""" + for lineno, raw in enumerate(path.read_text().splitlines(), 1): + line = raw.strip() + if not line.startswith("--partition"): + continue + lun_m = re.search(r"--(?:lun|phys-part)=(\S+)", line) + name_m = re.search(r"--name=(\S+)", line) + size_m = re.search(r"--size=(\S+)", line) + yield ( + lineno, + lun_m.group(1) if lun_m else "0", + name_m.group(1) if name_m else None, + size_m.group(1) if size_m else None, + ) + + +def check(path: Path) -> tuple[list[str], list[str]]: + """Return (errors, warnings) for path.""" + errors: list[str] = [] + warnings: list[str] = [] + by_lun_name: dict[str, dict[str, list[int]]] = {} + + for lineno, lun, name, size in parse(path): + if name is None: + errors.append(f"{path}:{lineno}: --partition without --name") + continue + if size is None: + errors.append(f"{path}:{lineno}: --partition '{name}' without --size") + by_lun_name.setdefault(lun, {}).setdefault(name, []).append(lineno) + + allowlisted = str(path) in DUP_NAME_ALLOWLIST + for lun, names in by_lun_name.items(): + for name, linenos in names.items(): + if len(linenos) > 1: + msg = ( + f"{path}: lun={lun} duplicate partition name '{name}' " + f"on lines {linenos}" + ) + if allowlisted: + warnings.append(f"{msg} (allowlisted)") + else: + errors.append(msg) + + return errors, warnings + + +def main() -> int: + all_errors: list[str] = [] + for path in sorted(Path("platforms").glob("*/*/partitions.conf")): + errors, warnings = check(path) + for w in warnings: + print(f"WARN: {w}", file=sys.stderr) + for e in errors: + print(f"ERROR: {e}", file=sys.stderr) + all_errors.extend(errors) + + if all_errors: + print( + f"\n{len(all_errors)} partition-configuration error(s) found.", + file=sys.stderr, + ) + return 1 + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/tests/integration/checksums.sha256 b/tests/integration/checksums.sha256 index 0a8add8..98820b4 100644 --- a/tests/integration/checksums.sha256 +++ b/tests/integration/checksums.sha256 @@ -382,16 +382,16 @@ f61da760e2f4c756dcae31caa15c8c10e7de1d4891f52010177e93bb02cc6bff platforms/iq-x f10f4221dac25b805194c19976f5a3aef26d9fe60179701439dc1379db34d90f platforms/iq-x7181-evk/nvme/wipe_rawprogram_PHY7.xml 076a27c79e5ace2a3d47f9dd2e83e4ff6ea8872b3c2218f66c92b89b55f36560 platforms/iq-x7181-evk/nvme/zeros_1sector.bin f57511198cd295e9187ab5e6153bd837c4ee91d0217ea593d6b767ca37fa74c2 platforms/iq-x7181-evk/nvme/zeros_33sectors.bin -676d2a50e70a2e59547ca65736146d12c0a28bd298e5a1d293119a0f7ecdfdc5 platforms/iq-x7181-evk/spinor/contents.xml -8ee89a96df8a7da1714c08ff22bb806239c28cab385475a1047b74ab92e9b6f1 platforms/iq-x7181-evk/spinor/gpt_backup0.bin -009de56972db81aafaba46e44887299cc01daaa04a679734b3c0b7edbba12c7e platforms/iq-x7181-evk/spinor/gpt_both0.bin +2324e4db421a0154b4e3b498005a5f6bd0ae41eedb0a6dc063ac8ffb5314bb2a platforms/iq-x7181-evk/spinor/contents.xml +51d8e3a3aabb7f72f849a0955bc5277adecb02b73250dbb932cd99316f68e9a0 platforms/iq-x7181-evk/spinor/gpt_backup0.bin +33cf115225e8abd593aecb294c446c5a76fc8031c5894d22b8019dc7527c7949 platforms/iq-x7181-evk/spinor/gpt_both0.bin 296ad8f9dac8ae490e27fc296e68de9183a83efd638e4f05404c3de700e4cc05 platforms/iq-x7181-evk/spinor/gpt_empty0.bin -0726a46092c12eec116982a88c6b44b896efab63e70b6e09a4132dad7eb5de00 platforms/iq-x7181-evk/spinor/gpt_main0.bin -45a36976e3243d52bb5edff3ca6a39da56a201fd6703f72b536c758325479288 platforms/iq-x7181-evk/spinor/partitions.xml +be9850d89e3bf8031719a1bf9e6ee2ff976e88055f8f45219ba8046ecddfdf8f platforms/iq-x7181-evk/spinor/gpt_main0.bin +3b9e6bf3eb1eec11af3b053618f404b48cb059effa1e846abe8b704336289fb1 platforms/iq-x7181-evk/spinor/partitions.xml 5e81ccbebcf2bb1ec760d4a3208e1c92972f79dac5f887b98205900681715ee9 platforms/iq-x7181-evk/spinor/patch0.xml -f8e56c6207e4f090a708570b750589bd8649572f85d57deb1f26bd099e681ab1 platforms/iq-x7181-evk/spinor/rawprogram0.xml +6c7b9b16cd75964c19babbac6eb78bf08a1b412adcc67b6644df02d4032d9eb9 platforms/iq-x7181-evk/spinor/rawprogram0.xml bfd6149fca38b0d45a636f87be864562f321e5418b917120f4f350d6f5a11a7e platforms/iq-x7181-evk/spinor/rawprogram0_BLANK_GPT.xml -dad50d1c6004812dae4927e11c82a6dc4322d4a9173592b088e84ebca050ee51 platforms/iq-x7181-evk/spinor/rawprogram0_WIPE_PARTITIONS.xml +45471cd95879e2a6cf9ce8156ddcec48263b3b79b8d685e821858b4bc4e69127 platforms/iq-x7181-evk/spinor/rawprogram0_WIPE_PARTITIONS.xml 8f4ad45a45bf96091a1bddc6e9ef9f0c1b6a8b93c4cfc9ee269d9563fdb927bf platforms/iq-x7181-evk/spinor/wipe_rawprogram_PHY0.xml c9f52ac16ce29c8c6ff84bd4d37429fb0ff049a08aedd66bebeb6163805a38e9 platforms/iq-x7181-evk/spinor/wipe_rawprogram_PHY1.xml 915acd9e9017bb6103cb0c7264b0df3c294dd4eabb4d099eda9da6df75153810 platforms/iq-x7181-evk/spinor/wipe_rawprogram_PHY2.xml