xref: /rk3399_ARM-atf/tools/sptool/hob.py (revision ee5915e2ffd4f8505b2804a5b40427a2990c5996)
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