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