Skip to content

Commit cd97c22

Browse files
td36ChaselChiu
authored andcommitted
Platform/Intel: Create MmPlatformHobProducerLib instance
Create MmPlatformHobProducerLib instance for QSP boot. In this libarary, CreateMmPlatformHob() function is called by StandaloneMm IPL to create all Platform specific HOBs that required by Standalone MM environment. On return, a list of ResourceDescriptorHob are generated to report MMIO ranges. All memory ranges except SMRAM and EFI_RESOURCE_SYSTEM_MEMORY type memory ranges are treated as MMIO. Signed-off-by: Dun Tan <[email protected]> Cc: Ray Ni <[email protected]> Cc: Jiaxin Wu <[email protected]> Cc: Nate DeSimone <[email protected]> Cc: Star Zeng <[email protected]> Cc: Wei6 Xu <[email protected]> Cc: Yuanhao Xie <[email protected]>
1 parent 6cfae9d commit cd97c22

File tree

2 files changed

+380
-0
lines changed

2 files changed

+380
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,340 @@
1+
/** @file
2+
Instance of MM Platform HOB Producer Library Class.
3+
4+
CreateMmPlatformHob() function is called by StandaloneMm IPL to create all
5+
Platform specific HOBs that required by Standalone MM environment. In this
6+
library instance, a list of ResourceDescriptorHob are generated to report
7+
MMIO ranges. All memory ranges except SMRAM and EFI_RESOURCE_SYSTEM_MEMORY
8+
type memory ranges are treated as MMIO.
9+
10+
Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
11+
12+
SPDX-License-Identifier: BSD-2-Clause-Patent
13+
14+
**/
15+
16+
#include <Uefi.h>
17+
#include <PiPei.h>
18+
19+
#include <Library/DebugLib.h>
20+
#include <Library/BaseMemoryLib.h>
21+
#include <Library/BaseLib.h>
22+
#include <Library/MemoryAllocationLib.h>
23+
#include <Library/HobLib.h>
24+
#include <Library/MmPlatformHobProducerLib.h>
25+
26+
#include <Guid/SmramMemoryReserve.h>
27+
28+
typedef struct {
29+
EFI_PHYSICAL_ADDRESS Base;
30+
UINT64 Length;
31+
} MM_PLATFORM_MEMORY_REGION;
32+
33+
/**
34+
Initialize the EFI_HOB_GENERIC_HEADER based on input Hob.
35+
36+
@param[in] Hob Pointer to the new HOB buffer.
37+
@param[in] HobType Type of the new HOB.
38+
@param[in] HobLength Length of the new HOB to allocate.
39+
40+
**/
41+
VOID
42+
MmCreateHob (
43+
IN VOID *Hob,
44+
IN UINT16 HobType,
45+
IN UINT16 HobLength
46+
)
47+
{
48+
//
49+
// Check Length to avoid data overflow.
50+
//
51+
ASSERT (HobLength < MAX_UINT16 - 0x7);
52+
53+
((EFI_HOB_GENERIC_HEADER *)Hob)->HobType = HobType;
54+
((EFI_HOB_GENERIC_HEADER *)Hob)->HobLength = HobLength;
55+
((EFI_HOB_GENERIC_HEADER *)Hob)->Reserved = 0;
56+
}
57+
58+
/**
59+
Builds a EFI_HOB_TYPE_RESOURCE_DESCRIPTOR HOB.
60+
61+
@param[in] Hob Pointer to the new HOB buffer.
62+
@param[in] ResourceType The type of resource described by this HOB.
63+
@param[in] ResourceAttribute The resource attributes of the memory described by this HOB.
64+
@param[in] PhysicalStart The 64 bit physical address of memory described by this HOB.
65+
@param[in] NumberOfBytes The length of the memory described by this HOB in bytes.
66+
67+
**/
68+
VOID
69+
MmBuildResourceDescriptorHob (
70+
IN EFI_HOB_RESOURCE_DESCRIPTOR *Hob,
71+
IN EFI_RESOURCE_TYPE ResourceType,
72+
IN EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute,
73+
IN EFI_PHYSICAL_ADDRESS PhysicalStart,
74+
IN UINT64 NumberOfBytes
75+
)
76+
{
77+
ASSERT (Hob != NULL);
78+
MmCreateHob (Hob, EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, sizeof (EFI_HOB_RESOURCE_DESCRIPTOR));
79+
80+
Hob->ResourceType = ResourceType;
81+
Hob->ResourceAttribute = ResourceAttribute;
82+
Hob->PhysicalStart = PhysicalStart;
83+
Hob->ResourceLength = NumberOfBytes;
84+
}
85+
86+
/**
87+
Calculate the maximum support address.
88+
89+
@return the maximum support address.
90+
**/
91+
static
92+
UINT8
93+
MmCalculateMaximumSupportAddress (
94+
VOID
95+
)
96+
{
97+
UINT32 RegEax;
98+
UINT8 PhysicalAddressBits;
99+
VOID *Hob;
100+
101+
//
102+
// Get physical address bits supported.
103+
//
104+
Hob = GetFirstHob (EFI_HOB_TYPE_CPU);
105+
if (Hob != NULL) {
106+
PhysicalAddressBits = ((EFI_HOB_CPU *)Hob)->SizeOfMemorySpace;
107+
} else {
108+
AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
109+
if (RegEax >= 0x80000008) {
110+
AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);
111+
PhysicalAddressBits = (UINT8)RegEax;
112+
} else {
113+
PhysicalAddressBits = 36;
114+
}
115+
}
116+
117+
return PhysicalAddressBits;
118+
}
119+
120+
/**
121+
Builds resource HOB list for all MMIO range.
122+
123+
This function treats all all ranges outside the system memory range and smram range
124+
as mmio and builds resource HOB list for all MMIO range.
125+
126+
@param[in] Create FALSE to indicate Buffer is not used and the return buffer size
127+
is increased by the required buffer size.
128+
@param[in] MemoryRegion MM_PLATFORM_MEMORY_REGION that describes all system memory range.
129+
@param[in] Count Number of MM_PLATFORM_MEMORY_REGION.
130+
@param[in] Buffer The pointer of new HOB buffer.
131+
132+
@return The expected/used buffer size.
133+
**/
134+
UINTN
135+
MmBuildHobForMmio (
136+
IN BOOLEAN Create,
137+
IN MM_PLATFORM_MEMORY_REGION *MemoryRegion,
138+
IN UINTN Count,
139+
IN UINT8 *Buffer
140+
)
141+
{
142+
UINT64 PreviousAddress;
143+
UINT64 Base;
144+
UINT64 Limit;
145+
UINT8 PhysicalAddressBits;
146+
UINTN Index;
147+
UINTN BufferSize;
148+
149+
Index = 0;
150+
PreviousAddress = 0;
151+
PhysicalAddressBits = MmCalculateMaximumSupportAddress ();
152+
Limit = LShiftU64 (1, PhysicalAddressBits);
153+
BufferSize = 0;
154+
155+
for (Index = 0; Index <= Count; Index++) {
156+
//
157+
// When Index is equal to Count, Base covers the very last region.
158+
//
159+
Base = (Index == Count) ? Limit : MemoryRegion[Index].Base;
160+
if (Base > PreviousAddress) {
161+
if (Create) {
162+
MmBuildResourceDescriptorHob (
163+
(EFI_HOB_RESOURCE_DESCRIPTOR *)(Buffer + BufferSize),
164+
EFI_RESOURCE_MEMORY_MAPPED_IO,
165+
0,
166+
PreviousAddress,
167+
Base - PreviousAddress
168+
);
169+
}
170+
171+
BufferSize += sizeof (EFI_HOB_RESOURCE_DESCRIPTOR);
172+
}
173+
174+
if (Index < Count) {
175+
PreviousAddress = MemoryRegion[Index].Base + MemoryRegion[Index].Length;
176+
}
177+
}
178+
179+
return BufferSize;
180+
}
181+
182+
/**
183+
Function to compare 2 MM_PLATFORM_MEMORY_REGION pointer based on Base.
184+
185+
@param[in] Buffer1 pointer to MP_INFORMATION2_HOB_DATA poiner to compare
186+
@param[in] Buffer2 pointer to second MP_INFORMATION2_HOB_DATA pointer to compare
187+
188+
@retval 0 Buffer1 equal to Buffer2
189+
@retval <0 Buffer1 is less than Buffer2
190+
@retval >0 Buffer1 is greater than Buffer2
191+
**/
192+
static
193+
INTN
194+
EFIAPI
195+
MmMemoryDescriptorCompare (
196+
IN CONST VOID *Buffer1,
197+
IN CONST VOID *Buffer2
198+
)
199+
{
200+
if (((MM_PLATFORM_MEMORY_REGION *)Buffer1)->Base > ((MM_PLATFORM_MEMORY_REGION *)Buffer2)->Base) {
201+
return 1;
202+
} else if (((MM_PLATFORM_MEMORY_REGION *)Buffer1)->Base < ((MM_PLATFORM_MEMORY_REGION *)Buffer2)->Base) {
203+
return -1;
204+
}
205+
206+
return 0;
207+
}
208+
209+
/**
210+
Create the platform specific HOBs needed by the Standalone MM environment.
211+
212+
The following HOBs are created by StandaloneMm IPL common logic.
213+
Hence they should NOT be created by this function:
214+
* Single EFI_HOB_TYPE_FV to describe the Firmware Volume where MM Core resides.
215+
* Single GUIDed (gEfiSmmSmramMemoryGuid) HOB to describe the MM regions.
216+
* Single EFI_HOB_MEMORY_ALLOCATION_MODULE to describe the MM region used by MM Core.
217+
* Multiple EFI_HOB_RESOURCE_DESCRIPTOR to describe the non-MM regions and their access permissions.
218+
Note: All accessible non-MM regions should be described by EFI_HOB_RESOURCE_DESCRIPTOR HOBs.
219+
* Single GUIDed (gMmCommBufferHobGuid) HOB to identify MM Communication buffer in non-MM region.
220+
* Multiple GUIDed (gSmmBaseHobGuid) HOB to describe the SMM base address of each processor.
221+
* Multiple GUIDed (gMpInformation2HobGuid) HOB to describe the MP information.
222+
* Single GUIDed (gMmCpuSyncConfigHobGuid) HOB to describe how BSP synchronizes with APs in x86 SMM.
223+
* Single GUIDed (gMmAcpiS3EnableHobGuid) HOB to describe the ACPI S3 enable status.
224+
* Single GUIDed (gEfiAcpiVariableGuid) HOB to identify the S3 data root region in x86.
225+
* Single GUIDed (gMmProfileDataHobGuid) HOB to describe the MM profile data region.
226+
227+
@param[in] Buffer The free buffer to be used for HOB creation.
228+
@param[in, out] BufferSize The buffer size.
229+
On return, the expected/used size.
230+
231+
@retval RETURN_INVALID_PARAMETER BufferSize is NULL.
232+
@retval RETURN_INVALID_PARAMETER Buffer is NULL and BufferSize is not 0.
233+
@retval RETURN_BUFFER_TOO_SMALL The buffer is too small for HOB creation.
234+
BufferSize is updated to indicate the expected buffer size.
235+
When the input BufferSize is bigger than the expected buffer size,
236+
the BufferSize value will be changed to the used buffer size.
237+
@retval RETURN_SUCCESS The HOB list is created successfully.
238+
239+
**/
240+
EFI_STATUS
241+
EFIAPI
242+
CreateMmPlatformHob (
243+
IN VOID *Buffer,
244+
IN OUT UINTN *BufferSize
245+
)
246+
{
247+
EFI_PEI_HOB_POINTERS Hob;
248+
EFI_PEI_HOB_POINTERS FirstResHob;
249+
UINTN Count;
250+
UINTN Index;
251+
MM_PLATFORM_MEMORY_REGION *MemoryRegion;
252+
MM_PLATFORM_MEMORY_REGION SortBuffer;
253+
UINTN RequiredSize;
254+
EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *SmramHob;
255+
256+
if (BufferSize == NULL) {
257+
return RETURN_INVALID_PARAMETER;
258+
}
259+
260+
if ((*BufferSize != 0) && (Buffer == NULL)) {
261+
return RETURN_INVALID_PARAMETER;
262+
}
263+
264+
Count = 0;
265+
RequiredSize = 0;
266+
267+
//
268+
// Count the Resource HOB number
269+
//
270+
Hob.Raw = GetFirstHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR);
271+
FirstResHob = Hob;
272+
while (Hob.Raw != NULL) {
273+
if (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) {
274+
Count++;
275+
}
276+
277+
Hob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, GET_NEXT_HOB (Hob));
278+
}
279+
280+
//
281+
// Count the gEfiSmmSmramMemoryGuid Descriptor number
282+
//
283+
Hob.Raw = GetFirstGuidHob (&gEfiSmmSmramMemoryGuid);
284+
ASSERT (Hob.Raw != NULL);
285+
SmramHob = GET_GUID_HOB_DATA (Hob.Raw);
286+
Count += SmramHob->NumberOfSmmReservedRegions;
287+
288+
MemoryRegion = AllocatePool (Count * sizeof (MM_PLATFORM_MEMORY_REGION));
289+
ASSERT (MemoryRegion != NULL);
290+
291+
//
292+
// Cache gEfiSmmSmramMemoryGuid Descriptor
293+
//
294+
Index = 0;
295+
while (Index < SmramHob->NumberOfSmmReservedRegions) {
296+
MemoryRegion[Index].Base = SmramHob->Descriptor[Index].PhysicalStart;
297+
MemoryRegion[Index].Length = SmramHob->Descriptor[Index].PhysicalSize;
298+
Index++;
299+
}
300+
301+
//
302+
// Cache resource HOB
303+
//
304+
Hob = FirstResHob;
305+
while (Hob.Raw != NULL) {
306+
if (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) {
307+
MemoryRegion[Index].Base = Hob.ResourceDescriptor->PhysicalStart;
308+
MemoryRegion[Index].Length = Hob.ResourceDescriptor->ResourceLength;
309+
Index++;
310+
}
311+
312+
Hob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, GET_NEXT_HOB (Hob));
313+
}
314+
315+
ASSERT (Index == Count);
316+
317+
//
318+
// Perform QuickSort for all MM_PLATFORM_MEMORY_REGION range for calculating the MMIO
319+
//
320+
QuickSort (MemoryRegion, Count, sizeof (MM_PLATFORM_MEMORY_REGION), (BASE_SORT_COMPARE)MmMemoryDescriptorCompare, &SortBuffer);
321+
322+
//
323+
// Calculate needed buffer size.
324+
//
325+
RequiredSize = MmBuildHobForMmio (FALSE, MemoryRegion, Count, NULL);
326+
327+
if (*BufferSize < RequiredSize) {
328+
*BufferSize = RequiredSize;
329+
FreePool (MemoryRegion);
330+
return EFI_BUFFER_TOO_SMALL;
331+
}
332+
333+
//
334+
// Build resource HOB for MMIO range.
335+
//
336+
*BufferSize = MmBuildHobForMmio (TRUE, MemoryRegion, Count, Buffer);
337+
FreePool (MemoryRegion);
338+
339+
return EFI_SUCCESS;
340+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
## @file
2+
# Instance of MM Platform HOB Producer Library Class.
3+
#
4+
# Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
5+
#
6+
# SPDX-License-Identifier: BSD-2-Clause-Patent
7+
#
8+
#
9+
##
10+
11+
[Defines]
12+
INF_VERSION = 0x00010017
13+
BASE_NAME = MmPlatformHobProducerLib
14+
FILE_GUID = 98700A68-CB99-4B2A-97DC-F0A0C8755EE7
15+
MODULE_TYPE = PEIM
16+
VERSION_STRING = 1.0
17+
LIBRARY_CLASS = MmPlatformHobProducerLib
18+
19+
#
20+
# VALID_ARCHITECTURES = IA32 X64
21+
#
22+
23+
[Sources]
24+
MmPlatformHobProducerLib.c
25+
26+
[Packages]
27+
MdePkg/MdePkg.dec
28+
UefiCpuPkg/UefiCpuPkg.dec
29+
StandaloneMmPkg/StandaloneMmPkg.dec
30+
SimicsOpenBoardPkg/OpenBoardPkg.dec
31+
32+
[LibraryClasses]
33+
BaseLib
34+
BaseMemoryLib
35+
DebugLib
36+
MemoryAllocationLib
37+
HobLib
38+
39+
[Guids]
40+
gEfiSmmSmramMemoryGuid

0 commit comments

Comments
 (0)