"""PMC / master register block (first-touch device). Evidence kind: **hardware register/field header + firmware use + observed access pattern.** * ``NV_PMC_BOOT_42`` lives at offset ``0xA00`` of the master (PMC) block and is read by the GSP boot code through the PRIV window at ``0x2000_0000_0000_0A00`` (observed 4-byte read, first MMIO of the real 570.144 image; the QEMU baseline faults there). * The firmware extracts bits ``28:20`` (``NV_PMC_BOOT_42_CHIP_ID``) and compares against the TU10x IDs ``0x162..0x168``; only a match continues the boot (observed branch chain at firmware vaddr ``0x4009020``). * ``NV_PMC_BOOT_42`` field layout: ARCHITECTURE ``28:24`` (TU100 = ``0x16``), IMPLEMENTATION ``23:20``, MAJOR_REVISION ``19:16``, MINOR_REVISION ``15:12``, MINOR_EXTENDED_REVISION ``11:8``, CHIP_ID ``28:20``. Only ``0xA00`` is modelled; every other offset in the window stays unhandled and is logged by the machine. """ from __future__ import annotations from .base import Device BOOT_42_OFFSET = 0xA00 CHIP_ID_SHIFT = 20 CHIP_ID_MASK = 0x1FF ARCHITECTURE_MASK = 0x1F IMPLEMENTATION_MASK = 0xF MAJOR_MASK = 0xF MINOR_MASK = 0xF MINOR_EXT_MASK = 0xF #: Chip IDs seen in the firmware's comparison chain (header field values). #: TU105 (0x165) is kept because it appears in the observed chain, but its #: product mapping is unverified. The former ``TU107 = 0x167`` entry was a #: transcription error (0x167 is TU117) and has been removed. TU102 = 0x162 TU104 = 0x164 TU105 = 0x165 # unverified product mapping (observed in the chain only) TU106 = 0x166 TU116 = 0x168 TU117 = 0x167 def boot_42_value(chip_id: int, *, major: int = 0, minor: int = 0, minor_ext: int = 0) -> int: """Assemble an ``NV_PMC_BOOT_42`` value from its documented fields. ARCHITECTURE and IMPLEMENTATION are derived from ``chip_id`` (they are the upper/lower nibbles of the same bits ``28:20``), matching the header's ``CHIP_ID_TU104 = 0x164`` / ``ARCHITECTURE_TU100 = 0x16`` pair. """ chip_id &= CHIP_ID_MASK arch = (chip_id >> 4) & ARCHITECTURE_MASK impl = chip_id & IMPLEMENTATION_MASK value = (chip_id << CHIP_ID_SHIFT) value |= (arch << 24) | (impl << 20) value |= (major & MAJOR_MASK) << 16 value |= (minor & MINOR_MASK) << 12 value |= (minor_ext & MINOR_EXT_MASK) << 8 return value class PmcBlock(Device): """Master/PMC block: ``NV_PMC_BOOT_42`` chip identification.""" name = "pmc" def __init__(self, *, chip_id: int = TU104, major: int = 0, minor: int = 0, minor_ext: int = 0, boot_42: int | None = None, base: int = 0, size: int = 0x1000): super().__init__(base=base, size=size) self.chip_id = chip_id self.boot_42 = boot_42 if boot_42 is not None else boot_42_value( chip_id, major=major, minor=minor, minor_ext=minor_ext) def read(self, offset: int, size: int) -> int | None: if offset == BOOT_42_OFFSET and size == 4: return self.boot_42 return None def peek(self, offset: int, size: int) -> int | None: return self.read(offset, size) def write(self, offset: int, size: int, value: int) -> bool: # NV_PMC_BOOT_42 is read-only (R--4R). return False def state(self) -> dict: return {"chip_id": self.chip_id, "boot_42": self.boot_42}