]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Pei/Ppi/Ppi.c
MdeModulePkg/PeiCore: Enable T-RAM evacuation in PeiCore (CVE-2019-11098)
[mirror_edk2.git] / MdeModulePkg / Core / Pei / Ppi / Ppi.c
CommitLineData
615c6dd0 1/** @file\r
b1f6a7c6 2 EFI PEI Core PPI services\r
d1102dba 3\r
d39d1260 4Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>\r
9d510e61 5SPDX-License-Identifier: BSD-2-Clause-Patent\r
192f6d4c 6\r
b1f6a7c6 7**/\r
192f6d4c 8\r
0d516397 9#include "PeiMain.h"\r
192f6d4c 10\r
b1f6a7c6 11/**\r
12\r
e9f4a2a9 13 Migrate Pointer from the temporary memory to PEI installed memory.\r
0f9ebb32 14\r
e9f4a2a9 15 @param Pointer Pointer to the Pointer needs to be converted.\r
0f9ebb32
LG
16 @param TempBottom Base of old temporary memory\r
17 @param TempTop Top of old temporary memory\r
18 @param Offset Offset of new memory to old temporary memory.\r
d1102dba 19 @param OffsetPositive Positive flag of Offset value.\r
0f9ebb32
LG
20\r
21**/\r
22VOID\r
e9f4a2a9
SZ
23ConvertPointer (\r
24 IN OUT VOID **Pointer,\r
0f9ebb32
LG
25 IN UINTN TempBottom,\r
26 IN UINTN TempTop,\r
27 IN UINTN Offset,\r
28 IN BOOLEAN OffsetPositive\r
29 )\r
30{\r
e9f4a2a9
SZ
31 if (((UINTN) *Pointer < TempTop) &&\r
32 ((UINTN) *Pointer >= TempBottom)) {\r
0f9ebb32 33 if (OffsetPositive) {\r
e9f4a2a9 34 *Pointer = (VOID *) ((UINTN) *Pointer + Offset);\r
0f9ebb32 35 } else {\r
e9f4a2a9 36 *Pointer = (VOID *) ((UINTN) *Pointer - Offset);\r
0f9ebb32 37 }\r
e9f4a2a9
SZ
38 }\r
39}\r
0f9ebb32 40\r
e9f4a2a9 41/**\r
0f9ebb32 42\r
e9f4a2a9
SZ
43 Migrate Pointer in ranges of the temporary memory to PEI installed memory.\r
44\r
45 @param SecCoreData Points to a data structure containing SEC to PEI handoff data, such as the size\r
46 and location of temporary RAM, the stack location and the BFV location.\r
47 @param PrivateData Pointer to PeiCore's private data structure.\r
48 @param Pointer Pointer to the Pointer needs to be converted.\r
49\r
50**/\r
51VOID\r
52ConvertPointerInRanges (\r
53 IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData,\r
54 IN PEI_CORE_INSTANCE *PrivateData,\r
55 IN OUT VOID **Pointer\r
56 )\r
57{\r
58 UINT8 IndexHole;\r
0f9ebb32 59\r
e9f4a2a9 60 if (PrivateData->MemoryPages.Size != 0) {\r
0f9ebb32 61 //\r
e9f4a2a9
SZ
62 // Convert PPI pointer in old memory pages\r
63 // It needs to be done before Convert PPI pointer in old Heap\r
0f9ebb32 64 //\r
e9f4a2a9
SZ
65 ConvertPointer (\r
66 Pointer,\r
67 (UINTN)PrivateData->MemoryPages.Base,\r
68 (UINTN)PrivateData->MemoryPages.Base + PrivateData->MemoryPages.Size,\r
69 PrivateData->MemoryPages.Offset,\r
70 PrivateData->MemoryPages.OffsetPositive\r
71 );\r
72 }\r
73\r
74 //\r
75 // Convert PPI pointer in old Heap\r
76 //\r
77 ConvertPointer (\r
78 Pointer,\r
79 (UINTN)SecCoreData->PeiTemporaryRamBase,\r
80 (UINTN)SecCoreData->PeiTemporaryRamBase + SecCoreData->PeiTemporaryRamSize,\r
81 PrivateData->HeapOffset,\r
82 PrivateData->HeapOffsetPositive\r
83 );\r
84\r
85 //\r
86 // Convert PPI pointer in old Stack\r
87 //\r
88 ConvertPointer (\r
89 Pointer,\r
90 (UINTN)SecCoreData->StackBase,\r
91 (UINTN)SecCoreData->StackBase + SecCoreData->StackSize,\r
92 PrivateData->StackOffset,\r
93 PrivateData->StackOffsetPositive\r
94 );\r
95\r
96 //\r
97 // Convert PPI pointer in old TempRam Hole\r
98 //\r
99 for (IndexHole = 0; IndexHole < HOLE_MAX_NUMBER; IndexHole ++) {\r
100 if (PrivateData->HoleData[IndexHole].Size == 0) {\r
101 continue;\r
0f9ebb32 102 }\r
e9f4a2a9
SZ
103\r
104 ConvertPointer (\r
105 Pointer,\r
106 (UINTN)PrivateData->HoleData[IndexHole].Base,\r
107 (UINTN)PrivateData->HoleData[IndexHole].Base + PrivateData->HoleData[IndexHole].Size,\r
108 PrivateData->HoleData[IndexHole].Offset,\r
109 PrivateData->HoleData[IndexHole].OffsetPositive\r
110 );\r
0f9ebb32
LG
111 }\r
112}\r
113\r
e9f4a2a9
SZ
114/**\r
115\r
116 Migrate Single PPI Pointer from the temporary memory to PEI installed memory.\r
117\r
4a76d9b9 118 @param SecCoreData Points to a data structure containing SEC to PEI handoff data, such as the size\r
e9f4a2a9
SZ
119 and location of temporary RAM, the stack location and the BFV location.\r
120 @param PrivateData Pointer to PeiCore's private data structure.\r
121 @param PpiPointer Pointer to Ppi\r
122\r
123**/\r
124VOID\r
125ConvertSinglePpiPointer (\r
126 IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData,\r
127 IN PEI_CORE_INSTANCE *PrivateData,\r
128 IN PEI_PPI_LIST_POINTERS *PpiPointer\r
129 )\r
130{\r
131 //\r
132 // 1. Convert the pointer to the PPI descriptor from the old TempRam\r
133 // to the relocated physical memory.\r
134 // It (for the pointer to the PPI descriptor) needs to be done before 2 (for\r
135 // the pointer to the GUID) and 3 (for the pointer to the PPI interface structure).\r
136 //\r
137 ConvertPointerInRanges (SecCoreData, PrivateData, &PpiPointer->Raw);\r
138 //\r
139 // 2. Convert the pointer to the GUID in the PPI or NOTIFY descriptor\r
140 // from the old TempRam to the relocated physical memory.\r
141 //\r
142 ConvertPointerInRanges (SecCoreData, PrivateData, (VOID **) &PpiPointer->Ppi->Guid);\r
143 //\r
144 // 3. Convert the pointer to the PPI interface structure in the PPI descriptor\r
145 // from the old TempRam to the relocated physical memory.\r
146 //\r
147 ConvertPointerInRanges (SecCoreData, PrivateData, (VOID **) &PpiPointer->Ppi->Ppi);\r
148}\r
149\r
0f9ebb32
LG
150/**\r
151\r
b2374cec 152 Migrate PPI Pointers from the temporary memory to PEI installed memory.\r
b1f6a7c6 153\r
4a76d9b9 154 @param SecCoreData Points to a data structure containing SEC to PEI handoff data, such as the size\r
424b7c9f 155 and location of temporary RAM, the stack location and the BFV location.\r
156 @param PrivateData Pointer to PeiCore's private data structure.\r
b1f6a7c6 157\r
158**/\r
192f6d4c 159VOID\r
160ConvertPpiPointers (\r
424b7c9f 161 IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData,\r
162 IN PEI_CORE_INSTANCE *PrivateData\r
192f6d4c 163 )\r
192f6d4c 164{\r
192f6d4c 165 UINT8 Index;\r
192f6d4c 166\r
f2bc359c
SZ
167 //\r
168 // Convert normal PPIs.\r
169 //\r
170 for (Index = 0; Index < PrivateData->PpiData.PpiList.CurrentCount; Index++) {\r
171 ConvertSinglePpiPointer (\r
172 SecCoreData,\r
173 PrivateData,\r
174 &PrivateData->PpiData.PpiList.PpiPtrs[Index]\r
175 );\r
176 }\r
177\r
178 //\r
179 // Convert Callback Notification PPIs.\r
180 //\r
181 for (Index = 0; Index < PrivateData->PpiData.CallbackNotifyList.CurrentCount; Index++) {\r
182 ConvertSinglePpiPointer (\r
183 SecCoreData,\r
184 PrivateData,\r
185 &PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index]\r
186 );\r
187 }\r
188\r
189 //\r
190 // Convert Dispatch Notification PPIs.\r
191 //\r
192 for (Index = 0; Index < PrivateData->PpiData.DispatchNotifyList.CurrentCount; Index++) {\r
193 ConvertSinglePpiPointer (\r
194 SecCoreData,\r
195 PrivateData,\r
196 &PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index]\r
197 );\r
192f6d4c 198 }\r
199}\r
200\r
9bedaec0
MK
201/**\r
202\r
203 Migrate Notify Pointers inside an FV from temporary memory to permanent memory.\r
204\r
205 @param PrivateData Pointer to PeiCore's private data structure.\r
206 @param OrgFvHandle Address of FV Handle in temporary memory.\r
207 @param FvHandle Address of FV Handle in permanent memory.\r
208 @param FvSize Size of the FV.\r
209\r
210**/\r
211VOID\r
212ConvertPpiPointersFv (\r
213 IN PEI_CORE_INSTANCE *PrivateData,\r
214 IN UINTN OrgFvHandle,\r
215 IN UINTN FvHandle,\r
216 IN UINTN FvSize\r
217 )\r
218{\r
219 UINT8 Index;\r
220 UINTN Offset;\r
221 BOOLEAN OffsetPositive;\r
222 EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *FvInfoPpi;\r
223 UINT8 GuidIndex;\r
224 EFI_GUID *Guid;\r
225 EFI_GUID *GuidCheckList[2];\r
226\r
227 GuidCheckList[0] = &gEfiPeiFirmwareVolumeInfoPpiGuid;\r
228 GuidCheckList[1] = &gEfiPeiFirmwareVolumeInfo2PpiGuid;\r
229\r
230 if (FvHandle > OrgFvHandle) {\r
231 OffsetPositive = TRUE;\r
232 Offset = FvHandle - OrgFvHandle;\r
233 } else {\r
234 OffsetPositive = FALSE;\r
235 Offset = OrgFvHandle - FvHandle;\r
236 }\r
237\r
238 DEBUG ((DEBUG_VERBOSE, "Converting PPI pointers in FV.\n"));\r
239 DEBUG ((\r
240 DEBUG_VERBOSE,\r
241 " OrgFvHandle at 0x%08x. FvHandle at 0x%08x. FvSize = 0x%x\n",\r
242 (UINTN) OrgFvHandle,\r
243 (UINTN) FvHandle,\r
244 FvSize\r
245 ));\r
246 DEBUG ((\r
247 DEBUG_VERBOSE,\r
248 " OrgFvHandle range: 0x%08x - 0x%08x\n",\r
249 OrgFvHandle,\r
250 OrgFvHandle + FvSize\r
251 ));\r
252\r
253 for (Index = 0; Index < PrivateData->PpiData.CallbackNotifyList.CurrentCount; Index++) {\r
254 ConvertPointer (\r
255 (VOID **) &PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Raw,\r
256 OrgFvHandle,\r
257 OrgFvHandle + FvSize,\r
258 Offset,\r
259 OffsetPositive\r
260 );\r
261 ConvertPointer (\r
262 (VOID **) &PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Notify->Guid,\r
263 OrgFvHandle,\r
264 OrgFvHandle + FvSize,\r
265 Offset,\r
266 OffsetPositive\r
267 );\r
268 ConvertPointer (\r
269 (VOID **) &PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Notify->Notify,\r
270 OrgFvHandle,\r
271 OrgFvHandle + FvSize,\r
272 Offset,\r
273 OffsetPositive\r
274 );\r
275 }\r
276\r
277 for (Index = 0; Index < PrivateData->PpiData.DispatchNotifyList.CurrentCount; Index++) {\r
278 ConvertPointer (\r
279 (VOID **) &PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Raw,\r
280 OrgFvHandle,\r
281 OrgFvHandle + FvSize,\r
282 Offset,\r
283 OffsetPositive\r
284 );\r
285 ConvertPointer (\r
286 (VOID **) &PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Notify->Guid,\r
287 OrgFvHandle,\r
288 OrgFvHandle + FvSize,\r
289 Offset,\r
290 OffsetPositive\r
291 );\r
292 ConvertPointer (\r
293 (VOID **) &PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Notify->Notify,\r
294 OrgFvHandle,\r
295 OrgFvHandle + FvSize,\r
296 Offset,\r
297 OffsetPositive\r
298 );\r
299 }\r
300\r
301 for (Index = 0; Index < PrivateData->PpiData.PpiList.CurrentCount; Index++) {\r
302 ConvertPointer (\r
303 (VOID **) &PrivateData->PpiData.PpiList.PpiPtrs[Index].Raw,\r
304 OrgFvHandle,\r
305 OrgFvHandle + FvSize,\r
306 Offset,\r
307 OffsetPositive\r
308 );\r
309 ConvertPointer (\r
310 (VOID **) &PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi->Guid,\r
311 OrgFvHandle,\r
312 OrgFvHandle + FvSize,\r
313 Offset,\r
314 OffsetPositive\r
315 );\r
316 ConvertPointer (\r
317 (VOID **) &PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi->Ppi,\r
318 OrgFvHandle,\r
319 OrgFvHandle + FvSize,\r
320 Offset,\r
321 OffsetPositive\r
322 );\r
323\r
324 Guid = PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi->Guid;\r
325 for (GuidIndex = 0; GuidIndex < ARRAY_SIZE (GuidCheckList); ++GuidIndex) {\r
326 //\r
327 // Don't use CompareGuid function here for performance reasons.\r
328 // Instead we compare the GUID as INT32 at a time and branch\r
329 // on the first failed comparison.\r
330 //\r
331 if ((((INT32 *)Guid)[0] == ((INT32 *)GuidCheckList[GuidIndex])[0]) &&\r
332 (((INT32 *)Guid)[1] == ((INT32 *)GuidCheckList[GuidIndex])[1]) &&\r
333 (((INT32 *)Guid)[2] == ((INT32 *)GuidCheckList[GuidIndex])[2]) &&\r
334 (((INT32 *)Guid)[3] == ((INT32 *)GuidCheckList[GuidIndex])[3])) {\r
335 FvInfoPpi = PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi->Ppi;\r
336 DEBUG ((DEBUG_VERBOSE, " FvInfo: %p -> ", FvInfoPpi->FvInfo));\r
337 if ((UINTN)FvInfoPpi->FvInfo == OrgFvHandle) {\r
338 ConvertPointer (\r
339 (VOID **)&FvInfoPpi->FvInfo,\r
340 OrgFvHandle,\r
341 OrgFvHandle + FvSize,\r
342 Offset,\r
343 OffsetPositive\r
344 );\r
345 DEBUG ((DEBUG_VERBOSE, "%p", FvInfoPpi->FvInfo));\r
346 }\r
347 DEBUG ((DEBUG_VERBOSE, "\n"));\r
348 break;\r
349 }\r
350 }\r
351 }\r
352}\r
353\r
354/**\r
355\r
356 Dumps the PPI lists to debug output.\r
357\r
358 @param PrivateData Points to PeiCore's private instance data.\r
359\r
360**/\r
361VOID\r
362DumpPpiList (\r
363 IN PEI_CORE_INSTANCE *PrivateData\r
364 )\r
365{\r
366 DEBUG_CODE_BEGIN ();\r
367 UINTN Index;\r
368\r
369 if (PrivateData == NULL) {\r
370 return;\r
371 }\r
372\r
373 for (Index = 0; Index < PrivateData->PpiData.CallbackNotifyList.CurrentCount; Index++) {\r
374 DEBUG ((\r
375 DEBUG_VERBOSE,\r
376 "CallbackNotify[%2d] {%g} at 0x%x (%a)\n",\r
377 Index,\r
378 PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Notify->Guid,\r
379 (UINTN) PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Raw,\r
380 (\r
381 !(\r
382 ((EFI_PHYSICAL_ADDRESS) (UINTN) PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Raw >= PrivateData->PhysicalMemoryBegin) &&\r
383 (((EFI_PHYSICAL_ADDRESS) ((UINTN) PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Raw) + sizeof (EFI_PEI_NOTIFY_DESCRIPTOR)) < PrivateData->FreePhysicalMemoryTop)\r
384 )\r
385 ? "CAR" : "Post-Memory"\r
386 )\r
387 ));\r
388 }\r
389 for (Index = 0; Index < PrivateData->PpiData.DispatchNotifyList.CurrentCount; Index++) {\r
390 DEBUG ((DEBUG_VERBOSE,\r
391 "DispatchNotify[%2d] {%g} at 0x%x (%a)\n",\r
392 Index,\r
393 PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Notify->Guid,\r
394 (UINTN) PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Raw,\r
395 (\r
396 !(\r
397 ((EFI_PHYSICAL_ADDRESS) (UINTN) PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Raw >=PrivateData->PhysicalMemoryBegin) &&\r
398 (((EFI_PHYSICAL_ADDRESS) ((UINTN) PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Raw) + sizeof (EFI_PEI_NOTIFY_DESCRIPTOR)) < PrivateData->FreePhysicalMemoryTop)\r
399 )\r
400 ? "CAR" : "Post-Memory"\r
401 )\r
402 ));\r
403 }\r
404 for (Index = 0; Index < PrivateData->PpiData.PpiList.CurrentCount; Index++) {\r
405 DEBUG ((DEBUG_VERBOSE,\r
406 "PPI[%2d] {%g} at 0x%x (%a)\n",\r
407 Index,\r
408 PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi->Guid,\r
409 (UINTN) PrivateData->PpiData.PpiList.PpiPtrs[Index].Raw,\r
410 (\r
411 !(\r
412 ((EFI_PHYSICAL_ADDRESS) (UINTN) PrivateData->PpiData.PpiList.PpiPtrs[Index].Raw >= PrivateData->PhysicalMemoryBegin) &&\r
413 (((EFI_PHYSICAL_ADDRESS) ((UINTN) PrivateData->PpiData.PpiList.PpiPtrs[Index].Raw) + sizeof (EFI_PEI_PPI_DESCRIPTOR)) < PrivateData->FreePhysicalMemoryTop)\r
414 )\r
415 ? "CAR" : "Post-Memory"\r
416 )\r
417 ));\r
418 }\r
419 DEBUG_CODE_END ();\r
420}\r
421\r
b1f6a7c6 422/**\r
192f6d4c 423\r
d1102dba 424 This function installs an interface in the PEI PPI database by GUID.\r
0f65cdaa 425 The purpose of the service is to publish an interface that other parties\r
426 can use to call additional PEIMs.\r
192f6d4c 427\r
0f65cdaa 428 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
429 @param PpiList Pointer to a list of PEI PPI Descriptors.\r
884200f9
SZ
430 @param Single TRUE if only single entry in the PpiList.\r
431 FALSE if the PpiList is ended with an entry which has the\r
432 EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST flag set in its Flags field.\r
b1f6a7c6 433\r
0f65cdaa 434 @retval EFI_SUCCESS if all PPIs in PpiList are successfully installed.\r
435 @retval EFI_INVALID_PARAMETER if PpiList is NULL pointer\r
731bd38e 436 if any PPI in PpiList is not valid\r
0f65cdaa 437 @retval EFI_OUT_OF_RESOURCES if there is no more memory resource to install PPI\r
b1f6a7c6 438\r
439**/\r
192f6d4c 440EFI_STATUS\r
884200f9 441InternalPeiInstallPpi (\r
0c2b5da8 442 IN CONST EFI_PEI_SERVICES **PeiServices,\r
884200f9
SZ
443 IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList,\r
444 IN BOOLEAN Single\r
192f6d4c 445 )\r
192f6d4c 446{\r
f2bc359c
SZ
447 PEI_CORE_INSTANCE *PrivateData;\r
448 PEI_PPI_LIST *PpiListPointer;\r
449 UINTN Index;\r
450 UINTN LastCount;\r
451 VOID *TempPtr;\r
192f6d4c 452\r
453 if (PpiList == NULL) {\r
454 return EFI_INVALID_PARAMETER;\r
455 }\r
456\r
457 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);\r
458\r
f2bc359c
SZ
459 PpiListPointer = &PrivateData->PpiData.PpiList;\r
460 Index = PpiListPointer->CurrentCount;\r
461 LastCount = Index;\r
192f6d4c 462\r
463 //\r
464 // This is loop installs all PPI descriptors in the PpiList. It is terminated\r
465 // by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last\r
466 // EFI_PEI_PPI_DESCRIPTOR in the list.\r
467 //\r
58dcdada 468\r
192f6d4c 469 for (;;) {\r
192f6d4c 470 //\r
58dcdada 471 // Check if it is a valid PPI.\r
192f6d4c 472 // If not, rollback list to exclude all in this list.\r
473 // Try to indicate which item failed.\r
474 //\r
475 if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_PPI) == 0) {\r
f2bc359c 476 PpiListPointer->CurrentCount = LastCount;\r
0e549d5b 477 DEBUG((EFI_D_ERROR, "ERROR -> InstallPpi: %g %p\n", PpiList->Guid, PpiList->Ppi));\r
192f6d4c 478 return EFI_INVALID_PARAMETER;\r
479 }\r
480\r
f2bc359c
SZ
481 if (Index >= PpiListPointer->MaxCount) {\r
482 //\r
483 // Run out of room, grow the buffer.\r
484 //\r
485 TempPtr = AllocateZeroPool (\r
486 sizeof (PEI_PPI_LIST_POINTERS) * (PpiListPointer->MaxCount + PPI_GROWTH_STEP)\r
487 );\r
488 ASSERT (TempPtr != NULL);\r
489 CopyMem (\r
490 TempPtr,\r
491 PpiListPointer->PpiPtrs,\r
492 sizeof (PEI_PPI_LIST_POINTERS) * PpiListPointer->MaxCount\r
493 );\r
494 PpiListPointer->PpiPtrs = TempPtr;\r
495 PpiListPointer->MaxCount = PpiListPointer->MaxCount + PPI_GROWTH_STEP;\r
496 }\r
497\r
58dcdada 498 DEBUG((EFI_D_INFO, "Install PPI: %g\n", PpiList->Guid));\r
f2bc359c
SZ
499 PpiListPointer->PpiPtrs[Index].Ppi = (EFI_PEI_PPI_DESCRIPTOR *) PpiList;\r
500 Index++;\r
501 PpiListPointer->CurrentCount++;\r
58dcdada 502\r
884200f9
SZ
503 if (Single) {\r
504 //\r
505 // Only single entry in the PpiList.\r
506 //\r
507 break;\r
508 } else if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) ==\r
509 EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) {\r
510 //\r
511 // Continue until the end of the PPI List.\r
512 //\r
192f6d4c 513 break;\r
514 }\r
f2bc359c
SZ
515 //\r
516 // Go to the next descriptor.\r
517 //\r
192f6d4c 518 PpiList++;\r
192f6d4c 519 }\r
520\r
521 //\r
f2bc359c 522 // Process any callback level notifies for newly installed PPIs.\r
192f6d4c 523 //\r
f2bc359c 524 ProcessNotify (\r
b0d803fe 525 PrivateData,\r
192f6d4c 526 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,\r
f2bc359c
SZ
527 LastCount,\r
528 PpiListPointer->CurrentCount,\r
529 0,\r
530 PrivateData->PpiData.CallbackNotifyList.CurrentCount\r
192f6d4c 531 );\r
532\r
192f6d4c 533 return EFI_SUCCESS;\r
534}\r
535\r
884200f9
SZ
536/**\r
537\r
d1102dba 538 This function installs an interface in the PEI PPI database by GUID.\r
884200f9
SZ
539 The purpose of the service is to publish an interface that other parties\r
540 can use to call additional PEIMs.\r
541\r
542 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
543 @param PpiList Pointer to a list of PEI PPI Descriptors.\r
544\r
545 @retval EFI_SUCCESS if all PPIs in PpiList are successfully installed.\r
546 @retval EFI_INVALID_PARAMETER if PpiList is NULL pointer\r
547 if any PPI in PpiList is not valid\r
548 @retval EFI_OUT_OF_RESOURCES if there is no more memory resource to install PPI\r
549\r
550**/\r
551EFI_STATUS\r
552EFIAPI\r
553PeiInstallPpi (\r
554 IN CONST EFI_PEI_SERVICES **PeiServices,\r
555 IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList\r
556 )\r
557{\r
558 return InternalPeiInstallPpi (PeiServices, PpiList, FALSE);\r
559}\r
560\r
b1f6a7c6 561/**\r
562\r
d1102dba
LG
563 This function reinstalls an interface in the PEI PPI database by GUID.\r
564 The purpose of the service is to publish an interface that other parties can\r
565 use to replace an interface of the same name in the protocol database with a\r
0f65cdaa 566 different interface.\r
b1f6a7c6 567\r
0f65cdaa 568 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
569 @param OldPpi Pointer to the old PEI PPI Descriptors.\r
570 @param NewPpi Pointer to the new PEI PPI Descriptors.\r
192f6d4c 571\r
0f65cdaa 572 @retval EFI_SUCCESS if the operation was successful\r
573 @retval EFI_INVALID_PARAMETER if OldPpi or NewPpi is NULL\r
574 @retval EFI_INVALID_PARAMETER if NewPpi is not valid\r
575 @retval EFI_NOT_FOUND if the PPI was not in the database\r
b1f6a7c6 576\r
577**/\r
192f6d4c 578EFI_STATUS\r
579EFIAPI\r
580PeiReInstallPpi (\r
0c2b5da8 581 IN CONST EFI_PEI_SERVICES **PeiServices,\r
582 IN CONST EFI_PEI_PPI_DESCRIPTOR *OldPpi,\r
583 IN CONST EFI_PEI_PPI_DESCRIPTOR *NewPpi\r
192f6d4c 584 )\r
192f6d4c 585{\r
586 PEI_CORE_INSTANCE *PrivateData;\r
f2bc359c 587 UINTN Index;\r
192f6d4c 588\r
589\r
590 if ((OldPpi == NULL) || (NewPpi == NULL)) {\r
591 return EFI_INVALID_PARAMETER;\r
592 }\r
593\r
594 if ((NewPpi->Flags & EFI_PEI_PPI_DESCRIPTOR_PPI) == 0) {\r
595 return EFI_INVALID_PARAMETER;\r
596 }\r
597\r
598 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);\r
599\r
600 //\r
601 // Find the old PPI instance in the database. If we can not find it,\r
602 // return the EFI_NOT_FOUND error.\r
603 //\r
f2bc359c
SZ
604 for (Index = 0; Index < PrivateData->PpiData.PpiList.CurrentCount; Index++) {\r
605 if (OldPpi == PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi) {\r
192f6d4c 606 break;\r
607 }\r
608 }\r
f2bc359c 609 if (Index == PrivateData->PpiData.PpiList.CurrentCount) {\r
192f6d4c 610 return EFI_NOT_FOUND;\r
611 }\r
612\r
613 //\r
f2bc359c 614 // Replace the old PPI with the new one.\r
58dcdada 615 //\r
192f6d4c 616 DEBUG((EFI_D_INFO, "Reinstall PPI: %g\n", NewPpi->Guid));\r
f2bc359c 617 PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi = (EFI_PEI_PPI_DESCRIPTOR *) NewPpi;\r
192f6d4c 618\r
619 //\r
f2bc359c 620 // Process any callback level notifies for the newly installed PPI.\r
192f6d4c 621 //\r
f2bc359c 622 ProcessNotify (\r
b0d803fe 623 PrivateData,\r
192f6d4c 624 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,\r
625 Index,\r
626 Index+1,\r
f2bc359c
SZ
627 0,\r
628 PrivateData->PpiData.CallbackNotifyList.CurrentCount\r
192f6d4c 629 );\r
630\r
192f6d4c 631 return EFI_SUCCESS;\r
632}\r
633\r
b1f6a7c6 634/**\r
635\r
636 Locate a given named PPI.\r
637\r
192f6d4c 638\r
0f65cdaa 639 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
640 @param Guid Pointer to GUID of the PPI.\r
641 @param Instance Instance Number to discover.\r
642 @param PpiDescriptor Pointer to reference the found descriptor. If not NULL,\r
643 returns a pointer to the descriptor (includes flags, etc)\r
644 @param Ppi Pointer to reference the found PPI\r
b1f6a7c6 645\r
646 @retval EFI_SUCCESS if the PPI is in the database\r
647 @retval EFI_NOT_FOUND if the PPI is not in the database\r
648\r
649**/\r
192f6d4c 650EFI_STATUS\r
651EFIAPI\r
652PeiLocatePpi (\r
0c2b5da8 653 IN CONST EFI_PEI_SERVICES **PeiServices,\r
654 IN CONST EFI_GUID *Guid,\r
0f65cdaa 655 IN UINTN Instance,\r
656 IN OUT EFI_PEI_PPI_DESCRIPTOR **PpiDescriptor,\r
657 IN OUT VOID **Ppi\r
192f6d4c 658 )\r
192f6d4c 659{\r
f2bc359c
SZ
660 PEI_CORE_INSTANCE *PrivateData;\r
661 UINTN Index;\r
662 EFI_GUID *CheckGuid;\r
663 EFI_PEI_PPI_DESCRIPTOR *TempPtr;\r
192f6d4c 664\r
58dcdada 665\r
192f6d4c 666 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);\r
667\r
668 //\r
669 // Search the data base for the matching instance of the GUIDed PPI.\r
670 //\r
f2bc359c
SZ
671 for (Index = 0; Index < PrivateData->PpiData.PpiList.CurrentCount; Index++) {\r
672 TempPtr = PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi;\r
192f6d4c 673 CheckGuid = TempPtr->Guid;\r
674\r
675 //\r
676 // Don't use CompareGuid function here for performance reasons.\r
677 // Instead we compare the GUID as INT32 at a time and branch\r
678 // on the first failed comparison.\r
679 //\r
680 if ((((INT32 *)Guid)[0] == ((INT32 *)CheckGuid)[0]) &&\r
681 (((INT32 *)Guid)[1] == ((INT32 *)CheckGuid)[1]) &&\r
682 (((INT32 *)Guid)[2] == ((INT32 *)CheckGuid)[2]) &&\r
683 (((INT32 *)Guid)[3] == ((INT32 *)CheckGuid)[3])) {\r
684 if (Instance == 0) {\r
685\r
686 if (PpiDescriptor != NULL) {\r
687 *PpiDescriptor = TempPtr;\r
688 }\r
689\r
690 if (Ppi != NULL) {\r
691 *Ppi = TempPtr->Ppi;\r
692 }\r
693\r
694\r
695 return EFI_SUCCESS;\r
696 }\r
697 Instance--;\r
698 }\r
699 }\r
700\r
701 return EFI_NOT_FOUND;\r
702}\r
703\r
b1f6a7c6 704/**\r
192f6d4c 705\r
d1102dba
LG
706 This function installs a notification service to be called back when a given\r
707 interface is installed or reinstalled. The purpose of the service is to publish\r
0f65cdaa 708 an interface that other parties can use to call additional PPIs that may materialize later.\r
b1f6a7c6 709\r
0f65cdaa 710 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
711 @param NotifyList Pointer to list of Descriptors to notify upon.\r
884200f9
SZ
712 @param Single TRUE if only single entry in the NotifyList.\r
713 FALSE if the NotifyList is ended with an entry which has the\r
714 EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST flag set in its Flags field.\r
b1f6a7c6 715\r
716 @retval EFI_SUCCESS if successful\r
717 @retval EFI_OUT_OF_RESOURCES if no space in the database\r
884200f9 718 @retval EFI_INVALID_PARAMETER if not a good descriptor\r
b1f6a7c6 719\r
720**/\r
192f6d4c 721EFI_STATUS\r
884200f9 722InternalPeiNotifyPpi (\r
0c2b5da8 723 IN CONST EFI_PEI_SERVICES **PeiServices,\r
884200f9
SZ
724 IN CONST EFI_PEI_NOTIFY_DESCRIPTOR *NotifyList,\r
725 IN BOOLEAN Single\r
192f6d4c 726 )\r
192f6d4c 727{\r
f2bc359c
SZ
728 PEI_CORE_INSTANCE *PrivateData;\r
729 PEI_CALLBACK_NOTIFY_LIST *CallbackNotifyListPointer;\r
730 UINTN CallbackNotifyIndex;\r
731 UINTN LastCallbackNotifyCount;\r
732 PEI_DISPATCH_NOTIFY_LIST *DispatchNotifyListPointer;\r
733 UINTN DispatchNotifyIndex;\r
734 UINTN LastDispatchNotifyCount;\r
735 VOID *TempPtr;\r
192f6d4c 736\r
737 if (NotifyList == NULL) {\r
738 return EFI_INVALID_PARAMETER;\r
739 }\r
740\r
741 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);\r
742\r
f2bc359c
SZ
743 CallbackNotifyListPointer = &PrivateData->PpiData.CallbackNotifyList;\r
744 CallbackNotifyIndex = CallbackNotifyListPointer->CurrentCount;\r
745 LastCallbackNotifyCount = CallbackNotifyIndex;\r
746\r
747 DispatchNotifyListPointer = &PrivateData->PpiData.DispatchNotifyList;\r
748 DispatchNotifyIndex = DispatchNotifyListPointer->CurrentCount;\r
749 LastDispatchNotifyCount = DispatchNotifyIndex;\r
192f6d4c 750\r
751 //\r
752 // This is loop installs all Notify descriptors in the NotifyList. It is\r
753 // terminated by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last\r
754 // EFI_PEI_NOTIFY_DESCRIPTOR in the list.\r
755 //\r
756\r
757 for (;;) {\r
192f6d4c 758 //\r
759 // If some of the PPI data is invalid restore original Notify PPI database value\r
760 //\r
761 if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_TYPES) == 0) {\r
f2bc359c
SZ
762 CallbackNotifyListPointer->CurrentCount = LastCallbackNotifyCount;\r
763 DispatchNotifyListPointer->CurrentCount = LastDispatchNotifyCount;\r
764 DEBUG((DEBUG_ERROR, "ERROR -> NotifyPpi: %g %p\n", NotifyList->Guid, NotifyList->Notify));\r
192f6d4c 765 return EFI_INVALID_PARAMETER;\r
766 }\r
58dcdada 767\r
f2bc359c
SZ
768 if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK) != 0) {\r
769 if (CallbackNotifyIndex >= CallbackNotifyListPointer->MaxCount) {\r
770 //\r
771 // Run out of room, grow the buffer.\r
772 //\r
773 TempPtr = AllocateZeroPool (\r
774 sizeof (PEI_PPI_LIST_POINTERS) * (CallbackNotifyListPointer->MaxCount + CALLBACK_NOTIFY_GROWTH_STEP)\r
775 );\r
776 ASSERT (TempPtr != NULL);\r
777 CopyMem (\r
778 TempPtr,\r
779 CallbackNotifyListPointer->NotifyPtrs,\r
780 sizeof (PEI_PPI_LIST_POINTERS) * CallbackNotifyListPointer->MaxCount\r
781 );\r
782 CallbackNotifyListPointer->NotifyPtrs = TempPtr;\r
783 CallbackNotifyListPointer->MaxCount = CallbackNotifyListPointer->MaxCount + CALLBACK_NOTIFY_GROWTH_STEP;\r
784 }\r
785 CallbackNotifyListPointer->NotifyPtrs[CallbackNotifyIndex].Notify = (EFI_PEI_NOTIFY_DESCRIPTOR *) NotifyList;\r
786 CallbackNotifyIndex++;\r
787 CallbackNotifyListPointer->CurrentCount++;\r
788 } else {\r
789 if (DispatchNotifyIndex >= DispatchNotifyListPointer->MaxCount) {\r
790 //\r
791 // Run out of room, grow the buffer.\r
792 //\r
793 TempPtr = AllocateZeroPool (\r
794 sizeof (PEI_PPI_LIST_POINTERS) * (DispatchNotifyListPointer->MaxCount + DISPATCH_NOTIFY_GROWTH_STEP)\r
795 );\r
796 ASSERT (TempPtr != NULL);\r
797 CopyMem (\r
798 TempPtr,\r
799 DispatchNotifyListPointer->NotifyPtrs,\r
800 sizeof (PEI_PPI_LIST_POINTERS) * DispatchNotifyListPointer->MaxCount\r
801 );\r
802 DispatchNotifyListPointer->NotifyPtrs = TempPtr;\r
803 DispatchNotifyListPointer->MaxCount = DispatchNotifyListPointer->MaxCount + DISPATCH_NOTIFY_GROWTH_STEP;\r
804 }\r
805 DispatchNotifyListPointer->NotifyPtrs[DispatchNotifyIndex].Notify = (EFI_PEI_NOTIFY_DESCRIPTOR *) NotifyList;\r
806 DispatchNotifyIndex++;\r
807 DispatchNotifyListPointer->CurrentCount++;\r
58dcdada 808 }\r
809\r
192f6d4c 810 DEBUG((EFI_D_INFO, "Register PPI Notify: %g\n", NotifyList->Guid));\r
f2bc359c 811\r
884200f9
SZ
812 if (Single) {\r
813 //\r
814 // Only single entry in the NotifyList.\r
815 //\r
816 break;\r
817 } else if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) ==\r
818 EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) {\r
819 //\r
820 // Continue until the end of the Notify List.\r
821 //\r
192f6d4c 822 break;\r
823 }\r
824 //\r
f2bc359c 825 // Go to the next descriptor.\r
192f6d4c 826 //\r
827 NotifyList++;\r
192f6d4c 828 }\r
58dcdada 829\r
192f6d4c 830 //\r
f2bc359c 831 // Process any callback level notifies for all previously installed PPIs.\r
192f6d4c 832 //\r
f2bc359c 833 ProcessNotify (\r
b0d803fe 834 PrivateData,\r
192f6d4c 835 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,\r
836 0,\r
f2bc359c
SZ
837 PrivateData->PpiData.PpiList.CurrentCount,\r
838 LastCallbackNotifyCount,\r
839 CallbackNotifyListPointer->CurrentCount\r
192f6d4c 840 );\r
58dcdada 841\r
192f6d4c 842 return EFI_SUCCESS;\r
843}\r
844\r
884200f9
SZ
845/**\r
846\r
d1102dba
LG
847 This function installs a notification service to be called back when a given\r
848 interface is installed or reinstalled. The purpose of the service is to publish\r
884200f9
SZ
849 an interface that other parties can use to call additional PPIs that may materialize later.\r
850\r
851 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
852 @param NotifyList Pointer to list of Descriptors to notify upon.\r
853\r
854 @retval EFI_SUCCESS if successful\r
855 @retval EFI_OUT_OF_RESOURCES if no space in the database\r
856 @retval EFI_INVALID_PARAMETER if not a good descriptor\r
857\r
858**/\r
859EFI_STATUS\r
860EFIAPI\r
861PeiNotifyPpi (\r
862 IN CONST EFI_PEI_SERVICES **PeiServices,\r
863 IN CONST EFI_PEI_NOTIFY_DESCRIPTOR *NotifyList\r
864 )\r
865{\r
866 return InternalPeiNotifyPpi (PeiServices, NotifyList, FALSE);\r
867}\r
868\r
b1f6a7c6 869/**\r
192f6d4c 870\r
871 Process the Notify List at dispatch level.\r
872\r
b1f6a7c6 873 @param PrivateData PeiCore's private data structure.\r
192f6d4c 874\r
b1f6a7c6 875**/\r
876VOID\r
f2bc359c 877ProcessDispatchNotifyList (\r
b1f6a7c6 878 IN PEI_CORE_INSTANCE *PrivateData\r
879 )\r
192f6d4c 880{\r
f2bc359c 881 UINTN TempValue;\r
58dcdada 882\r
192f6d4c 883 while (TRUE) {\r
884 //\r
885 // Check if the PEIM that was just dispatched resulted in any\r
886 // Notifies getting installed. If so, go process any dispatch\r
d39d1260 887 // level Notifies that match the previously installed PPIs.\r
f2bc359c
SZ
888 // Use "while" instead of "if" since ProcessNotify can modify\r
889 // DispatchNotifyList.CurrentCount (with NotifyPpi) so we have\r
890 // to iterate until the same.\r
192f6d4c 891 //\r
f2bc359c
SZ
892 while (PrivateData->PpiData.DispatchNotifyList.LastDispatchedCount != PrivateData->PpiData.DispatchNotifyList.CurrentCount) {\r
893 TempValue = PrivateData->PpiData.DispatchNotifyList.CurrentCount;\r
894 ProcessNotify (\r
b0d803fe 895 PrivateData,\r
192f6d4c 896 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH,\r
897 0,\r
f2bc359c
SZ
898 PrivateData->PpiData.PpiList.LastDispatchedCount,\r
899 PrivateData->PpiData.DispatchNotifyList.LastDispatchedCount,\r
900 PrivateData->PpiData.DispatchNotifyList.CurrentCount\r
192f6d4c 901 );\r
f2bc359c 902 PrivateData->PpiData.DispatchNotifyList.LastDispatchedCount = TempValue;\r
192f6d4c 903 }\r
58dcdada 904\r
192f6d4c 905 //\r
906 // Check if the PEIM that was just dispatched resulted in any\r
907 // PPIs getting installed. If so, go process any dispatch\r
908 // level Notifies that match the installed PPIs.\r
f2bc359c
SZ
909 // Use "while" instead of "if" since ProcessNotify can modify\r
910 // PpiList.CurrentCount (with InstallPpi) so we have to iterate\r
911 // until the same.\r
192f6d4c 912 //\r
f2bc359c
SZ
913 while (PrivateData->PpiData.PpiList.LastDispatchedCount != PrivateData->PpiData.PpiList.CurrentCount) {\r
914 TempValue = PrivateData->PpiData.PpiList.CurrentCount;\r
915 ProcessNotify (\r
b0d803fe 916 PrivateData,\r
192f6d4c 917 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH,\r
f2bc359c
SZ
918 PrivateData->PpiData.PpiList.LastDispatchedCount,\r
919 PrivateData->PpiData.PpiList.CurrentCount,\r
920 0,\r
921 PrivateData->PpiData.DispatchNotifyList.LastDispatchedCount\r
192f6d4c 922 );\r
f2bc359c 923 PrivateData->PpiData.PpiList.LastDispatchedCount = TempValue;\r
192f6d4c 924 }\r
58dcdada 925\r
f2bc359c 926 if (PrivateData->PpiData.DispatchNotifyList.LastDispatchedCount == PrivateData->PpiData.DispatchNotifyList.CurrentCount) {\r
192f6d4c 927 break;\r
928 }\r
58dcdada 929 }\r
192f6d4c 930 return;\r
931}\r
932\r
b1f6a7c6 933/**\r
934\r
f2bc359c 935 Process notifications.\r
b1f6a7c6 936\r
937 @param PrivateData PeiCore's private data structure\r
938 @param NotifyType Type of notify to fire.\r
939 @param InstallStartIndex Install Beginning index.\r
940 @param InstallStopIndex Install Ending index.\r
941 @param NotifyStartIndex Notify Beginning index.\r
942 @param NotifyStopIndex Notify Ending index.\r
943\r
944**/\r
192f6d4c 945VOID\r
f2bc359c 946ProcessNotify (\r
b0d803fe 947 IN PEI_CORE_INSTANCE *PrivateData,\r
192f6d4c 948 IN UINTN NotifyType,\r
949 IN INTN InstallStartIndex,\r
950 IN INTN InstallStopIndex,\r
951 IN INTN NotifyStartIndex,\r
952 IN INTN NotifyStopIndex\r
953 )\r
192f6d4c 954{\r
f2bc359c
SZ
955 INTN Index1;\r
956 INTN Index2;\r
957 EFI_GUID *SearchGuid;\r
958 EFI_GUID *CheckGuid;\r
959 EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor;\r
960\r
961 for (Index1 = NotifyStartIndex; Index1 < NotifyStopIndex; Index1++) {\r
962 if (NotifyType == EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK) {\r
963 NotifyDescriptor = PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index1].Notify;\r
964 } else {\r
965 NotifyDescriptor = PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index1].Notify;\r
966 }\r
192f6d4c 967\r
968 CheckGuid = NotifyDescriptor->Guid;\r
969\r
970 for (Index2 = InstallStartIndex; Index2 < InstallStopIndex; Index2++) {\r
f2bc359c 971 SearchGuid = PrivateData->PpiData.PpiList.PpiPtrs[Index2].Ppi->Guid;\r
192f6d4c 972 //\r
973 // Don't use CompareGuid function here for performance reasons.\r
974 // Instead we compare the GUID as INT32 at a time and branch\r
975 // on the first failed comparison.\r
976 //\r
977 if ((((INT32 *)SearchGuid)[0] == ((INT32 *)CheckGuid)[0]) &&\r
978 (((INT32 *)SearchGuid)[1] == ((INT32 *)CheckGuid)[1]) &&\r
979 (((INT32 *)SearchGuid)[2] == ((INT32 *)CheckGuid)[2]) &&\r
980 (((INT32 *)SearchGuid)[3] == ((INT32 *)CheckGuid)[3])) {\r
0e549d5b 981 DEBUG ((EFI_D_INFO, "Notify: PPI Guid: %g, Peim notify entry point: %p\n",\r
58dcdada 982 SearchGuid,\r
192f6d4c 983 NotifyDescriptor->Notify\r
984 ));\r
985 NotifyDescriptor->Notify (\r
284c8400 986 (EFI_PEI_SERVICES **) GetPeiServicesTablePointer (),\r
192f6d4c 987 NotifyDescriptor,\r
f2bc359c 988 (PrivateData->PpiData.PpiList.PpiPtrs[Index2].Ppi)->Ppi\r
192f6d4c 989 );\r
990 }\r
991 }\r
992 }\r
192f6d4c 993}\r
994\r
884200f9
SZ
995/**\r
996 Process PpiList from SEC phase.\r
997\r
998 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
999 @param PpiList Points to a list of one or more PPI descriptors to be installed initially by the PEI core.\r
1000 These PPI's will be installed and/or immediately signaled if they are notification type.\r
1001\r
1002**/\r
1003VOID\r
1004ProcessPpiListFromSec (\r
1005 IN CONST EFI_PEI_SERVICES **PeiServices,\r
1006 IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList\r
1007 )\r
1008{\r
483e2cdd
SZ
1009 EFI_STATUS Status;\r
1010 EFI_SEC_HOB_DATA_PPI *SecHobDataPpi;\r
1011 EFI_HOB_GENERIC_HEADER *SecHobList;\r
884200f9
SZ
1012\r
1013 for (;;) {\r
1014 if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_TYPES) != 0) {\r
1015 //\r
1016 // It is a notification PPI.\r
1017 //\r
1018 Status = InternalPeiNotifyPpi (PeiServices, (CONST EFI_PEI_NOTIFY_DESCRIPTOR *) PpiList, TRUE);\r
1019 ASSERT_EFI_ERROR (Status);\r
1020 } else {\r
1021 //\r
1022 // It is a normal PPI.\r
1023 //\r
1024 Status = InternalPeiInstallPpi (PeiServices, PpiList, TRUE);\r
1025 ASSERT_EFI_ERROR (Status);\r
1026 }\r
1027\r
1028 if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) == EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) {\r
1029 //\r
1030 // Continue until the end of the PPI List.\r
1031 //\r
1032 break;\r
1033 }\r
1034\r
1035 PpiList++;\r
1036 }\r
483e2cdd
SZ
1037\r
1038 //\r
1039 // If the EFI_SEC_HOB_DATA_PPI is in the list of PPIs passed to the PEI entry point,\r
1040 // the PEI Foundation will call the GetHobs() member function and install all HOBs\r
1041 // returned into the HOB list. It does this after installing all PPIs passed from SEC\r
1042 // into the PPI database and before dispatching any PEIMs.\r
1043 //\r
1044 Status = PeiLocatePpi (PeiServices, &gEfiSecHobDataPpiGuid, 0, NULL, (VOID **) &SecHobDataPpi);\r
1045 if (!EFI_ERROR (Status)) {\r
1046 Status = SecHobDataPpi->GetHobs (SecHobDataPpi, &SecHobList);\r
1047 if (!EFI_ERROR (Status)) {\r
1048 Status = PeiInstallSecHobData (PeiServices, SecHobList);\r
1049 ASSERT_EFI_ERROR (Status);\r
1050 }\r
1051 }\r
884200f9
SZ
1052}\r
1053\r
9bedaec0
MK
1054/**\r
1055\r
1056 Migrate PPI Pointers of PEI_CORE from temporary memory to permanent memory.\r
1057\r
1058 @param PrivateData Pointer to PeiCore's private data structure.\r
1059 @param CoreFvHandle Address of PEI_CORE FV Handle in temporary memory.\r
1060\r
1061**/\r
1062VOID\r
1063ConvertPeiCorePpiPointers (\r
1064 IN PEI_CORE_INSTANCE *PrivateData,\r
1065 PEI_CORE_FV_HANDLE CoreFvHandle\r
1066 )\r
1067{\r
1068 EFI_FV_FILE_INFO FileInfo;\r
1069 EFI_PHYSICAL_ADDRESS OrgImageBase;\r
1070 EFI_PHYSICAL_ADDRESS MigratedImageBase;\r
1071 UINTN PeiCoreModuleSize;\r
1072 EFI_PEI_FILE_HANDLE PeiCoreFileHandle;\r
1073 VOID *PeiCoreImageBase;\r
1074 VOID *PeiCoreEntryPoint;\r
1075 EFI_STATUS Status;\r
1076\r
1077 PeiCoreFileHandle = NULL;\r
1078\r
1079 //\r
1080 // Find the PEI Core in the BFV in temporary memory.\r
1081 //\r
1082 Status = CoreFvHandle.FvPpi->FindFileByType (\r
1083 CoreFvHandle.FvPpi,\r
1084 EFI_FV_FILETYPE_PEI_CORE,\r
1085 CoreFvHandle.FvHandle,\r
1086 &PeiCoreFileHandle\r
1087 );\r
1088 ASSERT_EFI_ERROR (Status);\r
1089\r
1090 if (!EFI_ERROR (Status)) {\r
1091 Status = CoreFvHandle.FvPpi->GetFileInfo (CoreFvHandle.FvPpi, PeiCoreFileHandle, &FileInfo);\r
1092 ASSERT_EFI_ERROR (Status);\r
1093\r
1094 Status = PeiGetPe32Data (PeiCoreFileHandle, &PeiCoreImageBase);\r
1095 ASSERT_EFI_ERROR (Status);\r
1096\r
1097 //\r
1098 // Find PEI Core EntryPoint in the BFV in temporary memory.\r
1099 //\r
1100 Status = PeCoffLoaderGetEntryPoint ((VOID *) (UINTN) PeiCoreImageBase, &PeiCoreEntryPoint);\r
1101 ASSERT_EFI_ERROR (Status);\r
1102\r
1103 OrgImageBase = (UINTN) PeiCoreImageBase;\r
1104 MigratedImageBase = (UINTN) _ModuleEntryPoint - ((UINTN) PeiCoreEntryPoint - (UINTN) PeiCoreImageBase);\r
1105\r
1106 //\r
1107 // Size of loaded PEI_CORE in permanent memory.\r
1108 //\r
1109 PeiCoreModuleSize = (UINTN)FileInfo.BufferSize - ((UINTN) OrgImageBase - (UINTN) FileInfo.Buffer);\r
1110\r
1111 //\r
1112 // Migrate PEI_CORE PPI pointers from temporary memory to newly\r
1113 // installed PEI_CORE in permanent memory.\r
1114 //\r
1115 ConvertPpiPointersFv (PrivateData, (UINTN) OrgImageBase, (UINTN) MigratedImageBase, PeiCoreModuleSize);\r
1116 }\r
1117}\r
1118\r