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