1 /** @file
2   This module provide Hand-Off Block manupulation.
3 
4 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6 
7 **/
8 
9 #include "PeiMain.h"
10 
11 /**
12 
13   Gets the pointer to the HOB List.
14 
15   @param PeiServices                   An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
16   @param HobList                       Pointer to the HOB List.
17 
18   @retval EFI_SUCCESS                  Get the pointer of HOB List
19   @retval EFI_NOT_AVAILABLE_YET        the HOB List is not yet published
20   @retval EFI_INVALID_PARAMETER        HobList is NULL (in debug mode)
21 
22 **/
23 EFI_STATUS
24 EFIAPI
PeiGetHobList(IN CONST EFI_PEI_SERVICES ** PeiServices,IN OUT VOID ** HobList)25 PeiGetHobList (
26   IN CONST EFI_PEI_SERVICES  **PeiServices,
27   IN OUT VOID          **HobList
28   )
29 {
30   PEI_CORE_INSTANCE *PrivateData;
31 
32   //
33   // Only check this parameter in debug mode
34   //
35 
36   DEBUG_CODE_BEGIN ();
37     if (HobList == NULL) {
38       return EFI_INVALID_PARAMETER;
39     }
40   DEBUG_CODE_END ();
41 
42   PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);
43 
44   *HobList    = PrivateData->HobList.Raw;
45 
46   return EFI_SUCCESS;
47 }
48 
49 
50 /**
51   Add a new HOB to the HOB List.
52 
53   @param PeiServices      An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
54   @param Type             Type of the new HOB.
55   @param Length           Length of the new HOB to allocate.
56   @param Hob              Pointer to the new HOB.
57 
58   @return  EFI_SUCCESS           Success to create hob.
59   @retval  EFI_INVALID_PARAMETER if Hob is NULL
60   @retval  EFI_NOT_AVAILABLE_YET if HobList is still not available.
61   @retval  EFI_OUT_OF_RESOURCES  if there is no more memory to grow the Hoblist.
62 
63 **/
64 EFI_STATUS
65 EFIAPI
PeiCreateHob(IN CONST EFI_PEI_SERVICES ** PeiServices,IN UINT16 Type,IN UINT16 Length,IN OUT VOID ** Hob)66 PeiCreateHob (
67   IN CONST EFI_PEI_SERVICES  **PeiServices,
68   IN UINT16            Type,
69   IN UINT16            Length,
70   IN OUT VOID          **Hob
71   )
72 {
73   EFI_STATUS                           Status;
74   EFI_HOB_HANDOFF_INFO_TABLE           *HandOffHob;
75   EFI_HOB_GENERIC_HEADER               *HobEnd;
76   EFI_PHYSICAL_ADDRESS                 FreeMemory;
77 
78 
79   Status = PeiGetHobList (PeiServices, Hob);
80   if (EFI_ERROR(Status)) {
81     return Status;
82   }
83 
84   HandOffHob = *Hob;
85 
86   //
87   // Check Length to avoid data overflow.
88   //
89   if (0x10000 - Length <= 0x7) {
90     return EFI_INVALID_PARAMETER;
91   }
92   Length     = (UINT16)((Length + 0x7) & (~0x7));
93 
94   FreeMemory = HandOffHob->EfiFreeMemoryTop -
95                HandOffHob->EfiFreeMemoryBottom;
96 
97   if (FreeMemory < Length) {
98     DEBUG ((EFI_D_ERROR, "PeiCreateHob fail: Length - 0x%08x\n", (UINTN)Length));
99     DEBUG ((EFI_D_ERROR, "  FreeMemoryTop    - 0x%08x\n", (UINTN)HandOffHob->EfiFreeMemoryTop));
100     DEBUG ((EFI_D_ERROR, "  FreeMemoryBottom - 0x%08x\n", (UINTN)HandOffHob->EfiFreeMemoryBottom));
101     return EFI_OUT_OF_RESOURCES;
102   }
103 
104   *Hob = (VOID*) (UINTN) HandOffHob->EfiEndOfHobList;
105   ((EFI_HOB_GENERIC_HEADER*) *Hob)->HobType   = Type;
106   ((EFI_HOB_GENERIC_HEADER*) *Hob)->HobLength = Length;
107   ((EFI_HOB_GENERIC_HEADER*) *Hob)->Reserved  = 0;
108 
109   HobEnd = (EFI_HOB_GENERIC_HEADER*) ((UINTN) *Hob + Length);
110   HandOffHob->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd;
111 
112   HobEnd->HobType   = EFI_HOB_TYPE_END_OF_HOB_LIST;
113   HobEnd->HobLength = (UINT16) sizeof (EFI_HOB_GENERIC_HEADER);
114   HobEnd->Reserved  = 0;
115   HobEnd++;
116   HandOffHob->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd;
117 
118   return EFI_SUCCESS;
119 }
120 
121 /**
122   Install SEC HOB data to the HOB List.
123 
124   @param PeiServices    An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
125   @param SecHobList     Pointer to SEC HOB List.
126 
127   @return EFI_SUCCESS           Success to install SEC HOB data.
128   @retval EFI_OUT_OF_RESOURCES  If there is no more memory to grow the Hoblist.
129 
130 **/
131 EFI_STATUS
PeiInstallSecHobData(IN CONST EFI_PEI_SERVICES ** PeiServices,IN EFI_HOB_GENERIC_HEADER * SecHobList)132 PeiInstallSecHobData (
133   IN CONST EFI_PEI_SERVICES     **PeiServices,
134   IN EFI_HOB_GENERIC_HEADER     *SecHobList
135   )
136 {
137   EFI_STATUS                    Status;
138   EFI_HOB_HANDOFF_INFO_TABLE    *HandOffHob;
139   EFI_PEI_HOB_POINTERS          HobStart;
140   EFI_PEI_HOB_POINTERS          Hob;
141   UINTN                         SecHobListLength;
142   EFI_PHYSICAL_ADDRESS          FreeMemory;
143   EFI_HOB_GENERIC_HEADER        *HobEnd;
144 
145   HandOffHob = NULL;
146   Status = PeiGetHobList (PeiServices, (VOID **) &HandOffHob);
147   if (EFI_ERROR(Status)) {
148     return Status;
149   }
150   ASSERT (HandOffHob != NULL);
151 
152   HobStart.Raw = (UINT8 *) SecHobList;
153   //
154   // The HobList must not contain a EFI_HOB_HANDOFF_INFO_TABLE HOB (PHIT) HOB.
155   //
156   ASSERT (HobStart.Header->HobType != EFI_HOB_TYPE_HANDOFF);
157   //
158   // Calculate the SEC HOB List length,
159   // not including the terminated HOB(EFI_HOB_TYPE_END_OF_HOB_LIST).
160   //
161   for (Hob.Raw = HobStart.Raw; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob));
162   SecHobListLength = (UINTN) Hob.Raw - (UINTN) HobStart.Raw;
163   //
164   // The length must be 8-bytes aligned.
165   //
166   ASSERT ((SecHobListLength & 0x7) == 0);
167 
168   FreeMemory = HandOffHob->EfiFreeMemoryTop -
169                HandOffHob->EfiFreeMemoryBottom;
170 
171   if (FreeMemory < SecHobListLength) {
172     DEBUG ((DEBUG_ERROR, "PeiInstallSecHobData fail: SecHobListLength - 0x%08x\n", SecHobListLength));
173     DEBUG ((DEBUG_ERROR, "  FreeMemoryTop    - 0x%08x\n", (UINTN)HandOffHob->EfiFreeMemoryTop));
174     DEBUG ((DEBUG_ERROR, "  FreeMemoryBottom - 0x%08x\n", (UINTN)HandOffHob->EfiFreeMemoryBottom));
175     return EFI_OUT_OF_RESOURCES;
176   }
177 
178   Hob.Raw = (UINT8 *) (UINTN) HandOffHob->EfiEndOfHobList;
179   CopyMem (Hob.Raw, HobStart.Raw, SecHobListLength);
180 
181   HobEnd = (EFI_HOB_GENERIC_HEADER *) ((UINTN) Hob.Raw + SecHobListLength);
182   HandOffHob->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd;
183 
184   HobEnd->HobType   = EFI_HOB_TYPE_END_OF_HOB_LIST;
185   HobEnd->HobLength = (UINT16) sizeof (EFI_HOB_GENERIC_HEADER);
186   HobEnd->Reserved  = 0;
187   HobEnd++;
188   HandOffHob->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd;
189 
190   return EFI_SUCCESS;
191 }
192 
193 /**
194 
195   Builds a Handoff Information Table HOB
196 
197   @param BootMode        - Current Bootmode
198   @param MemoryBegin     - Start Memory Address.
199   @param MemoryLength    - Length of Memory.
200 
201   @return EFI_SUCCESS Always success to initialize HOB.
202 
203 **/
204 EFI_STATUS
PeiCoreBuildHobHandoffInfoTable(IN EFI_BOOT_MODE BootMode,IN EFI_PHYSICAL_ADDRESS MemoryBegin,IN UINT64 MemoryLength)205 PeiCoreBuildHobHandoffInfoTable (
206   IN EFI_BOOT_MODE         BootMode,
207   IN EFI_PHYSICAL_ADDRESS  MemoryBegin,
208   IN UINT64                MemoryLength
209   )
210 {
211   EFI_HOB_HANDOFF_INFO_TABLE   *Hob;
212   EFI_HOB_GENERIC_HEADER       *HobEnd;
213 
214   Hob                      = (VOID *)(UINTN)MemoryBegin;
215   HobEnd                   = (EFI_HOB_GENERIC_HEADER*) (Hob+1);
216   Hob->Header.HobType      = EFI_HOB_TYPE_HANDOFF;
217   Hob->Header.HobLength    = (UINT16) sizeof (EFI_HOB_HANDOFF_INFO_TABLE);
218   Hob->Header.Reserved     = 0;
219 
220   HobEnd->HobType          = EFI_HOB_TYPE_END_OF_HOB_LIST;
221   HobEnd->HobLength        = (UINT16) sizeof (EFI_HOB_GENERIC_HEADER);
222   HobEnd->Reserved         = 0;
223 
224   Hob->Version             = EFI_HOB_HANDOFF_TABLE_VERSION;
225   Hob->BootMode            = BootMode;
226 
227   Hob->EfiMemoryTop        = MemoryBegin + MemoryLength;
228   Hob->EfiMemoryBottom     = MemoryBegin;
229   Hob->EfiFreeMemoryTop    = MemoryBegin + MemoryLength;
230   Hob->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS) (UINTN) (HobEnd + 1);
231   Hob->EfiEndOfHobList     = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd;
232 
233   return EFI_SUCCESS;
234 }
235