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