1 /** @file
2   HOB Library implementation for Standalone MM Core.
3 
4 Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
5 Copyright (c) 2017 - 2018, ARM Limited. All rights reserved.<BR>
6 
7 SPDX-License-Identifier: BSD-2-Clause-Patent
8 
9 **/
10 
11 #include <PiMm.h>
12 
13 #include <Library/HobLib.h>
14 #include <Library/DebugLib.h>
15 #include <Library/BaseMemoryLib.h>
16 
17 #include <Guid/MemoryAllocationHob.h>
18 
19 //
20 // Cache copy of HobList pointer.
21 //
22 VOID *gHobList = NULL;
23 
24 /**
25   Returns the pointer to the HOB list.
26 
27   This function returns the pointer to first HOB in the list.
28   If the pointer to the HOB list is NULL, then ASSERT().
29 
30   @return The pointer to the HOB list.
31 
32 **/
33 VOID *
34 EFIAPI
GetHobList(VOID)35 GetHobList (
36   VOID
37   )
38 {
39   ASSERT (gHobList != NULL);
40   return gHobList;
41 }
42 
43 /**
44   Returns the next instance of a HOB type from the starting HOB.
45 
46   This function searches the first instance of a HOB type from the starting HOB pointer.
47   If there does not exist such HOB type from the starting HOB pointer, it will return NULL.
48   In contrast with macro GET_NEXT_HOB(), this function does not skip the starting HOB pointer
49   unconditionally: it returns HobStart back if HobStart itself meets the requirement;
50   caller is required to use GET_NEXT_HOB() if it wishes to skip current HobStart.
51 
52   If HobStart is NULL, then ASSERT().
53 
54   @param  Type          The HOB type to return.
55   @param  HobStart      The starting HOB pointer to search from.
56 
57   @return The next instance of a HOB type from the starting HOB.
58 
59 **/
60 VOID *
61 EFIAPI
GetNextHob(IN UINT16 Type,IN CONST VOID * HobStart)62 GetNextHob (
63   IN UINT16                 Type,
64   IN CONST VOID             *HobStart
65   )
66 {
67   EFI_PEI_HOB_POINTERS  Hob;
68 
69   ASSERT (HobStart != NULL);
70 
71   Hob.Raw = (UINT8 *) HobStart;
72   //
73   // Parse the HOB list until end of list or matching type is found.
74   //
75   while (!END_OF_HOB_LIST (Hob)) {
76     if (Hob.Header->HobType == Type) {
77       return Hob.Raw;
78     }
79     Hob.Raw = GET_NEXT_HOB (Hob);
80   }
81   return NULL;
82 }
83 
84 /**
85   Returns the first instance of a HOB type among the whole HOB list.
86 
87   This function searches the first instance of a HOB type among the whole HOB list.
88   If there does not exist such HOB type in the HOB list, it will return NULL.
89 
90   If the pointer to the HOB list is NULL, then ASSERT().
91 
92   @param  Type          The HOB type to return.
93 
94   @return The next instance of a HOB type from the starting HOB.
95 
96 **/
97 VOID *
98 EFIAPI
GetFirstHob(IN UINT16 Type)99 GetFirstHob (
100   IN UINT16                 Type
101   )
102 {
103   VOID      *HobList;
104 
105   HobList = GetHobList ();
106   return GetNextHob (Type, HobList);
107 }
108 
109 /**
110   Returns the next instance of the matched GUID HOB from the starting HOB.
111 
112   This function searches the first instance of a HOB from the starting HOB pointer.
113   Such HOB should satisfy two conditions:
114   its HOB type is EFI_HOB_TYPE_GUID_EXTENSION, and its GUID Name equals to the input Guid.
115   If such a HOB from the starting HOB pointer does not exist, it will return NULL.
116   Caller is required to apply GET_GUID_HOB_DATA () and GET_GUID_HOB_DATA_SIZE ()
117   to extract the data section and its size information, respectively.
118   In contrast with macro GET_NEXT_HOB(), this function does not skip the starting HOB pointer
119   unconditionally: it returns HobStart back if HobStart itself meets the requirement;
120   caller is required to use GET_NEXT_HOB() if it wishes to skip current HobStart.
121 
122   If Guid is NULL, then ASSERT().
123   If HobStart is NULL, then ASSERT().
124 
125   @param  Guid          The GUID to match with in the HOB list.
126   @param  HobStart      A pointer to a Guid.
127 
128   @return The next instance of the matched GUID HOB from the starting HOB.
129 
130 **/
131 VOID *
132 EFIAPI
GetNextGuidHob(IN CONST EFI_GUID * Guid,IN CONST VOID * HobStart)133 GetNextGuidHob (
134   IN CONST EFI_GUID         *Guid,
135   IN CONST VOID             *HobStart
136   )
137 {
138   EFI_PEI_HOB_POINTERS  GuidHob;
139 
140   GuidHob.Raw = (UINT8 *) HobStart;
141   while ((GuidHob.Raw = GetNextHob (EFI_HOB_TYPE_GUID_EXTENSION, GuidHob.Raw)) != NULL) {
142     if (CompareGuid (Guid, &GuidHob.Guid->Name)) {
143       break;
144     }
145     GuidHob.Raw = GET_NEXT_HOB (GuidHob);
146   }
147   return GuidHob.Raw;
148 }
149 
150 /**
151   Returns the first instance of the matched GUID HOB among the whole HOB list.
152 
153   This function searches the first instance of a HOB among the whole HOB list.
154   Such HOB should satisfy two conditions:
155   its HOB type is EFI_HOB_TYPE_GUID_EXTENSION and its GUID Name equals to the input Guid.
156   If such a HOB from the starting HOB pointer does not exist, it will return NULL.
157   Caller is required to apply GET_GUID_HOB_DATA () and GET_GUID_HOB_DATA_SIZE ()
158   to extract the data section and its size information, respectively.
159 
160   If the pointer to the HOB list is NULL, then ASSERT().
161   If Guid is NULL, then ASSERT().
162 
163   @param  Guid          The GUID to match with in the HOB list.
164 
165   @return The first instance of the matched GUID HOB among the whole HOB list.
166 
167 **/
168 VOID *
169 EFIAPI
GetFirstGuidHob(IN CONST EFI_GUID * Guid)170 GetFirstGuidHob (
171   IN CONST EFI_GUID         *Guid
172   )
173 {
174   VOID      *HobList;
175 
176   HobList = GetHobList ();
177   return GetNextGuidHob (Guid, HobList);
178 }
179 
180 /**
181   Get the system boot mode from the HOB list.
182 
183   This function returns the system boot mode information from the
184   PHIT HOB in HOB list.
185 
186   If the pointer to the HOB list is NULL, then ASSERT().
187 
188   @param  VOID
189 
190   @return The Boot Mode.
191 
192 **/
193 EFI_BOOT_MODE
194 EFIAPI
GetBootModeHob(VOID)195 GetBootModeHob (
196   VOID
197   )
198 {
199   EFI_HOB_HANDOFF_INFO_TABLE    *HandOffHob;
200 
201   HandOffHob = (EFI_HOB_HANDOFF_INFO_TABLE *) GetHobList ();
202 
203   return HandOffHob->BootMode;
204 }
205 
206 VOID *
CreateHob(IN UINT16 HobType,IN UINT16 HobLength)207 CreateHob (
208   IN  UINT16    HobType,
209   IN  UINT16    HobLength
210   )
211 {
212   EFI_HOB_HANDOFF_INFO_TABLE  *HandOffHob;
213   EFI_HOB_GENERIC_HEADER      *HobEnd;
214   EFI_PHYSICAL_ADDRESS        FreeMemory;
215   VOID                        *Hob;
216 
217   HandOffHob = GetHobList ();
218 
219   HobLength = (UINT16)((HobLength + 0x7) & (~0x7));
220 
221   FreeMemory = HandOffHob->EfiFreeMemoryTop - HandOffHob->EfiFreeMemoryBottom;
222 
223   if (FreeMemory < HobLength) {
224     return NULL;
225   }
226 
227   Hob = (VOID*) (UINTN) HandOffHob->EfiEndOfHobList;
228   ((EFI_HOB_GENERIC_HEADER*) Hob)->HobType = HobType;
229   ((EFI_HOB_GENERIC_HEADER*) Hob)->HobLength = HobLength;
230   ((EFI_HOB_GENERIC_HEADER*) Hob)->Reserved = 0;
231 
232   HobEnd = (EFI_HOB_GENERIC_HEADER*) ((UINTN)Hob + HobLength);
233   HandOffHob->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd;
234 
235   HobEnd->HobType   = EFI_HOB_TYPE_END_OF_HOB_LIST;
236   HobEnd->HobLength = sizeof (EFI_HOB_GENERIC_HEADER);
237   HobEnd->Reserved  = 0;
238   HobEnd++;
239   HandOffHob->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd;
240 
241   return Hob;
242 }
243 
244 /**
245   Builds a HOB for a loaded PE32 module.
246 
247   This function builds a HOB for a loaded PE32 module.
248   If ModuleName is NULL, then ASSERT().
249   If there is no additional space for HOB creation, then ASSERT().
250 
251   @param  ModuleName              The GUID File Name of the module.
252   @param  MemoryAllocationModule  The 64 bit physical address of the module.
253   @param  ModuleLength            The length of the module in bytes.
254   @param  EntryPoint              The 64 bit physical address of the module entry point.
255 
256 **/
257 VOID
258 EFIAPI
BuildModuleHob(IN CONST EFI_GUID * ModuleName,IN EFI_PHYSICAL_ADDRESS MemoryAllocationModule,IN UINT64 ModuleLength,IN EFI_PHYSICAL_ADDRESS EntryPoint)259 BuildModuleHob (
260   IN CONST EFI_GUID         *ModuleName,
261   IN EFI_PHYSICAL_ADDRESS   MemoryAllocationModule,
262   IN UINT64                 ModuleLength,
263   IN EFI_PHYSICAL_ADDRESS   EntryPoint
264   )
265 {
266   EFI_HOB_MEMORY_ALLOCATION_MODULE  *Hob;
267 
268   ASSERT (((MemoryAllocationModule & (EFI_PAGE_SIZE - 1)) == 0) &&
269           ((ModuleLength & (EFI_PAGE_SIZE - 1)) == 0));
270 
271   Hob = CreateHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, sizeof (EFI_HOB_MEMORY_ALLOCATION_MODULE));
272 
273   CopyGuid (&(Hob->MemoryAllocationHeader.Name), &gEfiHobMemoryAllocModuleGuid);
274   Hob->MemoryAllocationHeader.MemoryBaseAddress = MemoryAllocationModule;
275   Hob->MemoryAllocationHeader.MemoryLength      = ModuleLength;
276   Hob->MemoryAllocationHeader.MemoryType        = EfiBootServicesCode;
277 
278   //
279   // Zero the reserved space to match HOB spec
280   //
281   ZeroMem (Hob->MemoryAllocationHeader.Reserved, sizeof (Hob->MemoryAllocationHeader.Reserved));
282 
283   CopyGuid (&Hob->ModuleName, ModuleName);
284   Hob->EntryPoint = EntryPoint;
285 }
286 
287 /**
288   Builds a HOB that describes a chunk of system memory.
289 
290   This function builds a HOB that describes a chunk of system memory.
291   If there is no additional space for HOB creation, then ASSERT().
292 
293   @param  ResourceType        The type of resource described by this HOB.
294   @param  ResourceAttribute   The resource attributes of the memory described by this HOB.
295   @param  PhysicalStart       The 64 bit physical address of memory described by this HOB.
296   @param  NumberOfBytes       The length of the memory described by this HOB in bytes.
297 
298 **/
299 VOID
300 EFIAPI
BuildResourceDescriptorHob(IN EFI_RESOURCE_TYPE ResourceType,IN EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute,IN EFI_PHYSICAL_ADDRESS PhysicalStart,IN UINT64 NumberOfBytes)301 BuildResourceDescriptorHob (
302   IN EFI_RESOURCE_TYPE            ResourceType,
303   IN EFI_RESOURCE_ATTRIBUTE_TYPE  ResourceAttribute,
304   IN EFI_PHYSICAL_ADDRESS         PhysicalStart,
305   IN UINT64                       NumberOfBytes
306   )
307 {
308   EFI_HOB_RESOURCE_DESCRIPTOR  *Hob;
309 
310   Hob = CreateHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, sizeof (EFI_HOB_RESOURCE_DESCRIPTOR));
311   ASSERT (Hob != NULL);
312 
313   Hob->ResourceType      = ResourceType;
314   Hob->ResourceAttribute = ResourceAttribute;
315   Hob->PhysicalStart     = PhysicalStart;
316   Hob->ResourceLength    = NumberOfBytes;
317 }
318 
319 /**
320   Builds a GUID HOB with a certain data length.
321 
322   This function builds a customized HOB tagged with a GUID for identification
323   and returns the start address of GUID HOB data so that caller can fill the customized data.
324   The HOB Header and Name field is already stripped.
325   If Guid is NULL, then ASSERT().
326   If there is no additional space for HOB creation, then ASSERT().
327   If DataLength >= (0x10000 - sizeof (EFI_HOB_GUID_TYPE)), then ASSERT().
328 
329   @param  Guid          The GUID to tag the customized HOB.
330   @param  DataLength    The size of the data payload for the GUID HOB.
331 
332   @return The start address of GUID HOB data.
333 
334 **/
335 VOID *
336 EFIAPI
BuildGuidHob(IN CONST EFI_GUID * Guid,IN UINTN DataLength)337 BuildGuidHob (
338   IN CONST EFI_GUID              *Guid,
339   IN UINTN                       DataLength
340   )
341 {
342   EFI_HOB_GUID_TYPE *Hob;
343 
344   //
345   // Make sure that data length is not too long.
346   //
347   ASSERT (DataLength <= (0xffff - sizeof (EFI_HOB_GUID_TYPE)));
348 
349   Hob = CreateHob (EFI_HOB_TYPE_GUID_EXTENSION, (UINT16) (sizeof (EFI_HOB_GUID_TYPE) + DataLength));
350   CopyGuid (&Hob->Name, Guid);
351   return Hob + 1;
352 }
353 
354 
355 /**
356   Copies a data buffer to a newly-built HOB.
357 
358   This function builds a customized HOB tagged with a GUID for identification,
359   copies the input data to the HOB data field and returns the start address of the GUID HOB data.
360   The HOB Header and Name field is already stripped.
361   If Guid is NULL, then ASSERT().
362   If Data is NULL and DataLength > 0, then ASSERT().
363   If there is no additional space for HOB creation, then ASSERT().
364   If DataLength >= (0x10000 - sizeof (EFI_HOB_GUID_TYPE)), then ASSERT().
365 
366   @param  Guid          The GUID to tag the customized HOB.
367   @param  Data          The data to be copied into the data field of the GUID HOB.
368   @param  DataLength    The size of the data payload for the GUID HOB.
369 
370   @return The start address of GUID HOB data.
371 
372 **/
373 VOID *
374 EFIAPI
BuildGuidDataHob(IN CONST EFI_GUID * Guid,IN VOID * Data,IN UINTN DataLength)375 BuildGuidDataHob (
376   IN CONST EFI_GUID              *Guid,
377   IN VOID                        *Data,
378   IN UINTN                       DataLength
379   )
380 {
381   VOID  *HobData;
382 
383   ASSERT (Data != NULL || DataLength == 0);
384 
385   HobData = BuildGuidHob (Guid, DataLength);
386 
387   return CopyMem (HobData, Data, DataLength);
388 }
389 
390 /**
391   Builds a Firmware Volume HOB.
392 
393   This function builds a Firmware Volume HOB.
394   If there is no additional space for HOB creation, then ASSERT().
395 
396   @param  BaseAddress   The base address of the Firmware Volume.
397   @param  Length        The size of the Firmware Volume in bytes.
398 
399 **/
400 VOID
401 EFIAPI
BuildFvHob(IN EFI_PHYSICAL_ADDRESS BaseAddress,IN UINT64 Length)402 BuildFvHob (
403   IN EFI_PHYSICAL_ADDRESS        BaseAddress,
404   IN UINT64                      Length
405   )
406 {
407   EFI_HOB_FIRMWARE_VOLUME  *Hob;
408 
409   Hob = CreateHob (EFI_HOB_TYPE_FV, sizeof (EFI_HOB_FIRMWARE_VOLUME));
410 
411   Hob->BaseAddress = BaseAddress;
412   Hob->Length      = Length;
413 }
414 
415 
416 /**
417   Builds a EFI_HOB_TYPE_FV2 HOB.
418 
419   This function builds a EFI_HOB_TYPE_FV2 HOB.
420   If there is no additional space for HOB creation, then ASSERT().
421 
422   @param  BaseAddress   The base address of the Firmware Volume.
423   @param  Length        The size of the Firmware Volume in bytes.
424   @param  FvName       The name of the Firmware Volume.
425   @param  FileName      The name of the file.
426 
427 **/
428 VOID
429 EFIAPI
BuildFv2Hob(IN EFI_PHYSICAL_ADDRESS BaseAddress,IN UINT64 Length,IN CONST EFI_GUID * FvName,IN CONST EFI_GUID * FileName)430 BuildFv2Hob (
431   IN          EFI_PHYSICAL_ADDRESS        BaseAddress,
432   IN          UINT64                      Length,
433   IN CONST    EFI_GUID                    *FvName,
434   IN CONST    EFI_GUID                    *FileName
435   )
436 {
437   EFI_HOB_FIRMWARE_VOLUME2  *Hob;
438 
439   Hob = CreateHob (EFI_HOB_TYPE_FV2, sizeof (EFI_HOB_FIRMWARE_VOLUME2));
440 
441   Hob->BaseAddress = BaseAddress;
442   Hob->Length      = Length;
443   CopyGuid (&Hob->FvName, FvName);
444   CopyGuid (&Hob->FileName, FileName);
445 }
446 
447 
448 /**
449   Builds a HOB for the CPU.
450 
451   This function builds a HOB for the CPU.
452   If there is no additional space for HOB creation, then ASSERT().
453 
454   @param  SizeOfMemorySpace   The maximum physical memory addressability of the processor.
455   @param  SizeOfIoSpace       The maximum physical I/O addressability of the processor.
456 
457 **/
458 VOID
459 EFIAPI
BuildCpuHob(IN UINT8 SizeOfMemorySpace,IN UINT8 SizeOfIoSpace)460 BuildCpuHob (
461   IN UINT8                       SizeOfMemorySpace,
462   IN UINT8                       SizeOfIoSpace
463   )
464 {
465   EFI_HOB_CPU  *Hob;
466 
467   Hob = CreateHob (EFI_HOB_TYPE_CPU, sizeof (EFI_HOB_CPU));
468 
469   Hob->SizeOfMemorySpace = SizeOfMemorySpace;
470   Hob->SizeOfIoSpace     = SizeOfIoSpace;
471 
472   //
473   // Zero the reserved space to match HOB spec
474   //
475   ZeroMem (Hob->Reserved, sizeof (Hob->Reserved));
476 }
477 
478 /**
479   Builds a HOB for the memory allocation.
480 
481   This function builds a HOB for the memory allocation.
482   If there is no additional space for HOB creation, then ASSERT().
483 
484   @param  BaseAddress   The 64 bit physical address of the memory.
485   @param  Length        The length of the memory allocation in bytes.
486   @param  MemoryType    Type of memory allocated by this HOB.
487 
488 **/
489 VOID
490 EFIAPI
BuildMemoryAllocationHob(IN EFI_PHYSICAL_ADDRESS BaseAddress,IN UINT64 Length,IN EFI_MEMORY_TYPE MemoryType)491 BuildMemoryAllocationHob (
492   IN EFI_PHYSICAL_ADDRESS        BaseAddress,
493   IN UINT64                      Length,
494   IN EFI_MEMORY_TYPE             MemoryType
495   )
496 {
497   EFI_HOB_MEMORY_ALLOCATION  *Hob;
498 
499   ASSERT (((BaseAddress & (EFI_PAGE_SIZE - 1)) == 0) &&
500           ((Length & (EFI_PAGE_SIZE - 1)) == 0));
501 
502   Hob = CreateHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, sizeof (EFI_HOB_MEMORY_ALLOCATION));
503 
504   ZeroMem (&(Hob->AllocDescriptor.Name), sizeof (EFI_GUID));
505   Hob->AllocDescriptor.MemoryBaseAddress = BaseAddress;
506   Hob->AllocDescriptor.MemoryLength      = Length;
507   Hob->AllocDescriptor.MemoryType        = MemoryType;
508   //
509   // Zero the reserved space to match HOB spec
510   //
511   ZeroMem (Hob->AllocDescriptor.Reserved, sizeof (Hob->AllocDescriptor.Reserved));
512 }
513 
514 /**
515   Builds a HOB that describes a chunk of system memory with Owner GUID.
516 
517   This function builds a HOB that describes a chunk of system memory.
518   If there is no additional space for HOB creation, then ASSERT().
519 
520   @param  ResourceType        The type of resource described by this HOB.
521   @param  ResourceAttribute   The resource attributes of the memory described by this HOB.
522   @param  PhysicalStart       The 64 bit physical address of memory described by this HOB.
523   @param  NumberOfBytes       The length of the memory described by this HOB in bytes.
524   @param  OwnerGUID           GUID for the owner of this resource.
525 
526 **/
527 VOID
528 EFIAPI
BuildResourceDescriptorWithOwnerHob(IN EFI_RESOURCE_TYPE ResourceType,IN EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute,IN EFI_PHYSICAL_ADDRESS PhysicalStart,IN UINT64 NumberOfBytes,IN EFI_GUID * OwnerGUID)529 BuildResourceDescriptorWithOwnerHob (
530   IN EFI_RESOURCE_TYPE            ResourceType,
531   IN EFI_RESOURCE_ATTRIBUTE_TYPE  ResourceAttribute,
532   IN EFI_PHYSICAL_ADDRESS         PhysicalStart,
533   IN UINT64                       NumberOfBytes,
534   IN EFI_GUID                     *OwnerGUID
535   )
536 {
537   ASSERT (FALSE);
538 }
539 
540 /**
541   Builds a Capsule Volume HOB.
542 
543   This function builds a Capsule Volume HOB.
544   If the platform does not support Capsule Volume HOBs, then ASSERT().
545   If there is no additional space for HOB creation, then ASSERT().
546 
547   @param  BaseAddress   The base address of the Capsule Volume.
548   @param  Length        The size of the Capsule Volume in bytes.
549 
550 **/
551 VOID
552 EFIAPI
BuildCvHob(IN EFI_PHYSICAL_ADDRESS BaseAddress,IN UINT64 Length)553 BuildCvHob (
554   IN EFI_PHYSICAL_ADDRESS        BaseAddress,
555   IN UINT64                      Length
556   )
557 {
558   ASSERT (FALSE);
559 }
560 
561 
562 /**
563   Builds a HOB for the BSP store.
564 
565   This function builds a HOB for BSP store.
566   If there is no additional space for HOB creation, then ASSERT().
567 
568   @param  BaseAddress   The 64 bit physical address of the BSP.
569   @param  Length        The length of the BSP store in bytes.
570   @param  MemoryType    Type of memory allocated by this HOB.
571 
572 **/
573 VOID
574 EFIAPI
BuildBspStoreHob(IN EFI_PHYSICAL_ADDRESS BaseAddress,IN UINT64 Length,IN EFI_MEMORY_TYPE MemoryType)575 BuildBspStoreHob (
576   IN EFI_PHYSICAL_ADDRESS        BaseAddress,
577   IN UINT64                      Length,
578   IN EFI_MEMORY_TYPE             MemoryType
579   )
580 {
581   ASSERT (FALSE);
582 }
583 
584 /**
585   Builds a HOB for the Stack.
586 
587   This function builds a HOB for the stack.
588   If there is no additional space for HOB creation, then ASSERT().
589 
590   @param  BaseAddress   The 64 bit physical address of the Stack.
591   @param  Length        The length of the stack in bytes.
592 
593 **/
594 VOID
595 EFIAPI
BuildStackHob(IN EFI_PHYSICAL_ADDRESS BaseAddress,IN UINT64 Length)596 BuildStackHob (
597   IN EFI_PHYSICAL_ADDRESS        BaseAddress,
598   IN UINT64                      Length
599   )
600 {
601   ASSERT (FALSE);
602 }
603