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