1cc594af6SKathleen Capella#!/usr/bin/python3 2cc594af6SKathleen Capella# Copyright (c) 2025, Arm Limited. All rights reserved. 3cc594af6SKathleen Capella# 4cc594af6SKathleen Capella# SPDX-License-Identifier: BSD-3-Clause 5cc594af6SKathleen Capella 6cc594af6SKathleen Capellaimport struct 7cc594af6SKathleen Capella 8cc594af6SKathleen CapellaEFI_HOB_HANDOFF_TABLE_VERSION = 0x000A 9cc594af6SKathleen Capella 10cc594af6SKathleen CapellaPAGE_SIZE_SHIFT = 12 # TODO assuming 4K page size 11cc594af6SKathleen Capella 12cc594af6SKathleen Capella# HobType values of EFI_HOB_GENERIC_HEADER. 13cc594af6SKathleen Capella 14cc594af6SKathleen CapellaEFI_HOB_TYPE_HANDOFF = 0x0001 15cc594af6SKathleen CapellaEFI_HOB_TYPE_MEMORY_ALLOCATION = 0x0002 16cc594af6SKathleen CapellaEFI_HOB_TYPE_RESOURCE_DESCRIPTOR = 0x0003 17cc594af6SKathleen CapellaEFI_HOB_TYPE_GUID_EXTENSION = 0x0004 18cc594af6SKathleen CapellaEFI_HOB_TYPE_FV = 0x0005 19cc594af6SKathleen CapellaEFI_HOB_TYPE_CPU = 0x0006 20cc594af6SKathleen CapellaEFI_HOB_TYPE_MEMORY_POOL = 0x0007 21cc594af6SKathleen CapellaEFI_HOB_TYPE_FV2 = 0x0009 22cc594af6SKathleen CapellaEFI_HOB_TYPE_LOAD_PEIM_UNUSED = 0x000A 23cc594af6SKathleen CapellaEFI_HOB_TYPE_UEFI_CAPSULE = 0x000B 24cc594af6SKathleen CapellaEFI_HOB_TYPE_FV3 = 0x000C 25cc594af6SKathleen CapellaEFI_HOB_TYPE_UNUSED = 0xFFFE 26cc594af6SKathleen CapellaEFI_HOB_TYPE_END_OF_HOB_LIST = 0xFFFF 27cc594af6SKathleen Capella 28cc594af6SKathleen Capella# GUID values 29cc594af6SKathleen Capella"""struct efi_guid { 30cc594af6SKathleen Capella uint32_t time_low; 31cc594af6SKathleen Capella uint16_t time_mid; 32cc594af6SKathleen Capella uint16_t time_hi_and_version; 33cc594af6SKathleen Capella uint8_t clock_seq_and_node[8]; 34cc594af6SKathleen Capella}""" 35cc594af6SKathleen Capella 36cc594af6SKathleen CapellaMM_PEI_MMRAM_MEMORY_RESERVE_GUID = ( 37cc594af6SKathleen Capella 0x0703F912, 38cc594af6SKathleen Capella 0xBF8D, 39cc594af6SKathleen Capella 0x4E2A, 40cc594af6SKathleen Capella (0xBE, 0x07, 0xAB, 0x27, 0x25, 0x25, 0xC5, 0x92), 41cc594af6SKathleen Capella) 42cc594af6SKathleen CapellaMM_NS_BUFFER_GUID = ( 43cc594af6SKathleen Capella 0xF00497E3, 44cc594af6SKathleen Capella 0xBFA2, 45cc594af6SKathleen Capella 0x41A1, 46cc594af6SKathleen Capella (0x9D, 0x29, 0x54, 0xC2, 0xE9, 0x37, 0x21, 0xC5), 47cc594af6SKathleen Capella) 48cc594af6SKathleen Capella 49cc594af6SKathleen Capella# MMRAM states and capabilities 50cc594af6SKathleen Capella# See UEFI Platform Initialization Specification Version 1.8, IV-5.3.5 51cc594af6SKathleen CapellaEFI_MMRAM_OPEN = 0x00000001 52cc594af6SKathleen CapellaEFI_MMRAM_CLOSED = 0x00000002 53cc594af6SKathleen CapellaEFI_MMRAM_LOCKED = 0x00000004 54cc594af6SKathleen CapellaEFI_CACHEABLE = 0x00000008 55cc594af6SKathleen CapellaEFI_ALLOCATED = 0x00000010 56cc594af6SKathleen CapellaEFI_NEEDS_TESTING = 0x00000020 57cc594af6SKathleen CapellaEFI_NEEDS_ECC_INITIALIZATION = 0x00000040 58cc594af6SKathleen Capella 59cc594af6SKathleen CapellaEFI_SMRAM_OPEN = EFI_MMRAM_OPEN 60cc594af6SKathleen CapellaEFI_SMRAM_CLOSED = EFI_MMRAM_CLOSED 61cc594af6SKathleen CapellaEFI_SMRAM_LOCKED = EFI_MMRAM_LOCKED 62cc594af6SKathleen Capella 63cc594af6SKathleen Capella# EFI boot mode. 64cc594af6SKathleen CapellaEFI_BOOT_WITH_FULL_CONFIGURATION = 0x00 65cc594af6SKathleen CapellaEFI_BOOT_WITH_MINIMAL_CONFIGURATION = 0x01 66cc594af6SKathleen CapellaEFI_BOOT_ASSUMING_NO_CONFIGURATION_CHANGES = 0x02 67cc594af6SKathleen CapellaEFI_BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS = 0x03 68cc594af6SKathleen CapellaEFI_BOOT_WITH_DEFAULT_SETTINGS = 0x04 69cc594af6SKathleen CapellaEFI_BOOT_ON_S4_RESUME = 0x05 70cc594af6SKathleen CapellaEFI_BOOT_ON_S5_RESUME = 0x06 71cc594af6SKathleen CapellaEFI_BOOT_WITH_MFG_MODE_SETTINGS = 0x07 72cc594af6SKathleen CapellaEFI_BOOT_ON_S2_RESUME = 0x10 73cc594af6SKathleen CapellaEFI_BOOT_ON_S3_RESUME = 0x11 74cc594af6SKathleen CapellaEFI_BOOT_ON_FLASH_UPDATE = 0x12 75cc594af6SKathleen CapellaEFI_BOOT_IN_RECOVERY_MODE = 0x20 76cc594af6SKathleen Capella 77cc594af6SKathleen CapellaSTMM_BOOT_MODE = EFI_BOOT_WITH_FULL_CONFIGURATION 78cc594af6SKathleen CapellaSTMM_MMRAM_REGION_STATE_DEFAULT = EFI_CACHEABLE | EFI_ALLOCATED 79cc594af6SKathleen CapellaSTMM_MMRAM_REGION_STATE_HEAP = EFI_CACHEABLE 80cc594af6SKathleen Capella 8149c65663SKathleen Capella"""`struct` python module allows user to specify endianness. 8249c65663SKathleen CapellaWe are expecting FVP or STMM platform as target and that they will be 8349c65663SKathleen Capellalittle-endian. See `struct` python module documentation if other endianness is 8449c65663SKathleen Capellaneeded.""" 8549c65663SKathleen CapellaENDIANNESS = "<" 8649c65663SKathleen Capella 8749c65663SKathleen Capella 8849c65663SKathleen Capelladef struct_pack_with_endianness(format_str, *args): 8949c65663SKathleen Capella return struct.pack((ENDIANNESS + format_str), *args) 9049c65663SKathleen Capella 9149c65663SKathleen Capella 9249c65663SKathleen Capelladef struct_calcsize_with_endianness(format_str): 9349c65663SKathleen Capella return struct.calcsize(ENDIANNESS + format_str) 9449c65663SKathleen Capella 95cc594af6SKathleen Capella 96cc594af6SKathleen Capella# Helper for fdt node property parsing 97cc594af6SKathleen Capelladef get_integer_property_value(fdt_node, name): 98cc594af6SKathleen Capella if fdt_node.exist_property(name): 99cc594af6SKathleen Capella p = fdt_node.get_property(name) 100cc594af6SKathleen Capella 101cc594af6SKathleen Capella # <u32> Device Tree value 102cc594af6SKathleen Capella if len(p) == 1: 103cc594af6SKathleen Capella return p.value 104cc594af6SKathleen Capella # <u64> Device Tree value represented as two 32-bit values 105cc594af6SKathleen Capella if len(p) == 2: 106cc594af6SKathleen Capella msb = p[0] 107cc594af6SKathleen Capella lsb = p[1] 108cc594af6SKathleen Capella return lsb | (msb << 32) 109cc594af6SKathleen Capella return None 110cc594af6SKathleen Capella 111cc594af6SKathleen Capella 112cc594af6SKathleen Capellaclass EfiGuid: 113cc594af6SKathleen Capella """Class representing EFI GUID (Globally Unique Identifier) as described by 114cc594af6SKathleen Capella the UEFI Specification v2.10""" 115cc594af6SKathleen Capella 116cc594af6SKathleen Capella def __init__(self, time_low, time_mid, time_hi_and_version, clock_seq_and_node): 117cc594af6SKathleen Capella self.time_low = time_low 118cc594af6SKathleen Capella self.time_mid = time_mid 119cc594af6SKathleen Capella self.time_hi_and_version = time_hi_and_version 120cc594af6SKathleen Capella self.clock_seq_and_node = clock_seq_and_node 121cc594af6SKathleen Capella self.format_str = "IHH8B" 122cc594af6SKathleen Capella 123cc594af6SKathleen Capella def pack(self): 12449c65663SKathleen Capella return struct_pack_with_endianness( 125cc594af6SKathleen Capella self.format_str, 126cc594af6SKathleen Capella self.time_low, 127cc594af6SKathleen Capella self.time_mid, 128cc594af6SKathleen Capella self.time_hi_and_version, 129cc594af6SKathleen Capella *self.clock_seq_and_node, 130cc594af6SKathleen Capella ) 131cc594af6SKathleen Capella 132cc594af6SKathleen Capella def __str__(self): 133cc594af6SKathleen Capella return f"{hex(self.time_low)}, {hex(self.time_mid)}, \ 134cc594af6SKathleen Capella {hex(self.time_hi_and_version)}, {[hex(i) for i in self.clock_seq_and_node]}" 135cc594af6SKathleen Capella 136cc594af6SKathleen Capella 137cc594af6SKathleen Capellaclass HobGenericHeader: 138cc594af6SKathleen Capella """Class representing the Hob Generic Header data type as described 139cc594af6SKathleen Capella in the UEFI Platform Initialization Specification version 1.8. 140cc594af6SKathleen Capella 141cc594af6SKathleen Capella Each HOB is required to contain this header specifying the type and length 142cc594af6SKathleen Capella of the HOB. 143cc594af6SKathleen Capella """ 144cc594af6SKathleen Capella 145cc594af6SKathleen Capella def __init__(self, hob_type, hob_length): 146cc594af6SKathleen Capella self.format_str = "HHI" 147cc594af6SKathleen Capella self.hob_type = hob_type 14849c65663SKathleen Capella self.hob_length = struct_calcsize_with_endianness(self.format_str) + hob_length 149cc594af6SKathleen Capella self.reserved = 0 150cc594af6SKathleen Capella 151cc594af6SKathleen Capella def pack(self): 15249c65663SKathleen Capella return struct_pack_with_endianness( 153cc594af6SKathleen Capella self.format_str, self.hob_type, self.hob_length, self.reserved 154cc594af6SKathleen Capella ) 155cc594af6SKathleen Capella 156cc594af6SKathleen Capella def __str__(self): 157cc594af6SKathleen Capella return f"Hob Type: {self.hob_type} Hob Length: {self.hob_length}" 158cc594af6SKathleen Capella 159cc594af6SKathleen Capella 160cc594af6SKathleen Capellaclass HobGuid: 161cc594af6SKathleen Capella """Class representing the Guid Extension HOB as described in the UEFI 162cc594af6SKathleen Capella Platform Initialization Specification version 1.8. 163cc594af6SKathleen Capella 164cc594af6SKathleen Capella Allows the production of HOBs whose types are not defined by the 165cc594af6SKathleen Capella specification by generating a GUID for the HOB entry.""" 166cc594af6SKathleen Capella 167cc594af6SKathleen Capella def __init__(self, name: EfiGuid, data_format_str, data): 16849c65663SKathleen Capella hob_length = struct_calcsize_with_endianness( 16949c65663SKathleen Capella name.format_str 17049c65663SKathleen Capella ) + struct_calcsize_with_endianness(data_format_str) 171cc594af6SKathleen Capella self.header = HobGenericHeader(EFI_HOB_TYPE_GUID_EXTENSION, hob_length) 172cc594af6SKathleen Capella self.name = name 173cc594af6SKathleen Capella self.data = data 174cc594af6SKathleen Capella self.data_format_str = data_format_str 175cc594af6SKathleen Capella self.format_str = ( 176cc594af6SKathleen Capella self.header.format_str + self.name.format_str + data_format_str 177cc594af6SKathleen Capella ) 178cc594af6SKathleen Capella 179cc594af6SKathleen Capella def pack(self): 180cc594af6SKathleen Capella return ( 181cc594af6SKathleen Capella self.header.pack() 182cc594af6SKathleen Capella + self.name.pack() 18349c65663SKathleen Capella + struct_pack_with_endianness(self.data_format_str, *self.data) 184cc594af6SKathleen Capella ) 185cc594af6SKathleen Capella 186cc594af6SKathleen Capella def __str__(self): 187cc594af6SKathleen Capella return f"Header: {self.header}\n Name: {self.name}\n Data: {self.data}" 188cc594af6SKathleen Capella 189cc594af6SKathleen Capella 190cc594af6SKathleen Capellaclass HandoffInfoTable: 191cc594af6SKathleen Capella """Class representing the Handoff Info Table HOB (also known as PHIT HOB) 192cc594af6SKathleen Capella as described in the UEFI Platform Initialization Specification version 1.8. 193cc594af6SKathleen Capella 194cc594af6SKathleen Capella Must be the first HOB in the HOB list. Contains general state 195cc594af6SKathleen Capella information. 196cc594af6SKathleen Capella 197cc594af6SKathleen Capella For an SP, the range `memory_bottom` to `memory_top` will be the memory 198cc594af6SKathleen Capella range for the SP starting at the load address. `free_memory_bottom` to 199cc594af6SKathleen Capella `free_memory_top` indicates space where more HOB's could be added to the 200cc594af6SKathleen Capella HOB List.""" 201cc594af6SKathleen Capella 202cc594af6SKathleen Capella def __init__(self, memory_base, memory_size, free_memory_base, free_memory_size): 203cc594af6SKathleen Capella # header,uint32t,uint32t, uint64_t * 5 204cc594af6SKathleen Capella self.format_str = "II5Q" 20549c65663SKathleen Capella hob_length = struct_calcsize_with_endianness(self.format_str) 206cc594af6SKathleen Capella self.header = HobGenericHeader(EFI_HOB_TYPE_HANDOFF, hob_length) 207cc594af6SKathleen Capella self.version = EFI_HOB_HANDOFF_TABLE_VERSION 208cc594af6SKathleen Capella self.boot_mode = STMM_BOOT_MODE 209cc594af6SKathleen Capella self.memory_top = memory_base + memory_size 210cc594af6SKathleen Capella self.memory_bottom = memory_base 211cc594af6SKathleen Capella self.free_memory_top = free_memory_base + free_memory_size 212cc594af6SKathleen Capella self.free_memory_bottom = free_memory_base + self.header.hob_length 213cc594af6SKathleen Capella self.hob_end = None 214cc594af6SKathleen Capella 215cc594af6SKathleen Capella def set_hob_end_addr(self, hob_end_addr): 216cc594af6SKathleen Capella self.hob_end = hob_end_addr 217cc594af6SKathleen Capella 218cc594af6SKathleen Capella def set_free_memory_bottom_addr(self, addr): 219cc594af6SKathleen Capella self.free_memory_bottom = addr 220cc594af6SKathleen Capella 221cc594af6SKathleen Capella def pack(self): 22249c65663SKathleen Capella return self.header.pack() + struct_pack_with_endianness( 223cc594af6SKathleen Capella self.format_str, 224cc594af6SKathleen Capella self.version, 225cc594af6SKathleen Capella self.boot_mode, 226cc594af6SKathleen Capella self.memory_top, 227cc594af6SKathleen Capella self.memory_bottom, 228cc594af6SKathleen Capella self.free_memory_top, 229cc594af6SKathleen Capella self.free_memory_bottom, 230cc594af6SKathleen Capella self.hob_end, 231cc594af6SKathleen Capella ) 232cc594af6SKathleen Capella 233cc594af6SKathleen Capella 234cc594af6SKathleen Capellaclass FirmwareVolumeHob: 235cc594af6SKathleen Capella """Class representing the Firmware Volume HOB type as described in the 236cc594af6SKathleen Capella UEFI Platform Initialization Specification version 1.8. 237cc594af6SKathleen Capella 238cc594af6SKathleen Capella For an SP this will detail where the SP binary is located. 239cc594af6SKathleen Capella """ 240cc594af6SKathleen Capella 241cc594af6SKathleen Capella def __init__(self, base_address, img_offset, img_size): 242cc594af6SKathleen Capella # header, uint64_t, uint64_t 243cc594af6SKathleen Capella self.data_format_str = "2Q" 24449c65663SKathleen Capella hob_length = struct_calcsize_with_endianness(self.data_format_str) 245cc594af6SKathleen Capella self.header = HobGenericHeader(EFI_HOB_TYPE_FV, hob_length) 246cc594af6SKathleen Capella self.format_str = self.header.format_str + self.data_format_str 247cc594af6SKathleen Capella self.base_address = base_address + img_offset 248cc594af6SKathleen Capella self.length = img_size - img_offset 249cc594af6SKathleen Capella 250cc594af6SKathleen Capella def pack(self): 25149c65663SKathleen Capella return self.header.pack() + struct_pack_with_endianness( 252cc594af6SKathleen Capella self.data_format_str, self.base_address, self.length 253cc594af6SKathleen Capella ) 254cc594af6SKathleen Capella 255cc594af6SKathleen Capella 256cc594af6SKathleen Capellaclass EndOfHobListHob: 257cc594af6SKathleen Capella """Class representing the End of HOB List HOB type as described in the 258cc594af6SKathleen Capella UEFI Platform Initialization Specification version 1.8. 259cc594af6SKathleen Capella 260cc594af6SKathleen Capella Must be the last entry in a HOB list. 261cc594af6SKathleen Capella """ 262cc594af6SKathleen Capella 263cc594af6SKathleen Capella def __init__(self): 264cc594af6SKathleen Capella self.header = HobGenericHeader(EFI_HOB_TYPE_END_OF_HOB_LIST, 0) 265cc594af6SKathleen Capella self.format_str = "" 266cc594af6SKathleen Capella 267cc594af6SKathleen Capella def pack(self): 268cc594af6SKathleen Capella return self.header.pack() 269cc594af6SKathleen Capella 270cc594af6SKathleen Capella 271cc594af6SKathleen Capellaclass HobList: 272cc594af6SKathleen Capella """Class representing a HOB (Handoff Block list) based on the UEFI Platform 273cc594af6SKathleen Capella Initialization Sepcification version 1.8""" 274cc594af6SKathleen Capella 275cc594af6SKathleen Capella def __init__(self, phit: HandoffInfoTable): 276cc594af6SKathleen Capella if phit is None: 277cc594af6SKathleen Capella raise Exception("HobList must be initialized with valid PHIT HOB") 278cc594af6SKathleen Capella final_hob = EndOfHobListHob() 279cc594af6SKathleen Capella phit.hob_end = phit.free_memory_bottom 280cc594af6SKathleen Capella phit.free_memory_bottom += final_hob.header.hob_length 281cc594af6SKathleen Capella self.hob_list = [phit, final_hob] 282cc594af6SKathleen Capella 283cc594af6SKathleen Capella def add(self, hob): 284cc594af6SKathleen Capella if hob is not None: 285cc594af6SKathleen Capella if hob.header.hob_length > ( 286cc594af6SKathleen Capella self.get_phit().free_memory_top - self.get_phit().free_memory_bottom 287cc594af6SKathleen Capella ): 288cc594af6SKathleen Capella raise MemoryError( 289cc594af6SKathleen Capella f"Cannot add HOB of length {hob.header.hob_length}. \ 290cc594af6SKathleen Capella Resulting table size would exceed max table size of \ 291cc594af6SKathleen Capella {self.max_size}. Current table size: {self.size}." 292cc594af6SKathleen Capella ) 293cc594af6SKathleen Capella self.hob_list.insert(-1, hob) 294cc594af6SKathleen Capella self.get_phit().hob_end += hob.header.hob_length 295cc594af6SKathleen Capella self.get_phit().free_memory_bottom += hob.header.hob_length 296cc594af6SKathleen Capella 297cc594af6SKathleen Capella def get_list(self): 298cc594af6SKathleen Capella return self.hob_list 299cc594af6SKathleen Capella 300cc594af6SKathleen Capella def get_phit(self): 301cc594af6SKathleen Capella if self.hob_list is not None: 302cc594af6SKathleen Capella if type(self.hob_list[0]) is not HandoffInfoTable: 303cc594af6SKathleen Capella raise Exception("First hob in list must be of type PHIT") 304cc594af6SKathleen Capella return self.hob_list[0] 305cc594af6SKathleen Capella 306cc594af6SKathleen Capella 307cc594af6SKathleen Capelladef generate_mmram_desc(base_addr, page_count, granule, region_state): 308cc594af6SKathleen Capella physical_size = page_count << (PAGE_SIZE_SHIFT + (granule << 1)) 309cc594af6SKathleen Capella physical_start = base_addr 310cc594af6SKathleen Capella cpu_start = base_addr 311cc594af6SKathleen Capella 312cc594af6SKathleen Capella return ("4Q", (physical_start, cpu_start, physical_size, region_state)) 313cc594af6SKathleen Capella 314cc594af6SKathleen Capella 315*35530877SKathleen Capelladef generate_stmm_region_descriptor(base_addr, physical_size): 316*35530877SKathleen Capella region_state = STMM_MMRAM_REGION_STATE_DEFAULT 317*35530877SKathleen Capella physical_start = base_addr 318*35530877SKathleen Capella cpu_start = base_addr 319*35530877SKathleen Capella return ("4Q", (physical_start, cpu_start, physical_size, region_state)) 320*35530877SKathleen Capella 321*35530877SKathleen Capella 322cc594af6SKathleen Capelladef generate_ns_buffer_guid(mmram_desc): 323cc594af6SKathleen Capella return HobGuid(EfiGuid(*MM_NS_BUFFER_GUID), *mmram_desc) 324cc594af6SKathleen Capella 325cc594af6SKathleen Capella 326cc594af6SKathleen Capelladef generate_pei_mmram_memory_reserve_guid(regions): 32749c65663SKathleen Capella # uint32t n_reserved regions, 4 bytes for padding so that array is aligned, 32849c65663SKathleen Capella # array of mmram descriptors 32949c65663SKathleen Capella format_str = "I4x" 330cc594af6SKathleen Capella data = [len(regions)] 331cc594af6SKathleen Capella for desc_format_str, mmram_desc in regions: 332cc594af6SKathleen Capella format_str += desc_format_str 333cc594af6SKathleen Capella data.extend(mmram_desc) 334cc594af6SKathleen Capella guid_data = (format_str, data) 335cc594af6SKathleen Capella return HobGuid(EfiGuid(*MM_PEI_MMRAM_MEMORY_RESERVE_GUID), *guid_data) 336cc594af6SKathleen Capella 337cc594af6SKathleen Capella 338cc594af6SKathleen Capelladef generate_hob_from_fdt_node(sp_fdt, hob_offset, hob_size=None): 339cc594af6SKathleen Capella """Create a HOB list binary from an SP FDT.""" 340cc594af6SKathleen Capella fv_hob = None 341cc594af6SKathleen Capella ns_buffer_hob = None 342cc594af6SKathleen Capella mmram_reserve_hob = None 343cc594af6SKathleen Capella shared_buf_hob = None 344cc594af6SKathleen Capella 345cc594af6SKathleen Capella load_address = get_integer_property_value(sp_fdt, "load-address") 346cc594af6SKathleen Capella img_size = get_integer_property_value(sp_fdt, "image-size") 347cc594af6SKathleen Capella entrypoint_offset = get_integer_property_value(sp_fdt, "entrypoint-offset") 348cc594af6SKathleen Capella 349cc594af6SKathleen Capella if entrypoint_offset is None: 350cc594af6SKathleen Capella entrypoint_offset = 0x0 351cc594af6SKathleen Capella if hob_offset is None: 352cc594af6SKathleen Capella hob_offset = 0x0 353cc594af6SKathleen Capella if img_size is None: 354cc594af6SKathleen Capella img_size = 0x0 355cc594af6SKathleen Capella 356*35530877SKathleen Capella regions = [] 357*35530877SKathleen Capella 358*35530877SKathleen Capella # StMM requires the first memory region described in the 359*35530877SKathleen Capella # MM_PEI_MMRAM_MEMORY_RESERVE_GUID describe the full partition layout. 360*35530877SKathleen Capella regions.append(generate_stmm_region_descriptor(load_address, img_size)) 361*35530877SKathleen Capella 362cc594af6SKathleen Capella if sp_fdt.exist_node("memory-regions"): 363cc594af6SKathleen Capella if sp_fdt.exist_property("xlat-granule"): 364cc594af6SKathleen Capella granule = int(sp_fdt.get_property("xlat-granule").value) 365cc594af6SKathleen Capella else: 366cc594af6SKathleen Capella # Default granule to 4K 367cc594af6SKathleen Capella granule = 0 368cc594af6SKathleen Capella memory_regions = sp_fdt.get_node("memory-regions") 369cc594af6SKathleen Capella for node in memory_regions.nodes: 370cc594af6SKathleen Capella base_addr = get_integer_property_value(node, "base-address") 371cc594af6SKathleen Capella page_count = get_integer_property_value(node, "pages-count") 372cc594af6SKathleen Capella 373cc594af6SKathleen Capella if base_addr is None: 374cc594af6SKathleen Capella offset = get_integer_property_value( 375cc594af6SKathleen Capella node, "load-address-relative-offset" 376cc594af6SKathleen Capella ) 377cc594af6SKathleen Capella if offset is None: 378cc594af6SKathleen Capella # Cannot create memory descriptor without base address, so skip 379cc594af6SKathleen Capella # node if base address cannot be defined 380cc594af6SKathleen Capella continue 381cc594af6SKathleen Capella else: 382cc594af6SKathleen Capella base_addr = load_address + offset 383cc594af6SKathleen Capella 384cc594af6SKathleen Capella if node.name.strip() == "heap": 385cc594af6SKathleen Capella region_state = STMM_MMRAM_REGION_STATE_HEAP 386cc594af6SKathleen Capella else: 387cc594af6SKathleen Capella region_state = STMM_MMRAM_REGION_STATE_DEFAULT 388cc594af6SKathleen Capella 389cc594af6SKathleen Capella mmram_desc = generate_mmram_desc( 390cc594af6SKathleen Capella base_addr, page_count, granule, region_state 391cc594af6SKathleen Capella ) 392cc594af6SKathleen Capella 393cc594af6SKathleen Capella if node.name.strip() == "ns_comm_buffer": 394cc594af6SKathleen Capella ns_buffer_hob = generate_ns_buffer_guid(mmram_desc) 395cc594af6SKathleen Capella 396cc594af6SKathleen Capella regions.append(mmram_desc) 397cc594af6SKathleen Capella 398cc594af6SKathleen Capella mmram_reserve_hob = generate_pei_mmram_memory_reserve_guid(regions) 399cc594af6SKathleen Capella 400cc594af6SKathleen Capella fv_hob = FirmwareVolumeHob(load_address, entrypoint_offset, img_size) 401cc594af6SKathleen Capella hob_list_base = load_address + hob_offset 402cc594af6SKathleen Capella 403cc594af6SKathleen Capella # TODO assuming default of 1 page allocated for HOB List 404cc594af6SKathleen Capella if hob_size is not None: 405cc594af6SKathleen Capella max_table_size = hob_size 406cc594af6SKathleen Capella else: 407cc594af6SKathleen Capella max_table_size = 1 << PAGE_SIZE_SHIFT 408cc594af6SKathleen Capella phit = HandoffInfoTable( 409cc594af6SKathleen Capella load_address, entrypoint_offset + img_size, hob_list_base, max_table_size 410cc594af6SKathleen Capella ) 411cc594af6SKathleen Capella 412cc594af6SKathleen Capella # Create a HobList containing only PHIT and EndofHobList HOBs. 413cc594af6SKathleen Capella hob_list = HobList(phit) 414cc594af6SKathleen Capella 415cc594af6SKathleen Capella # Add HOBs to HOB list 416cc594af6SKathleen Capella if fv_hob is not None: 417cc594af6SKathleen Capella hob_list.add(fv_hob) 418cc594af6SKathleen Capella if ns_buffer_hob is not None: 419cc594af6SKathleen Capella hob_list.add(ns_buffer_hob) 420cc594af6SKathleen Capella if mmram_reserve_hob is not None: 421cc594af6SKathleen Capella hob_list.add(mmram_reserve_hob) 422cc594af6SKathleen Capella if shared_buf_hob is not None: 423cc594af6SKathleen Capella hob_list.add(shared_buf_hob) 424cc594af6SKathleen Capella 425cc594af6SKathleen Capella return hob_list 426