1 /** @file
2 Sample to provide FSP wrapper hob process related function.
3
4 Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
9 #include <PiPei.h>
10
11 #include <Library/PeiServicesLib.h>
12 #include <Library/PeiServicesTablePointerLib.h>
13 #include <Library/BaseLib.h>
14 #include <Library/DebugLib.h>
15 #include <Library/BaseMemoryLib.h>
16 #include <Library/HobLib.h>
17 #include <Library/PcdLib.h>
18 #include <Library/FspWrapperPlatformLib.h>
19
20 #include <Guid/GuidHobFspEas.h>
21 #include <Guid/MemoryTypeInformation.h>
22 #include <Guid/PcdDataBaseHobGuid.h>
23 #include <Ppi/Capsule.h>
24
25 //
26 // Additional pages are used by DXE memory manager.
27 // It should be consistent between RetrieveRequiredMemorySize() and GetPeiMemSize()
28 //
29 #define PEI_ADDITIONAL_MEMORY_SIZE (16 * EFI_PAGE_SIZE)
30
31 /**
32 Get the mem size in memory type information table.
33
34 @param[in] PeiServices PEI Services table.
35
36 @return the mem size in memory type information table.
37 **/
38 UINT64
GetMemorySizeInMemoryTypeInformation(IN EFI_PEI_SERVICES ** PeiServices)39 GetMemorySizeInMemoryTypeInformation (
40 IN EFI_PEI_SERVICES **PeiServices
41 )
42 {
43 EFI_STATUS Status;
44 EFI_PEI_HOB_POINTERS Hob;
45 EFI_MEMORY_TYPE_INFORMATION *MemoryData;
46 UINT8 Index;
47 UINTN TempPageNum;
48
49 MemoryData = NULL;
50 Status = (*PeiServices)->GetHobList ((CONST EFI_PEI_SERVICES**)PeiServices, (VOID **) &Hob.Raw);
51 ASSERT_EFI_ERROR (Status);
52 while (!END_OF_HOB_LIST (Hob)) {
53 if (Hob.Header->HobType == EFI_HOB_TYPE_GUID_EXTENSION &&
54 CompareGuid (&Hob.Guid->Name, &gEfiMemoryTypeInformationGuid)) {
55 MemoryData = (EFI_MEMORY_TYPE_INFORMATION *) (Hob.Raw + sizeof (EFI_HOB_GENERIC_HEADER) + sizeof (EFI_GUID));
56 break;
57 }
58
59 Hob.Raw = GET_NEXT_HOB (Hob);
60 }
61
62 if (MemoryData == NULL) {
63 return 0;
64 }
65
66 TempPageNum = 0;
67 for (Index = 0; MemoryData[Index].Type != EfiMaxMemoryType; Index++) {
68 //
69 // Accumulate default memory size requirements
70 //
71 TempPageNum += MemoryData[Index].NumberOfPages;
72 }
73
74 return TempPageNum * EFI_PAGE_SIZE;
75 }
76
77 /**
78 Get the mem size need to be reserved in PEI phase.
79
80 @param[in] PeiServices PEI Services table.
81
82 @return the mem size need to be reserved in PEI phase.
83 **/
84 UINT64
RetrieveRequiredMemorySize(IN EFI_PEI_SERVICES ** PeiServices)85 RetrieveRequiredMemorySize (
86 IN EFI_PEI_SERVICES **PeiServices
87 )
88 {
89 UINT64 Size;
90
91 Size = GetMemorySizeInMemoryTypeInformation (PeiServices);
92 return Size + PEI_ADDITIONAL_MEMORY_SIZE;
93 }
94
95 /**
96 Get the mem size need to be consumed and reserved in PEI phase.
97
98 @param[in] PeiServices PEI Services table.
99 @param[in] BootMode Current boot mode.
100
101 @return the mem size need to be consumed and reserved in PEI phase.
102 **/
103 UINT64
GetPeiMemSize(IN EFI_PEI_SERVICES ** PeiServices,IN UINT32 BootMode)104 GetPeiMemSize (
105 IN EFI_PEI_SERVICES **PeiServices,
106 IN UINT32 BootMode
107 )
108 {
109 UINT64 Size;
110 UINT64 MinSize;
111
112 if (BootMode == BOOT_IN_RECOVERY_MODE) {
113 return PcdGet32 (PcdPeiRecoveryMinMemSize);
114 }
115
116 Size = GetMemorySizeInMemoryTypeInformation (PeiServices);
117
118 if (BootMode == BOOT_ON_FLASH_UPDATE) {
119 //
120 // Maybe more size when in CapsuleUpdate phase ?
121 //
122 MinSize = PcdGet32 (PcdPeiMinMemSize);
123 } else {
124 MinSize = PcdGet32 (PcdPeiMinMemSize);
125 }
126
127 return MinSize + Size + PEI_ADDITIONAL_MEMORY_SIZE;
128 }
129
130 /**
131 Post FSP-M HOB process for Memory Resource Descriptor.
132
133 @param[in] FspHobList Pointer to the HOB data structure produced by FSP.
134
135 @return If platform process the FSP hob list successfully.
136 **/
137 EFI_STATUS
138 EFIAPI
PostFspmHobProcess(IN VOID * FspHobList)139 PostFspmHobProcess (
140 IN VOID *FspHobList
141 )
142 {
143 EFI_PEI_HOB_POINTERS Hob;
144 UINT64 LowMemorySize;
145 UINT64 FspMemorySize;
146 EFI_PHYSICAL_ADDRESS FspMemoryBase;
147 UINT64 PeiMemSize;
148 EFI_PHYSICAL_ADDRESS PeiMemBase;
149 UINT64 S3PeiMemSize;
150 EFI_PHYSICAL_ADDRESS S3PeiMemBase;
151 BOOLEAN FoundFspMemHob;
152 EFI_STATUS Status;
153 EFI_BOOT_MODE BootMode;
154 EFI_PEI_CAPSULE_PPI *Capsule;
155 VOID *CapsuleBuffer;
156 UINTN CapsuleBufferLength;
157 UINT64 RequiredMemSize;
158 EFI_PEI_SERVICES **PeiServices;
159
160 PeiServices = (EFI_PEI_SERVICES **)GetPeiServicesTablePointer ();
161
162 PeiServicesGetBootMode (&BootMode);
163
164 PeiMemBase = 0;
165 LowMemorySize = 0;
166 FspMemorySize = 0;
167 FspMemoryBase = 0;
168 FoundFspMemHob = FALSE;
169
170 //
171 // Parse the hob list from fsp
172 // Report all the resource hob except the memory between 1M and 4G
173 //
174 Hob.Raw = (UINT8 *)(UINTN)FspHobList;
175 DEBUG((DEBUG_INFO, "FspHobList - 0x%x\n", FspHobList));
176
177 while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, Hob.Raw)) != NULL) {
178 DEBUG((DEBUG_INFO, "\nResourceType: 0x%x\n", Hob.ResourceDescriptor->ResourceType));
179 if ((Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) ||
180 (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_MEMORY_RESERVED)) {
181 DEBUG((DEBUG_INFO, "ResourceAttribute: 0x%x\n", Hob.ResourceDescriptor->ResourceAttribute));
182 DEBUG((DEBUG_INFO, "PhysicalStart: 0x%x\n", Hob.ResourceDescriptor->PhysicalStart));
183 DEBUG((DEBUG_INFO, "ResourceLength: 0x%x\n", Hob.ResourceDescriptor->ResourceLength));
184 DEBUG((DEBUG_INFO, "Owner: %g\n\n", &Hob.ResourceDescriptor->Owner));
185 }
186
187 if ((Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) // Found the low memory length below 4G
188 && (Hob.ResourceDescriptor->PhysicalStart >= BASE_1MB)
189 && (Hob.ResourceDescriptor->PhysicalStart + Hob.ResourceDescriptor->ResourceLength <= BASE_4GB)) {
190 LowMemorySize += Hob.ResourceDescriptor->ResourceLength;
191 Hob.Raw = GET_NEXT_HOB (Hob);
192 continue;
193 }
194
195 if ((Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_MEMORY_RESERVED) // Found the low memory length below 4G
196 && (Hob.ResourceDescriptor->PhysicalStart >= BASE_1MB)
197 && (Hob.ResourceDescriptor->PhysicalStart + Hob.ResourceDescriptor->ResourceLength <= BASE_4GB)
198 && (CompareGuid (&Hob.ResourceDescriptor->Owner, &gFspReservedMemoryResourceHobGuid))) {
199 FoundFspMemHob = TRUE;
200 FspMemoryBase = Hob.ResourceDescriptor->PhysicalStart;
201 FspMemorySize = Hob.ResourceDescriptor->ResourceLength;
202 DEBUG((DEBUG_INFO, "Find fsp mem hob, base 0x%x, len 0x%x\n", FspMemoryBase, FspMemorySize));
203 }
204
205 //
206 // Report the resource hob
207 //
208 BuildResourceDescriptorHob (
209 Hob.ResourceDescriptor->ResourceType,
210 Hob.ResourceDescriptor->ResourceAttribute,
211 Hob.ResourceDescriptor->PhysicalStart,
212 Hob.ResourceDescriptor->ResourceLength
213 );
214
215 Hob.Raw = GET_NEXT_HOB (Hob);
216 }
217
218 if (!FoundFspMemHob) {
219 DEBUG((DEBUG_INFO, "Didn't find the fsp used memory information.\n"));
220 //ASSERT(FALSE);
221 }
222
223 DEBUG((DEBUG_INFO, "LowMemorySize: 0x%x.\n", LowMemorySize));
224 DEBUG((DEBUG_INFO, "FspMemoryBase: 0x%x.\n", FspMemoryBase));
225 DEBUG((DEBUG_INFO, "FspMemorySize: 0x%x.\n", FspMemorySize));
226
227 if (BootMode == BOOT_ON_S3_RESUME) {
228 BuildResourceDescriptorHob (
229 EFI_RESOURCE_SYSTEM_MEMORY,
230 (
231 EFI_RESOURCE_ATTRIBUTE_PRESENT |
232 EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
233 // EFI_RESOURCE_ATTRIBUTE_TESTED |
234 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
235 EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
236 EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
237 EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
238 ),
239 BASE_1MB,
240 LowMemorySize
241 );
242
243 S3PeiMemBase = 0;
244 S3PeiMemSize = 0;
245 Status = GetS3MemoryInfo (&S3PeiMemSize, &S3PeiMemBase);
246 ASSERT_EFI_ERROR (Status);
247 DEBUG((DEBUG_INFO, "S3 memory %Xh - %Xh bytes\n", S3PeiMemBase, S3PeiMemSize));
248
249 //
250 // Make sure Stack and PeiMemory are not overlap
251 //
252
253 Status = PeiServicesInstallPeiMemory (
254 S3PeiMemBase,
255 S3PeiMemSize
256 );
257 ASSERT_EFI_ERROR (Status);
258 } else {
259 PeiMemSize = GetPeiMemSize (PeiServices, BootMode);
260 DEBUG((DEBUG_INFO, "PEI memory size = %Xh bytes\n", PeiMemSize));
261
262 //
263 // Capsule mode
264 //
265 Capsule = NULL;
266 CapsuleBuffer = NULL;
267 CapsuleBufferLength = 0;
268 if (BootMode == BOOT_ON_FLASH_UPDATE) {
269 Status = PeiServicesLocatePpi (
270 &gEfiPeiCapsulePpiGuid,
271 0,
272 NULL,
273 (VOID **) &Capsule
274 );
275 ASSERT_EFI_ERROR (Status);
276
277 if (Status == EFI_SUCCESS) {
278 //
279 // Make sure Stack and CapsuleBuffer are not overlap
280 //
281 CapsuleBuffer = (VOID *)(UINTN)BASE_1MB;
282 CapsuleBufferLength = (UINTN)(LowMemorySize - PeiMemSize);
283 //
284 // Call the Capsule PPI Coalesce function to coalesce the capsule data.
285 //
286 Status = Capsule->Coalesce (PeiServices, &CapsuleBuffer, &CapsuleBufferLength);
287 }
288 }
289
290 RequiredMemSize = RetrieveRequiredMemorySize (PeiServices);
291 DEBUG((DEBUG_INFO, "Required memory size = %Xh bytes\n", RequiredMemSize));
292
293 //
294 // Report the main memory
295 //
296 BuildResourceDescriptorHob (
297 EFI_RESOURCE_SYSTEM_MEMORY,
298 (
299 EFI_RESOURCE_ATTRIBUTE_PRESENT |
300 EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
301 EFI_RESOURCE_ATTRIBUTE_TESTED |
302 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
303 EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
304 EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
305 EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
306 ),
307 BASE_1MB,
308 LowMemorySize
309 );
310
311 //
312 // Make sure Stack and CapsuleBuffer are not overlap
313 //
314
315 //
316 // Install efi memory
317 //
318 PeiMemBase = BASE_1MB + LowMemorySize - PeiMemSize;
319 Status = PeiServicesInstallPeiMemory (
320 PeiMemBase,
321 PeiMemSize - RequiredMemSize
322 );
323 ASSERT_EFI_ERROR (Status);
324
325 if (Capsule != NULL) {
326 Status = Capsule->CreateState (PeiServices, CapsuleBuffer, CapsuleBufferLength);
327 }
328 }
329
330 return EFI_SUCCESS;
331 }
332
333 /**
334 Process FSP HOB list
335
336 @param[in] FspHobList Pointer to the HOB data structure produced by FSP.
337
338 **/
339 VOID
ProcessFspHobList(IN VOID * FspHobList)340 ProcessFspHobList (
341 IN VOID *FspHobList
342 )
343 {
344 EFI_PEI_HOB_POINTERS FspHob;
345
346 FspHob.Raw = FspHobList;
347
348 //
349 // Add all the HOBs from FSP binary to FSP wrapper
350 //
351 while (!END_OF_HOB_LIST (FspHob)) {
352 if (FspHob.Header->HobType == EFI_HOB_TYPE_GUID_EXTENSION) {
353 //
354 // Skip FSP binary creates PcdDataBaseHobGuid
355 //
356 if (!CompareGuid(&FspHob.Guid->Name, &gPcdDataBaseHobGuid)) {
357 BuildGuidDataHob (
358 &FspHob.Guid->Name,
359 GET_GUID_HOB_DATA(FspHob),
360 GET_GUID_HOB_DATA_SIZE(FspHob)
361 );
362 }
363 }
364 FspHob.Raw = GET_NEXT_HOB (FspHob);
365 }
366 }
367
368 /**
369 Post FSP-S HOB process (not Memory Resource Descriptor).
370
371 @param[in] FspHobList Pointer to the HOB data structure produced by FSP.
372
373 @return If platform process the FSP hob list successfully.
374 **/
375 EFI_STATUS
376 EFIAPI
PostFspsHobProcess(IN VOID * FspHobList)377 PostFspsHobProcess (
378 IN VOID *FspHobList
379 )
380 {
381 //
382 // PostFspsHobProcess () will be called in both FSP API and Dispatch modes to
383 // align the same behavior and support a variety of boot loader implementations.
384 // Boot loader provided library function is recommended to support both API and
385 // Dispatch modes by checking PcdFspModeSelection.
386 //
387 if (PcdGet8 (PcdFspModeSelection) == 1) {
388 //
389 // Only in FSP API mode the wrapper has to build hobs basing on FSP output data.
390 // In this case FspHobList cannot be NULL.
391 //
392 ASSERT (FspHobList != NULL);
393 ProcessFspHobList (FspHobList);
394 }
395 return EFI_SUCCESS;
396 }
397