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