]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdeModulePkg/Core/Pei/Ppi/Ppi.c
MdeModulePkg PeiCore: Fix typos
[mirror_edk2.git] / MdeModulePkg / Core / Pei / Ppi / Ppi.c
... / ...
CommitLineData
1/** @file\r
2 EFI PEI Core PPI services\r
3\r
4Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>\r
5SPDX-License-Identifier: BSD-2-Clause-Patent\r
6\r
7**/\r
8\r
9#include "PeiMain.h"\r
10\r
11/**\r
12\r
13 Migrate Pointer from the temporary memory to PEI installed memory.\r
14\r
15 @param Pointer Pointer to the Pointer needs to be converted.\r
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
19 @param OffsetPositive Positive flag of Offset value.\r
20\r
21**/\r
22VOID\r
23ConvertPointer (\r
24 IN OUT VOID **Pointer,\r
25 IN UINTN TempBottom,\r
26 IN UINTN TempTop,\r
27 IN UINTN Offset,\r
28 IN BOOLEAN OffsetPositive\r
29 )\r
30{\r
31 if (((UINTN) *Pointer < TempTop) &&\r
32 ((UINTN) *Pointer >= TempBottom)) {\r
33 if (OffsetPositive) {\r
34 *Pointer = (VOID *) ((UINTN) *Pointer + Offset);\r
35 } else {\r
36 *Pointer = (VOID *) ((UINTN) *Pointer - Offset);\r
37 }\r
38 }\r
39}\r
40\r
41/**\r
42\r
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
59\r
60 if (PrivateData->MemoryPages.Size != 0) {\r
61 //\r
62 // Convert PPI pointer in old memory pages\r
63 // It needs to be done before Convert PPI pointer in old Heap\r
64 //\r
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
102 }\r
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
111 }\r
112}\r
113\r
114/**\r
115\r
116 Migrate Single PPI Pointer from the temporary memory to PEI installed memory.\r
117\r
118 @param SecCoreData Points to a data structure containing SEC to PEI handoff data, such as the size\r
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
150/**\r
151\r
152 Migrate PPI Pointers from the temporary memory to PEI installed memory.\r
153\r
154 @param SecCoreData Points to a data structure containing SEC to PEI handoff data, such as the size\r
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
157\r
158**/\r
159VOID\r
160ConvertPpiPointers (\r
161 IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData,\r
162 IN PEI_CORE_INSTANCE *PrivateData\r
163 )\r
164{\r
165 UINT8 Index;\r
166\r
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
198 }\r
199}\r
200\r
201/**\r
202\r
203 This function installs an interface in the PEI PPI database by GUID.\r
204 The purpose of the service is to publish an interface that other parties\r
205 can use to call additional PEIMs.\r
206\r
207 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
208 @param PpiList Pointer to a list of PEI PPI Descriptors.\r
209 @param Single TRUE if only single entry in the PpiList.\r
210 FALSE if the PpiList is ended with an entry which has the\r
211 EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST flag set in its Flags field.\r
212\r
213 @retval EFI_SUCCESS if all PPIs in PpiList are successfully installed.\r
214 @retval EFI_INVALID_PARAMETER if PpiList is NULL pointer\r
215 if any PPI in PpiList is not valid\r
216 @retval EFI_OUT_OF_RESOURCES if there is no more memory resource to install PPI\r
217\r
218**/\r
219EFI_STATUS\r
220InternalPeiInstallPpi (\r
221 IN CONST EFI_PEI_SERVICES **PeiServices,\r
222 IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList,\r
223 IN BOOLEAN Single\r
224 )\r
225{\r
226 PEI_CORE_INSTANCE *PrivateData;\r
227 PEI_PPI_LIST *PpiListPointer;\r
228 UINTN Index;\r
229 UINTN LastCount;\r
230 VOID *TempPtr;\r
231\r
232 if (PpiList == NULL) {\r
233 return EFI_INVALID_PARAMETER;\r
234 }\r
235\r
236 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);\r
237\r
238 PpiListPointer = &PrivateData->PpiData.PpiList;\r
239 Index = PpiListPointer->CurrentCount;\r
240 LastCount = Index;\r
241\r
242 //\r
243 // This is loop installs all PPI descriptors in the PpiList. It is terminated\r
244 // by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last\r
245 // EFI_PEI_PPI_DESCRIPTOR in the list.\r
246 //\r
247\r
248 for (;;) {\r
249 //\r
250 // Check if it is a valid PPI.\r
251 // If not, rollback list to exclude all in this list.\r
252 // Try to indicate which item failed.\r
253 //\r
254 if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_PPI) == 0) {\r
255 PpiListPointer->CurrentCount = LastCount;\r
256 DEBUG((EFI_D_ERROR, "ERROR -> InstallPpi: %g %p\n", PpiList->Guid, PpiList->Ppi));\r
257 return EFI_INVALID_PARAMETER;\r
258 }\r
259\r
260 if (Index >= PpiListPointer->MaxCount) {\r
261 //\r
262 // Run out of room, grow the buffer.\r
263 //\r
264 TempPtr = AllocateZeroPool (\r
265 sizeof (PEI_PPI_LIST_POINTERS) * (PpiListPointer->MaxCount + PPI_GROWTH_STEP)\r
266 );\r
267 ASSERT (TempPtr != NULL);\r
268 CopyMem (\r
269 TempPtr,\r
270 PpiListPointer->PpiPtrs,\r
271 sizeof (PEI_PPI_LIST_POINTERS) * PpiListPointer->MaxCount\r
272 );\r
273 PpiListPointer->PpiPtrs = TempPtr;\r
274 PpiListPointer->MaxCount = PpiListPointer->MaxCount + PPI_GROWTH_STEP;\r
275 }\r
276\r
277 DEBUG((EFI_D_INFO, "Install PPI: %g\n", PpiList->Guid));\r
278 PpiListPointer->PpiPtrs[Index].Ppi = (EFI_PEI_PPI_DESCRIPTOR *) PpiList;\r
279 Index++;\r
280 PpiListPointer->CurrentCount++;\r
281\r
282 if (Single) {\r
283 //\r
284 // Only single entry in the PpiList.\r
285 //\r
286 break;\r
287 } else if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) ==\r
288 EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) {\r
289 //\r
290 // Continue until the end of the PPI List.\r
291 //\r
292 break;\r
293 }\r
294 //\r
295 // Go to the next descriptor.\r
296 //\r
297 PpiList++;\r
298 }\r
299\r
300 //\r
301 // Process any callback level notifies for newly installed PPIs.\r
302 //\r
303 ProcessNotify (\r
304 PrivateData,\r
305 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,\r
306 LastCount,\r
307 PpiListPointer->CurrentCount,\r
308 0,\r
309 PrivateData->PpiData.CallbackNotifyList.CurrentCount\r
310 );\r
311\r
312 return EFI_SUCCESS;\r
313}\r
314\r
315/**\r
316\r
317 This function installs an interface in the PEI PPI database by GUID.\r
318 The purpose of the service is to publish an interface that other parties\r
319 can use to call additional PEIMs.\r
320\r
321 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
322 @param PpiList Pointer to a list of PEI PPI Descriptors.\r
323\r
324 @retval EFI_SUCCESS if all PPIs in PpiList are successfully installed.\r
325 @retval EFI_INVALID_PARAMETER if PpiList is NULL pointer\r
326 if any PPI in PpiList is not valid\r
327 @retval EFI_OUT_OF_RESOURCES if there is no more memory resource to install PPI\r
328\r
329**/\r
330EFI_STATUS\r
331EFIAPI\r
332PeiInstallPpi (\r
333 IN CONST EFI_PEI_SERVICES **PeiServices,\r
334 IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList\r
335 )\r
336{\r
337 return InternalPeiInstallPpi (PeiServices, PpiList, FALSE);\r
338}\r
339\r
340/**\r
341\r
342 This function reinstalls an interface in the PEI PPI database by GUID.\r
343 The purpose of the service is to publish an interface that other parties can\r
344 use to replace an interface of the same name in the protocol database with a\r
345 different interface.\r
346\r
347 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
348 @param OldPpi Pointer to the old PEI PPI Descriptors.\r
349 @param NewPpi Pointer to the new PEI PPI Descriptors.\r
350\r
351 @retval EFI_SUCCESS if the operation was successful\r
352 @retval EFI_INVALID_PARAMETER if OldPpi or NewPpi is NULL\r
353 @retval EFI_INVALID_PARAMETER if NewPpi is not valid\r
354 @retval EFI_NOT_FOUND if the PPI was not in the database\r
355\r
356**/\r
357EFI_STATUS\r
358EFIAPI\r
359PeiReInstallPpi (\r
360 IN CONST EFI_PEI_SERVICES **PeiServices,\r
361 IN CONST EFI_PEI_PPI_DESCRIPTOR *OldPpi,\r
362 IN CONST EFI_PEI_PPI_DESCRIPTOR *NewPpi\r
363 )\r
364{\r
365 PEI_CORE_INSTANCE *PrivateData;\r
366 UINTN Index;\r
367\r
368\r
369 if ((OldPpi == NULL) || (NewPpi == NULL)) {\r
370 return EFI_INVALID_PARAMETER;\r
371 }\r
372\r
373 if ((NewPpi->Flags & EFI_PEI_PPI_DESCRIPTOR_PPI) == 0) {\r
374 return EFI_INVALID_PARAMETER;\r
375 }\r
376\r
377 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);\r
378\r
379 //\r
380 // Find the old PPI instance in the database. If we can not find it,\r
381 // return the EFI_NOT_FOUND error.\r
382 //\r
383 for (Index = 0; Index < PrivateData->PpiData.PpiList.CurrentCount; Index++) {\r
384 if (OldPpi == PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi) {\r
385 break;\r
386 }\r
387 }\r
388 if (Index == PrivateData->PpiData.PpiList.CurrentCount) {\r
389 return EFI_NOT_FOUND;\r
390 }\r
391\r
392 //\r
393 // Replace the old PPI with the new one.\r
394 //\r
395 DEBUG((EFI_D_INFO, "Reinstall PPI: %g\n", NewPpi->Guid));\r
396 PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi = (EFI_PEI_PPI_DESCRIPTOR *) NewPpi;\r
397\r
398 //\r
399 // Process any callback level notifies for the newly installed PPI.\r
400 //\r
401 ProcessNotify (\r
402 PrivateData,\r
403 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,\r
404 Index,\r
405 Index+1,\r
406 0,\r
407 PrivateData->PpiData.CallbackNotifyList.CurrentCount\r
408 );\r
409\r
410 return EFI_SUCCESS;\r
411}\r
412\r
413/**\r
414\r
415 Locate a given named PPI.\r
416\r
417\r
418 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
419 @param Guid Pointer to GUID of the PPI.\r
420 @param Instance Instance Number to discover.\r
421 @param PpiDescriptor Pointer to reference the found descriptor. If not NULL,\r
422 returns a pointer to the descriptor (includes flags, etc)\r
423 @param Ppi Pointer to reference the found PPI\r
424\r
425 @retval EFI_SUCCESS if the PPI is in the database\r
426 @retval EFI_NOT_FOUND if the PPI is not in the database\r
427\r
428**/\r
429EFI_STATUS\r
430EFIAPI\r
431PeiLocatePpi (\r
432 IN CONST EFI_PEI_SERVICES **PeiServices,\r
433 IN CONST EFI_GUID *Guid,\r
434 IN UINTN Instance,\r
435 IN OUT EFI_PEI_PPI_DESCRIPTOR **PpiDescriptor,\r
436 IN OUT VOID **Ppi\r
437 )\r
438{\r
439 PEI_CORE_INSTANCE *PrivateData;\r
440 UINTN Index;\r
441 EFI_GUID *CheckGuid;\r
442 EFI_PEI_PPI_DESCRIPTOR *TempPtr;\r
443\r
444\r
445 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);\r
446\r
447 //\r
448 // Search the data base for the matching instance of the GUIDed PPI.\r
449 //\r
450 for (Index = 0; Index < PrivateData->PpiData.PpiList.CurrentCount; Index++) {\r
451 TempPtr = PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi;\r
452 CheckGuid = TempPtr->Guid;\r
453\r
454 //\r
455 // Don't use CompareGuid function here for performance reasons.\r
456 // Instead we compare the GUID as INT32 at a time and branch\r
457 // on the first failed comparison.\r
458 //\r
459 if ((((INT32 *)Guid)[0] == ((INT32 *)CheckGuid)[0]) &&\r
460 (((INT32 *)Guid)[1] == ((INT32 *)CheckGuid)[1]) &&\r
461 (((INT32 *)Guid)[2] == ((INT32 *)CheckGuid)[2]) &&\r
462 (((INT32 *)Guid)[3] == ((INT32 *)CheckGuid)[3])) {\r
463 if (Instance == 0) {\r
464\r
465 if (PpiDescriptor != NULL) {\r
466 *PpiDescriptor = TempPtr;\r
467 }\r
468\r
469 if (Ppi != NULL) {\r
470 *Ppi = TempPtr->Ppi;\r
471 }\r
472\r
473\r
474 return EFI_SUCCESS;\r
475 }\r
476 Instance--;\r
477 }\r
478 }\r
479\r
480 return EFI_NOT_FOUND;\r
481}\r
482\r
483/**\r
484\r
485 This function installs a notification service to be called back when a given\r
486 interface is installed or reinstalled. The purpose of the service is to publish\r
487 an interface that other parties can use to call additional PPIs that may materialize later.\r
488\r
489 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
490 @param NotifyList Pointer to list of Descriptors to notify upon.\r
491 @param Single TRUE if only single entry in the NotifyList.\r
492 FALSE if the NotifyList is ended with an entry which has the\r
493 EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST flag set in its Flags field.\r
494\r
495 @retval EFI_SUCCESS if successful\r
496 @retval EFI_OUT_OF_RESOURCES if no space in the database\r
497 @retval EFI_INVALID_PARAMETER if not a good descriptor\r
498\r
499**/\r
500EFI_STATUS\r
501InternalPeiNotifyPpi (\r
502 IN CONST EFI_PEI_SERVICES **PeiServices,\r
503 IN CONST EFI_PEI_NOTIFY_DESCRIPTOR *NotifyList,\r
504 IN BOOLEAN Single\r
505 )\r
506{\r
507 PEI_CORE_INSTANCE *PrivateData;\r
508 PEI_CALLBACK_NOTIFY_LIST *CallbackNotifyListPointer;\r
509 UINTN CallbackNotifyIndex;\r
510 UINTN LastCallbackNotifyCount;\r
511 PEI_DISPATCH_NOTIFY_LIST *DispatchNotifyListPointer;\r
512 UINTN DispatchNotifyIndex;\r
513 UINTN LastDispatchNotifyCount;\r
514 VOID *TempPtr;\r
515\r
516 if (NotifyList == NULL) {\r
517 return EFI_INVALID_PARAMETER;\r
518 }\r
519\r
520 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);\r
521\r
522 CallbackNotifyListPointer = &PrivateData->PpiData.CallbackNotifyList;\r
523 CallbackNotifyIndex = CallbackNotifyListPointer->CurrentCount;\r
524 LastCallbackNotifyCount = CallbackNotifyIndex;\r
525\r
526 DispatchNotifyListPointer = &PrivateData->PpiData.DispatchNotifyList;\r
527 DispatchNotifyIndex = DispatchNotifyListPointer->CurrentCount;\r
528 LastDispatchNotifyCount = DispatchNotifyIndex;\r
529\r
530 //\r
531 // This is loop installs all Notify descriptors in the NotifyList. It is\r
532 // terminated by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last\r
533 // EFI_PEI_NOTIFY_DESCRIPTOR in the list.\r
534 //\r
535\r
536 for (;;) {\r
537 //\r
538 // If some of the PPI data is invalid restore original Notify PPI database value\r
539 //\r
540 if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_TYPES) == 0) {\r
541 CallbackNotifyListPointer->CurrentCount = LastCallbackNotifyCount;\r
542 DispatchNotifyListPointer->CurrentCount = LastDispatchNotifyCount;\r
543 DEBUG((DEBUG_ERROR, "ERROR -> NotifyPpi: %g %p\n", NotifyList->Guid, NotifyList->Notify));\r
544 return EFI_INVALID_PARAMETER;\r
545 }\r
546\r
547 if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK) != 0) {\r
548 if (CallbackNotifyIndex >= CallbackNotifyListPointer->MaxCount) {\r
549 //\r
550 // Run out of room, grow the buffer.\r
551 //\r
552 TempPtr = AllocateZeroPool (\r
553 sizeof (PEI_PPI_LIST_POINTERS) * (CallbackNotifyListPointer->MaxCount + CALLBACK_NOTIFY_GROWTH_STEP)\r
554 );\r
555 ASSERT (TempPtr != NULL);\r
556 CopyMem (\r
557 TempPtr,\r
558 CallbackNotifyListPointer->NotifyPtrs,\r
559 sizeof (PEI_PPI_LIST_POINTERS) * CallbackNotifyListPointer->MaxCount\r
560 );\r
561 CallbackNotifyListPointer->NotifyPtrs = TempPtr;\r
562 CallbackNotifyListPointer->MaxCount = CallbackNotifyListPointer->MaxCount + CALLBACK_NOTIFY_GROWTH_STEP;\r
563 }\r
564 CallbackNotifyListPointer->NotifyPtrs[CallbackNotifyIndex].Notify = (EFI_PEI_NOTIFY_DESCRIPTOR *) NotifyList;\r
565 CallbackNotifyIndex++;\r
566 CallbackNotifyListPointer->CurrentCount++;\r
567 } else {\r
568 if (DispatchNotifyIndex >= DispatchNotifyListPointer->MaxCount) {\r
569 //\r
570 // Run out of room, grow the buffer.\r
571 //\r
572 TempPtr = AllocateZeroPool (\r
573 sizeof (PEI_PPI_LIST_POINTERS) * (DispatchNotifyListPointer->MaxCount + DISPATCH_NOTIFY_GROWTH_STEP)\r
574 );\r
575 ASSERT (TempPtr != NULL);\r
576 CopyMem (\r
577 TempPtr,\r
578 DispatchNotifyListPointer->NotifyPtrs,\r
579 sizeof (PEI_PPI_LIST_POINTERS) * DispatchNotifyListPointer->MaxCount\r
580 );\r
581 DispatchNotifyListPointer->NotifyPtrs = TempPtr;\r
582 DispatchNotifyListPointer->MaxCount = DispatchNotifyListPointer->MaxCount + DISPATCH_NOTIFY_GROWTH_STEP;\r
583 }\r
584 DispatchNotifyListPointer->NotifyPtrs[DispatchNotifyIndex].Notify = (EFI_PEI_NOTIFY_DESCRIPTOR *) NotifyList;\r
585 DispatchNotifyIndex++;\r
586 DispatchNotifyListPointer->CurrentCount++;\r
587 }\r
588\r
589 DEBUG((EFI_D_INFO, "Register PPI Notify: %g\n", NotifyList->Guid));\r
590\r
591 if (Single) {\r
592 //\r
593 // Only single entry in the NotifyList.\r
594 //\r
595 break;\r
596 } else if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) ==\r
597 EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) {\r
598 //\r
599 // Continue until the end of the Notify List.\r
600 //\r
601 break;\r
602 }\r
603 //\r
604 // Go to the next descriptor.\r
605 //\r
606 NotifyList++;\r
607 }\r
608\r
609 //\r
610 // Process any callback level notifies for all previously installed PPIs.\r
611 //\r
612 ProcessNotify (\r
613 PrivateData,\r
614 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,\r
615 0,\r
616 PrivateData->PpiData.PpiList.CurrentCount,\r
617 LastCallbackNotifyCount,\r
618 CallbackNotifyListPointer->CurrentCount\r
619 );\r
620\r
621 return EFI_SUCCESS;\r
622}\r
623\r
624/**\r
625\r
626 This function installs a notification service to be called back when a given\r
627 interface is installed or reinstalled. The purpose of the service is to publish\r
628 an interface that other parties can use to call additional PPIs that may materialize later.\r
629\r
630 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
631 @param NotifyList Pointer to list of Descriptors to notify upon.\r
632\r
633 @retval EFI_SUCCESS if successful\r
634 @retval EFI_OUT_OF_RESOURCES if no space in the database\r
635 @retval EFI_INVALID_PARAMETER if not a good descriptor\r
636\r
637**/\r
638EFI_STATUS\r
639EFIAPI\r
640PeiNotifyPpi (\r
641 IN CONST EFI_PEI_SERVICES **PeiServices,\r
642 IN CONST EFI_PEI_NOTIFY_DESCRIPTOR *NotifyList\r
643 )\r
644{\r
645 return InternalPeiNotifyPpi (PeiServices, NotifyList, FALSE);\r
646}\r
647\r
648/**\r
649\r
650 Process the Notify List at dispatch level.\r
651\r
652 @param PrivateData PeiCore's private data structure.\r
653\r
654**/\r
655VOID\r
656ProcessDispatchNotifyList (\r
657 IN PEI_CORE_INSTANCE *PrivateData\r
658 )\r
659{\r
660 UINTN TempValue;\r
661\r
662 while (TRUE) {\r
663 //\r
664 // Check if the PEIM that was just dispatched resulted in any\r
665 // Notifies getting installed. If so, go process any dispatch\r
666 // level Notifies that match the previously installed PPIs.\r
667 // Use "while" instead of "if" since ProcessNotify can modify\r
668 // DispatchNotifyList.CurrentCount (with NotifyPpi) so we have\r
669 // to iterate until the same.\r
670 //\r
671 while (PrivateData->PpiData.DispatchNotifyList.LastDispatchedCount != PrivateData->PpiData.DispatchNotifyList.CurrentCount) {\r
672 TempValue = PrivateData->PpiData.DispatchNotifyList.CurrentCount;\r
673 ProcessNotify (\r
674 PrivateData,\r
675 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH,\r
676 0,\r
677 PrivateData->PpiData.PpiList.LastDispatchedCount,\r
678 PrivateData->PpiData.DispatchNotifyList.LastDispatchedCount,\r
679 PrivateData->PpiData.DispatchNotifyList.CurrentCount\r
680 );\r
681 PrivateData->PpiData.DispatchNotifyList.LastDispatchedCount = TempValue;\r
682 }\r
683\r
684 //\r
685 // Check if the PEIM that was just dispatched resulted in any\r
686 // PPIs getting installed. If so, go process any dispatch\r
687 // level Notifies that match the installed PPIs.\r
688 // Use "while" instead of "if" since ProcessNotify can modify\r
689 // PpiList.CurrentCount (with InstallPpi) so we have to iterate\r
690 // until the same.\r
691 //\r
692 while (PrivateData->PpiData.PpiList.LastDispatchedCount != PrivateData->PpiData.PpiList.CurrentCount) {\r
693 TempValue = PrivateData->PpiData.PpiList.CurrentCount;\r
694 ProcessNotify (\r
695 PrivateData,\r
696 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH,\r
697 PrivateData->PpiData.PpiList.LastDispatchedCount,\r
698 PrivateData->PpiData.PpiList.CurrentCount,\r
699 0,\r
700 PrivateData->PpiData.DispatchNotifyList.LastDispatchedCount\r
701 );\r
702 PrivateData->PpiData.PpiList.LastDispatchedCount = TempValue;\r
703 }\r
704\r
705 if (PrivateData->PpiData.DispatchNotifyList.LastDispatchedCount == PrivateData->PpiData.DispatchNotifyList.CurrentCount) {\r
706 break;\r
707 }\r
708 }\r
709 return;\r
710}\r
711\r
712/**\r
713\r
714 Process notifications.\r
715\r
716 @param PrivateData PeiCore's private data structure\r
717 @param NotifyType Type of notify to fire.\r
718 @param InstallStartIndex Install Beginning index.\r
719 @param InstallStopIndex Install Ending index.\r
720 @param NotifyStartIndex Notify Beginning index.\r
721 @param NotifyStopIndex Notify Ending index.\r
722\r
723**/\r
724VOID\r
725ProcessNotify (\r
726 IN PEI_CORE_INSTANCE *PrivateData,\r
727 IN UINTN NotifyType,\r
728 IN INTN InstallStartIndex,\r
729 IN INTN InstallStopIndex,\r
730 IN INTN NotifyStartIndex,\r
731 IN INTN NotifyStopIndex\r
732 )\r
733{\r
734 INTN Index1;\r
735 INTN Index2;\r
736 EFI_GUID *SearchGuid;\r
737 EFI_GUID *CheckGuid;\r
738 EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor;\r
739\r
740 for (Index1 = NotifyStartIndex; Index1 < NotifyStopIndex; Index1++) {\r
741 if (NotifyType == EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK) {\r
742 NotifyDescriptor = PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index1].Notify;\r
743 } else {\r
744 NotifyDescriptor = PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index1].Notify;\r
745 }\r
746\r
747 CheckGuid = NotifyDescriptor->Guid;\r
748\r
749 for (Index2 = InstallStartIndex; Index2 < InstallStopIndex; Index2++) {\r
750 SearchGuid = PrivateData->PpiData.PpiList.PpiPtrs[Index2].Ppi->Guid;\r
751 //\r
752 // Don't use CompareGuid function here for performance reasons.\r
753 // Instead we compare the GUID as INT32 at a time and branch\r
754 // on the first failed comparison.\r
755 //\r
756 if ((((INT32 *)SearchGuid)[0] == ((INT32 *)CheckGuid)[0]) &&\r
757 (((INT32 *)SearchGuid)[1] == ((INT32 *)CheckGuid)[1]) &&\r
758 (((INT32 *)SearchGuid)[2] == ((INT32 *)CheckGuid)[2]) &&\r
759 (((INT32 *)SearchGuid)[3] == ((INT32 *)CheckGuid)[3])) {\r
760 DEBUG ((EFI_D_INFO, "Notify: PPI Guid: %g, Peim notify entry point: %p\n",\r
761 SearchGuid,\r
762 NotifyDescriptor->Notify\r
763 ));\r
764 NotifyDescriptor->Notify (\r
765 (EFI_PEI_SERVICES **) GetPeiServicesTablePointer (),\r
766 NotifyDescriptor,\r
767 (PrivateData->PpiData.PpiList.PpiPtrs[Index2].Ppi)->Ppi\r
768 );\r
769 }\r
770 }\r
771 }\r
772}\r
773\r
774/**\r
775 Process PpiList from SEC phase.\r
776\r
777 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
778 @param PpiList Points to a list of one or more PPI descriptors to be installed initially by the PEI core.\r
779 These PPI's will be installed and/or immediately signaled if they are notification type.\r
780\r
781**/\r
782VOID\r
783ProcessPpiListFromSec (\r
784 IN CONST EFI_PEI_SERVICES **PeiServices,\r
785 IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList\r
786 )\r
787{\r
788 EFI_STATUS Status;\r
789 EFI_SEC_HOB_DATA_PPI *SecHobDataPpi;\r
790 EFI_HOB_GENERIC_HEADER *SecHobList;\r
791\r
792 for (;;) {\r
793 if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_TYPES) != 0) {\r
794 //\r
795 // It is a notification PPI.\r
796 //\r
797 Status = InternalPeiNotifyPpi (PeiServices, (CONST EFI_PEI_NOTIFY_DESCRIPTOR *) PpiList, TRUE);\r
798 ASSERT_EFI_ERROR (Status);\r
799 } else {\r
800 //\r
801 // It is a normal PPI.\r
802 //\r
803 Status = InternalPeiInstallPpi (PeiServices, PpiList, TRUE);\r
804 ASSERT_EFI_ERROR (Status);\r
805 }\r
806\r
807 if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) == EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) {\r
808 //\r
809 // Continue until the end of the PPI List.\r
810 //\r
811 break;\r
812 }\r
813\r
814 PpiList++;\r
815 }\r
816\r
817 //\r
818 // If the EFI_SEC_HOB_DATA_PPI is in the list of PPIs passed to the PEI entry point,\r
819 // the PEI Foundation will call the GetHobs() member function and install all HOBs\r
820 // returned into the HOB list. It does this after installing all PPIs passed from SEC\r
821 // into the PPI database and before dispatching any PEIMs.\r
822 //\r
823 Status = PeiLocatePpi (PeiServices, &gEfiSecHobDataPpiGuid, 0, NULL, (VOID **) &SecHobDataPpi);\r
824 if (!EFI_ERROR (Status)) {\r
825 Status = SecHobDataPpi->GetHobs (SecHobDataPpi, &SecHobList);\r
826 if (!EFI_ERROR (Status)) {\r
827 Status = PeiInstallSecHobData (PeiServices, SecHobList);\r
828 ASSERT_EFI_ERROR (Status);\r
829 }\r
830 }\r
831}\r
832\r