]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Pei/Ppi/Ppi.c
MdePkg: Add definition for SecHobData PPI
[mirror_edk2.git] / MdeModulePkg / Core / Pei / Ppi / Ppi.c
CommitLineData
615c6dd0 1/** @file\r
b1f6a7c6 2 EFI PEI Core PPI services\r
3 \r
884200f9 4Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>\r
cd5ebaa0 5This program and the accompanying materials\r
58dcdada 6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
192f6d4c 12\r
b1f6a7c6 13**/\r
192f6d4c 14\r
0d516397 15#include "PeiMain.h"\r
192f6d4c 16\r
b1f6a7c6 17/**\r
192f6d4c 18\r
b1f6a7c6 19 Initialize PPI services.\r
192f6d4c 20\r
b1f6a7c6 21 @param PrivateData Pointer to the PEI Core data.\r
22 @param OldCoreData Pointer to old PEI Core data. \r
23 NULL if being run in non-permament memory mode.\r
192f6d4c 24\r
b1f6a7c6 25**/\r
192f6d4c 26VOID\r
27InitializePpiServices (\r
b0d803fe 28 IN PEI_CORE_INSTANCE *PrivateData,\r
192f6d4c 29 IN PEI_CORE_INSTANCE *OldCoreData\r
30 )\r
192f6d4c 31{\r
192f6d4c 32 if (OldCoreData == NULL) {\r
fe781940
SZ
33 PrivateData->PpiData.NotifyListEnd = PcdGet32 (PcdPeiCoreMaxPpiSupported)-1;\r
34 PrivateData->PpiData.DispatchListEnd = PcdGet32 (PcdPeiCoreMaxPpiSupported)-1;\r
35 PrivateData->PpiData.LastDispatchedNotify = PcdGet32 (PcdPeiCoreMaxPpiSupported)-1;\r
192f6d4c 36 }\r
192f6d4c 37}\r
38\r
b1f6a7c6 39/**\r
40\r
0f9ebb32
LG
41 Migrate Single PPI Pointer from the temporary memory to PEI installed memory.\r
42\r
43 @param PpiPointer Pointer to Ppi\r
44 @param TempBottom Base of old temporary memory\r
45 @param TempTop Top of old temporary memory\r
46 @param Offset Offset of new memory to old temporary memory.\r
47 @param OffsetPositive Positive flag of Offset value. \r
48\r
49**/\r
50VOID\r
de74668f 51ConvertSinglePpiPointer (\r
0f9ebb32
LG
52 IN PEI_PPI_LIST_POINTERS *PpiPointer,\r
53 IN UINTN TempBottom,\r
54 IN UINTN TempTop,\r
55 IN UINTN Offset,\r
56 IN BOOLEAN OffsetPositive\r
57 )\r
58{\r
59 if (((UINTN)PpiPointer->Raw < TempTop) &&\r
60 ((UINTN)PpiPointer->Raw >= TempBottom)) {\r
61 //\r
62 // Convert the pointer to the PPI descriptor from the old TempRam\r
63 // to the relocated physical memory.\r
64 //\r
65 if (OffsetPositive) {\r
66 PpiPointer->Raw = (VOID *) ((UINTN)PpiPointer->Raw + Offset);\r
67 } else {\r
68 PpiPointer->Raw = (VOID *) ((UINTN)PpiPointer->Raw - Offset);\r
69 }\r
70\r
71 //\r
72 // Only when the PEIM descriptor is in the old TempRam should it be necessary\r
73 // to try to convert the pointers in the PEIM descriptor\r
74 //\r
75\r
76 if (((UINTN)PpiPointer->Ppi->Guid < TempTop) &&\r
77 ((UINTN)PpiPointer->Ppi->Guid >= TempBottom)) {\r
78 //\r
79 // Convert the pointer to the GUID in the PPI or NOTIFY descriptor\r
80 // from the old TempRam to the relocated physical memory.\r
81 //\r
82 if (OffsetPositive) {\r
83 PpiPointer->Ppi->Guid = (VOID *) ((UINTN)PpiPointer->Ppi->Guid + Offset);\r
84 } else {\r
85 PpiPointer->Ppi->Guid = (VOID *) ((UINTN)PpiPointer->Ppi->Guid - Offset);\r
86 }\r
87 }\r
88\r
89 //\r
90 // Convert the pointer to the PPI interface structure in the PPI descriptor\r
91 // from the old TempRam to the relocated physical memory.\r
92 //\r
93 if ((UINTN)PpiPointer->Ppi->Ppi < TempTop &&\r
94 (UINTN)PpiPointer->Ppi->Ppi >= TempBottom) {\r
95 if (OffsetPositive) {\r
96 PpiPointer->Ppi->Ppi = (VOID *) ((UINTN)PpiPointer->Ppi->Ppi + Offset);\r
97 } else {\r
98 PpiPointer->Ppi->Ppi = (VOID *) ((UINTN)PpiPointer->Ppi->Ppi - Offset);\r
99 }\r
100 }\r
101 }\r
102}\r
103\r
104/**\r
105\r
106 Migrate PPI Pointers from the temporary memory stack to PEI installed memory.\r
b1f6a7c6 107\r
424b7c9f 108 @param SecCoreData Points to a data structure containing SEC to PEI handoff data, such as the size \r
109 and location of temporary RAM, the stack location and the BFV location.\r
110 @param PrivateData Pointer to PeiCore's private data structure.\r
b1f6a7c6 111\r
112**/\r
192f6d4c 113VOID\r
114ConvertPpiPointers (\r
424b7c9f 115 IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData,\r
116 IN PEI_CORE_INSTANCE *PrivateData\r
192f6d4c 117 )\r
192f6d4c 118{\r
192f6d4c 119 UINT8 Index;\r
0f9ebb32 120 UINT8 IndexHole;\r
192f6d4c 121\r
fe781940 122 for (Index = 0; Index < PcdGet32 (PcdPeiCoreMaxPpiSupported); Index++) {\r
0f9ebb32
LG
123 if (Index < PrivateData->PpiData.PpiListEnd || Index > PrivateData->PpiData.NotifyListEnd) {\r
124 //\r
125 // Convert PPI pointer in old Heap\r
126 //\r
de74668f 127 ConvertSinglePpiPointer (\r
0f9ebb32
LG
128 &PrivateData->PpiData.PpiListPtrs[Index],\r
129 (UINTN)SecCoreData->PeiTemporaryRamBase,\r
130 (UINTN)SecCoreData->PeiTemporaryRamBase + SecCoreData->PeiTemporaryRamSize,\r
131 PrivateData->HeapOffset,\r
132 PrivateData->HeapOffsetPositive\r
133 );\r
134 \r
135 //\r
136 // Convert PPI pointer in old Stack\r
137 //\r
de74668f 138 ConvertSinglePpiPointer (\r
0f9ebb32
LG
139 &PrivateData->PpiData.PpiListPtrs[Index],\r
140 (UINTN)SecCoreData->StackBase,\r
141 (UINTN)SecCoreData->StackBase + SecCoreData->StackSize,\r
142 PrivateData->StackOffset,\r
143 PrivateData->StackOffsetPositive\r
144 );\r
145 \r
146 //\r
147 // Convert PPI pointer in old TempRam Hole\r
148 //\r
149 for (IndexHole = 0; IndexHole < HOLE_MAX_NUMBER; IndexHole ++) {\r
150 if (PrivateData->HoleData[IndexHole].Size == 0) {\r
151 continue;\r
2740a797 152 }\r
0f9ebb32 153 \r
de74668f 154 ConvertSinglePpiPointer (\r
0f9ebb32
LG
155 &PrivateData->PpiData.PpiListPtrs[Index],\r
156 (UINTN)PrivateData->HoleData[IndexHole].Base,\r
157 (UINTN)PrivateData->HoleData[IndexHole].Base + PrivateData->HoleData[IndexHole].Size,\r
158 PrivateData->HoleData[IndexHole].Offset,\r
159 PrivateData->HoleData[IndexHole].OffsetPositive\r
160 );\r
192f6d4c 161 }\r
162 }\r
163 }\r
164}\r
165\r
b1f6a7c6 166/**\r
192f6d4c 167\r
0f65cdaa 168 This function installs an interface in the PEI PPI database by GUID. \r
169 The purpose of the service is to publish an interface that other parties\r
170 can use to call additional PEIMs.\r
192f6d4c 171\r
0f65cdaa 172 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
173 @param PpiList Pointer to a list of PEI PPI Descriptors.\r
884200f9
SZ
174 @param Single TRUE if only single entry in the PpiList.\r
175 FALSE if the PpiList is ended with an entry which has the\r
176 EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST flag set in its Flags field.\r
b1f6a7c6 177\r
0f65cdaa 178 @retval EFI_SUCCESS if all PPIs in PpiList are successfully installed.\r
179 @retval EFI_INVALID_PARAMETER if PpiList is NULL pointer\r
731bd38e 180 if any PPI in PpiList is not valid\r
0f65cdaa 181 @retval EFI_OUT_OF_RESOURCES if there is no more memory resource to install PPI\r
b1f6a7c6 182\r
183**/\r
192f6d4c 184EFI_STATUS\r
884200f9 185InternalPeiInstallPpi (\r
0c2b5da8 186 IN CONST EFI_PEI_SERVICES **PeiServices,\r
884200f9
SZ
187 IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList,\r
188 IN BOOLEAN Single\r
192f6d4c 189 )\r
192f6d4c 190{\r
191 PEI_CORE_INSTANCE *PrivateData;\r
192 INTN Index;\r
193 INTN LastCallbackInstall;\r
194\r
195\r
196 if (PpiList == NULL) {\r
197 return EFI_INVALID_PARAMETER;\r
198 }\r
199\r
200 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);\r
201\r
202 Index = PrivateData->PpiData.PpiListEnd;\r
203 LastCallbackInstall = Index;\r
204\r
205 //\r
206 // This is loop installs all PPI descriptors in the PpiList. It is terminated\r
207 // by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last\r
208 // EFI_PEI_PPI_DESCRIPTOR in the list.\r
209 //\r
58dcdada 210\r
192f6d4c 211 for (;;) {\r
212 //\r
731bd38e 213 // Since PpiData is used for NotifyList and PpiList, max resource\r
192f6d4c 214 // is reached if the Install reaches the NotifyList\r
97b2c9b5 215 // PcdPeiCoreMaxPpiSupported can be set to a larger value in DSC to satisfy more PPI requirement.\r
192f6d4c 216 //\r
217 if (Index == PrivateData->PpiData.NotifyListEnd + 1) {\r
218 return EFI_OUT_OF_RESOURCES;\r
219 }\r
220 //\r
58dcdada 221 // Check if it is a valid PPI.\r
192f6d4c 222 // If not, rollback list to exclude all in this list.\r
223 // Try to indicate which item failed.\r
224 //\r
225 if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_PPI) == 0) {\r
226 PrivateData->PpiData.PpiListEnd = LastCallbackInstall;\r
0e549d5b 227 DEBUG((EFI_D_ERROR, "ERROR -> InstallPpi: %g %p\n", PpiList->Guid, PpiList->Ppi));\r
192f6d4c 228 return EFI_INVALID_PARAMETER;\r
229 }\r
230\r
58dcdada 231 DEBUG((EFI_D_INFO, "Install PPI: %g\n", PpiList->Guid));\r
232 PrivateData->PpiData.PpiListPtrs[Index].Ppi = (EFI_PEI_PPI_DESCRIPTOR*) PpiList;\r
192f6d4c 233 PrivateData->PpiData.PpiListEnd++;\r
58dcdada 234\r
884200f9
SZ
235 if (Single) {\r
236 //\r
237 // Only single entry in the PpiList.\r
238 //\r
239 break;\r
240 } else if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) ==\r
241 EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) {\r
242 //\r
243 // Continue until the end of the PPI List.\r
244 //\r
192f6d4c 245 break;\r
246 }\r
247 PpiList++;\r
248 Index++;\r
249 }\r
250\r
251 //\r
252 // Dispatch any callback level notifies for newly installed PPIs.\r
253 //\r
254 DispatchNotify (\r
b0d803fe 255 PrivateData,\r
192f6d4c 256 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,\r
257 LastCallbackInstall,\r
258 PrivateData->PpiData.PpiListEnd,\r
58dcdada 259 PrivateData->PpiData.DispatchListEnd,\r
192f6d4c 260 PrivateData->PpiData.NotifyListEnd\r
261 );\r
262\r
263\r
264 return EFI_SUCCESS;\r
265}\r
266\r
884200f9
SZ
267/**\r
268\r
269 This function installs an interface in the PEI PPI database by GUID. \r
270 The purpose of the service is to publish an interface that other parties\r
271 can use to call additional PEIMs.\r
272\r
273 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
274 @param PpiList Pointer to a list of PEI PPI Descriptors.\r
275\r
276 @retval EFI_SUCCESS if all PPIs in PpiList are successfully installed.\r
277 @retval EFI_INVALID_PARAMETER if PpiList is NULL pointer\r
278 if any PPI in PpiList is not valid\r
279 @retval EFI_OUT_OF_RESOURCES if there is no more memory resource to install PPI\r
280\r
281**/\r
282EFI_STATUS\r
283EFIAPI\r
284PeiInstallPpi (\r
285 IN CONST EFI_PEI_SERVICES **PeiServices,\r
286 IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList\r
287 )\r
288{\r
289 return InternalPeiInstallPpi (PeiServices, PpiList, FALSE);\r
290}\r
291\r
b1f6a7c6 292/**\r
293\r
0f65cdaa 294 This function reinstalls an interface in the PEI PPI database by GUID. \r
295 The purpose of the service is to publish an interface that other parties can \r
296 use to replace an interface of the same name in the protocol database with a \r
297 different interface.\r
b1f6a7c6 298\r
0f65cdaa 299 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
300 @param OldPpi Pointer to the old PEI PPI Descriptors.\r
301 @param NewPpi Pointer to the new PEI PPI Descriptors.\r
192f6d4c 302\r
0f65cdaa 303 @retval EFI_SUCCESS if the operation was successful\r
304 @retval EFI_INVALID_PARAMETER if OldPpi or NewPpi is NULL\r
305 @retval EFI_INVALID_PARAMETER if NewPpi is not valid\r
306 @retval EFI_NOT_FOUND if the PPI was not in the database\r
b1f6a7c6 307\r
308**/\r
192f6d4c 309EFI_STATUS\r
310EFIAPI\r
311PeiReInstallPpi (\r
0c2b5da8 312 IN CONST EFI_PEI_SERVICES **PeiServices,\r
313 IN CONST EFI_PEI_PPI_DESCRIPTOR *OldPpi,\r
314 IN CONST EFI_PEI_PPI_DESCRIPTOR *NewPpi\r
192f6d4c 315 )\r
192f6d4c 316{\r
317 PEI_CORE_INSTANCE *PrivateData;\r
318 INTN Index;\r
319\r
320\r
321 if ((OldPpi == NULL) || (NewPpi == NULL)) {\r
322 return EFI_INVALID_PARAMETER;\r
323 }\r
324\r
325 if ((NewPpi->Flags & EFI_PEI_PPI_DESCRIPTOR_PPI) == 0) {\r
326 return EFI_INVALID_PARAMETER;\r
327 }\r
328\r
329 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);\r
330\r
331 //\r
332 // Find the old PPI instance in the database. If we can not find it,\r
333 // return the EFI_NOT_FOUND error.\r
334 //\r
335 for (Index = 0; Index < PrivateData->PpiData.PpiListEnd; Index++) {\r
336 if (OldPpi == PrivateData->PpiData.PpiListPtrs[Index].Ppi) {\r
337 break;\r
338 }\r
339 }\r
340 if (Index == PrivateData->PpiData.PpiListEnd) {\r
341 return EFI_NOT_FOUND;\r
342 }\r
343\r
344 //\r
345 // Remove the old PPI from the database, add the new one.\r
58dcdada 346 //\r
192f6d4c 347 DEBUG((EFI_D_INFO, "Reinstall PPI: %g\n", NewPpi->Guid));\r
fe781940 348 ASSERT (Index < (INTN)(PcdGet32 (PcdPeiCoreMaxPpiSupported)));\r
0c2b5da8 349 PrivateData->PpiData.PpiListPtrs[Index].Ppi = (EFI_PEI_PPI_DESCRIPTOR *) NewPpi;\r
192f6d4c 350\r
351 //\r
352 // Dispatch any callback level notifies for the newly installed PPI.\r
353 //\r
354 DispatchNotify (\r
b0d803fe 355 PrivateData,\r
192f6d4c 356 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,\r
357 Index,\r
358 Index+1,\r
58dcdada 359 PrivateData->PpiData.DispatchListEnd,\r
192f6d4c 360 PrivateData->PpiData.NotifyListEnd\r
361 );\r
362\r
363\r
364 return EFI_SUCCESS;\r
365}\r
366\r
b1f6a7c6 367/**\r
368\r
369 Locate a given named PPI.\r
370\r
192f6d4c 371\r
0f65cdaa 372 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
373 @param Guid Pointer to GUID of the PPI.\r
374 @param Instance Instance Number to discover.\r
375 @param PpiDescriptor Pointer to reference the found descriptor. If not NULL,\r
376 returns a pointer to the descriptor (includes flags, etc)\r
377 @param Ppi Pointer to reference the found PPI\r
b1f6a7c6 378\r
379 @retval EFI_SUCCESS if the PPI is in the database\r
380 @retval EFI_NOT_FOUND if the PPI is not in the database\r
381\r
382**/\r
192f6d4c 383EFI_STATUS\r
384EFIAPI\r
385PeiLocatePpi (\r
0c2b5da8 386 IN CONST EFI_PEI_SERVICES **PeiServices,\r
387 IN CONST EFI_GUID *Guid,\r
0f65cdaa 388 IN UINTN Instance,\r
389 IN OUT EFI_PEI_PPI_DESCRIPTOR **PpiDescriptor,\r
390 IN OUT VOID **Ppi\r
192f6d4c 391 )\r
192f6d4c 392{\r
393 PEI_CORE_INSTANCE *PrivateData;\r
394 INTN Index;\r
395 EFI_GUID *CheckGuid;\r
396 EFI_PEI_PPI_DESCRIPTOR *TempPtr;\r
397\r
58dcdada 398\r
192f6d4c 399 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);\r
400\r
401 //\r
402 // Search the data base for the matching instance of the GUIDed PPI.\r
403 //\r
404 for (Index = 0; Index < PrivateData->PpiData.PpiListEnd; Index++) {\r
405 TempPtr = PrivateData->PpiData.PpiListPtrs[Index].Ppi;\r
406 CheckGuid = TempPtr->Guid;\r
407\r
408 //\r
409 // Don't use CompareGuid function here for performance reasons.\r
410 // Instead we compare the GUID as INT32 at a time and branch\r
411 // on the first failed comparison.\r
412 //\r
413 if ((((INT32 *)Guid)[0] == ((INT32 *)CheckGuid)[0]) &&\r
414 (((INT32 *)Guid)[1] == ((INT32 *)CheckGuid)[1]) &&\r
415 (((INT32 *)Guid)[2] == ((INT32 *)CheckGuid)[2]) &&\r
416 (((INT32 *)Guid)[3] == ((INT32 *)CheckGuid)[3])) {\r
417 if (Instance == 0) {\r
418\r
419 if (PpiDescriptor != NULL) {\r
420 *PpiDescriptor = TempPtr;\r
421 }\r
422\r
423 if (Ppi != NULL) {\r
424 *Ppi = TempPtr->Ppi;\r
425 }\r
426\r
427\r
428 return EFI_SUCCESS;\r
429 }\r
430 Instance--;\r
431 }\r
432 }\r
433\r
434 return EFI_NOT_FOUND;\r
435}\r
436\r
b1f6a7c6 437/**\r
192f6d4c 438\r
0f65cdaa 439 This function installs a notification service to be called back when a given \r
440 interface is installed or reinstalled. The purpose of the service is to publish \r
441 an interface that other parties can use to call additional PPIs that may materialize later.\r
b1f6a7c6 442\r
0f65cdaa 443 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
444 @param NotifyList Pointer to list of Descriptors to notify upon.\r
884200f9
SZ
445 @param Single TRUE if only single entry in the NotifyList.\r
446 FALSE if the NotifyList is ended with an entry which has the\r
447 EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST flag set in its Flags field.\r
b1f6a7c6 448\r
449 @retval EFI_SUCCESS if successful\r
450 @retval EFI_OUT_OF_RESOURCES if no space in the database\r
884200f9 451 @retval EFI_INVALID_PARAMETER if not a good descriptor\r
b1f6a7c6 452\r
453**/\r
192f6d4c 454EFI_STATUS\r
884200f9 455InternalPeiNotifyPpi (\r
0c2b5da8 456 IN CONST EFI_PEI_SERVICES **PeiServices,\r
884200f9
SZ
457 IN CONST EFI_PEI_NOTIFY_DESCRIPTOR *NotifyList,\r
458 IN BOOLEAN Single\r
192f6d4c 459 )\r
192f6d4c 460{\r
461 PEI_CORE_INSTANCE *PrivateData;\r
462 INTN Index;\r
463 INTN NotifyIndex;\r
464 INTN LastCallbackNotify;\r
465 EFI_PEI_NOTIFY_DESCRIPTOR *NotifyPtr;\r
466 UINTN NotifyDispatchCount;\r
467\r
468\r
469 NotifyDispatchCount = 0;\r
470\r
471 if (NotifyList == NULL) {\r
472 return EFI_INVALID_PARAMETER;\r
473 }\r
474\r
475 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);\r
476\r
477 Index = PrivateData->PpiData.NotifyListEnd;\r
478 LastCallbackNotify = Index;\r
479\r
480 //\r
481 // This is loop installs all Notify descriptors in the NotifyList. It is\r
482 // terminated by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last\r
483 // EFI_PEI_NOTIFY_DESCRIPTOR in the list.\r
484 //\r
485\r
486 for (;;) {\r
487 //\r
488 // Since PpiData is used for NotifyList and InstallList, max resource\r
489 // is reached if the Install reaches the PpiList\r
97b2c9b5 490 // PcdPeiCoreMaxPpiSupported can be set to a larger value in DSC to satisfy more Notify PPIs requirement.\r
192f6d4c 491 //\r
492 if (Index == PrivateData->PpiData.PpiListEnd - 1) {\r
493 return EFI_OUT_OF_RESOURCES;\r
494 }\r
58dcdada 495\r
192f6d4c 496 //\r
497 // If some of the PPI data is invalid restore original Notify PPI database value\r
498 //\r
499 if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_TYPES) == 0) {\r
500 PrivateData->PpiData.NotifyListEnd = LastCallbackNotify;\r
0e549d5b 501 DEBUG((EFI_D_ERROR, "ERROR -> InstallNotify: %g %p\n", NotifyList->Guid, NotifyList->Notify));\r
192f6d4c 502 return EFI_INVALID_PARAMETER;\r
503 }\r
58dcdada 504\r
192f6d4c 505 if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH) != 0) {\r
58dcdada 506 NotifyDispatchCount ++;\r
507 }\r
508\r
509 PrivateData->PpiData.PpiListPtrs[Index].Notify = (EFI_PEI_NOTIFY_DESCRIPTOR *) NotifyList;\r
510\r
192f6d4c 511 PrivateData->PpiData.NotifyListEnd--;\r
512 DEBUG((EFI_D_INFO, "Register PPI Notify: %g\n", NotifyList->Guid));\r
884200f9
SZ
513 if (Single) {\r
514 //\r
515 // Only single entry in the NotifyList.\r
516 //\r
517 break;\r
518 } else if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) ==\r
519 EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) {\r
520 //\r
521 // Continue until the end of the Notify List.\r
522 //\r
192f6d4c 523 break;\r
524 }\r
525 //\r
526 // Go the next descriptor. Remember the NotifyList moves down.\r
527 //\r
528 NotifyList++;\r
529 Index--;\r
530 }\r
58dcdada 531\r
192f6d4c 532 //\r
58dcdada 533 // If there is Dispatch Notify PPI installed put them on the bottom\r
192f6d4c 534 //\r
535 if (NotifyDispatchCount > 0) {\r
58dcdada 536 for (NotifyIndex = LastCallbackNotify; NotifyIndex > PrivateData->PpiData.NotifyListEnd; NotifyIndex--) {\r
192f6d4c 537 if ((PrivateData->PpiData.PpiListPtrs[NotifyIndex].Notify->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH) != 0) {\r
538 NotifyPtr = PrivateData->PpiData.PpiListPtrs[NotifyIndex].Notify;\r
58dcdada 539\r
192f6d4c 540 for (Index = NotifyIndex; Index < PrivateData->PpiData.DispatchListEnd; Index++){\r
541 PrivateData->PpiData.PpiListPtrs[Index].Notify = PrivateData->PpiData.PpiListPtrs[Index + 1].Notify;\r
542 }\r
543 PrivateData->PpiData.PpiListPtrs[Index].Notify = NotifyPtr;\r
58dcdada 544 PrivateData->PpiData.DispatchListEnd--;\r
192f6d4c 545 }\r
546 }\r
58dcdada 547\r
548 LastCallbackNotify -= NotifyDispatchCount;\r
192f6d4c 549 }\r
58dcdada 550\r
192f6d4c 551 //\r
552 // Dispatch any callback level notifies for all previously installed PPIs.\r
553 //\r
554 DispatchNotify (\r
b0d803fe 555 PrivateData,\r
192f6d4c 556 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,\r
557 0,\r
558 PrivateData->PpiData.PpiListEnd,\r
559 LastCallbackNotify,\r
560 PrivateData->PpiData.NotifyListEnd\r
561 );\r
58dcdada 562\r
192f6d4c 563 return EFI_SUCCESS;\r
564}\r
565\r
884200f9
SZ
566/**\r
567\r
568 This function installs a notification service to be called back when a given \r
569 interface is installed or reinstalled. The purpose of the service is to publish \r
570 an interface that other parties can use to call additional PPIs that may materialize later.\r
571\r
572 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
573 @param NotifyList Pointer to list of Descriptors to notify upon.\r
574\r
575 @retval EFI_SUCCESS if successful\r
576 @retval EFI_OUT_OF_RESOURCES if no space in the database\r
577 @retval EFI_INVALID_PARAMETER if not a good descriptor\r
578\r
579**/\r
580EFI_STATUS\r
581EFIAPI\r
582PeiNotifyPpi (\r
583 IN CONST EFI_PEI_SERVICES **PeiServices,\r
584 IN CONST EFI_PEI_NOTIFY_DESCRIPTOR *NotifyList\r
585 )\r
586{\r
587 return InternalPeiNotifyPpi (PeiServices, NotifyList, FALSE);\r
588}\r
589\r
192f6d4c 590\r
b1f6a7c6 591/**\r
192f6d4c 592\r
593 Process the Notify List at dispatch level.\r
594\r
b1f6a7c6 595 @param PrivateData PeiCore's private data structure.\r
192f6d4c 596\r
b1f6a7c6 597**/\r
598VOID\r
599ProcessNotifyList (\r
600 IN PEI_CORE_INSTANCE *PrivateData\r
601 )\r
192f6d4c 602{\r
192f6d4c 603 INTN TempValue;\r
58dcdada 604\r
192f6d4c 605 while (TRUE) {\r
606 //\r
607 // Check if the PEIM that was just dispatched resulted in any\r
608 // Notifies getting installed. If so, go process any dispatch\r
609 // level Notifies that match the previouly installed PPIs.\r
58dcdada 610 // Use "while" instead of "if" since DispatchNotify can modify\r
192f6d4c 611 // DispatchListEnd (with NotifyPpi) so we have to iterate until the same.\r
612 //\r
613 while (PrivateData->PpiData.LastDispatchedNotify != PrivateData->PpiData.DispatchListEnd) {\r
614 TempValue = PrivateData->PpiData.DispatchListEnd;\r
615 DispatchNotify (\r
b0d803fe 616 PrivateData,\r
192f6d4c 617 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH,\r
618 0,\r
619 PrivateData->PpiData.LastDispatchedInstall,\r
620 PrivateData->PpiData.LastDispatchedNotify,\r
621 PrivateData->PpiData.DispatchListEnd\r
622 );\r
623 PrivateData->PpiData.LastDispatchedNotify = TempValue;\r
624 }\r
58dcdada 625\r
626\r
192f6d4c 627 //\r
628 // Check if the PEIM that was just dispatched resulted in any\r
629 // PPIs getting installed. If so, go process any dispatch\r
630 // level Notifies that match the installed PPIs.\r
58dcdada 631 // Use "while" instead of "if" since DispatchNotify can modify\r
192f6d4c 632 // PpiListEnd (with InstallPpi) so we have to iterate until the same.\r
633 //\r
634 while (PrivateData->PpiData.LastDispatchedInstall != PrivateData->PpiData.PpiListEnd) {\r
635 TempValue = PrivateData->PpiData.PpiListEnd;\r
636 DispatchNotify (\r
b0d803fe 637 PrivateData,\r
192f6d4c 638 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH,\r
639 PrivateData->PpiData.LastDispatchedInstall,\r
640 PrivateData->PpiData.PpiListEnd,\r
fe781940 641 PcdGet32 (PcdPeiCoreMaxPpiSupported)-1,\r
192f6d4c 642 PrivateData->PpiData.DispatchListEnd\r
643 );\r
644 PrivateData->PpiData.LastDispatchedInstall = TempValue;\r
645 }\r
58dcdada 646\r
192f6d4c 647 if (PrivateData->PpiData.LastDispatchedNotify == PrivateData->PpiData.DispatchListEnd) {\r
648 break;\r
649 }\r
58dcdada 650 }\r
192f6d4c 651 return;\r
652}\r
653\r
b1f6a7c6 654/**\r
655\r
656 Dispatch notifications.\r
657\r
658 @param PrivateData PeiCore's private data structure\r
659 @param NotifyType Type of notify to fire.\r
660 @param InstallStartIndex Install Beginning index.\r
661 @param InstallStopIndex Install Ending index.\r
662 @param NotifyStartIndex Notify Beginning index.\r
663 @param NotifyStopIndex Notify Ending index.\r
664\r
665**/\r
192f6d4c 666VOID\r
667DispatchNotify (\r
b0d803fe 668 IN PEI_CORE_INSTANCE *PrivateData,\r
192f6d4c 669 IN UINTN NotifyType,\r
670 IN INTN InstallStartIndex,\r
671 IN INTN InstallStopIndex,\r
672 IN INTN NotifyStartIndex,\r
673 IN INTN NotifyStopIndex\r
674 )\r
192f6d4c 675{\r
192f6d4c 676 INTN Index1;\r
677 INTN Index2;\r
678 EFI_GUID *SearchGuid;\r
679 EFI_GUID *CheckGuid;\r
680 EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor;\r
681\r
192f6d4c 682 //\r
683 // Remember that Installs moves up and Notifies moves down.\r
684 //\r
685 for (Index1 = NotifyStartIndex; Index1 > NotifyStopIndex; Index1--) {\r
686 NotifyDescriptor = PrivateData->PpiData.PpiListPtrs[Index1].Notify;\r
687\r
688 CheckGuid = NotifyDescriptor->Guid;\r
689\r
690 for (Index2 = InstallStartIndex; Index2 < InstallStopIndex; Index2++) {\r
691 SearchGuid = PrivateData->PpiData.PpiListPtrs[Index2].Ppi->Guid;\r
692 //\r
693 // Don't use CompareGuid function here for performance reasons.\r
694 // Instead we compare the GUID as INT32 at a time and branch\r
695 // on the first failed comparison.\r
696 //\r
697 if ((((INT32 *)SearchGuid)[0] == ((INT32 *)CheckGuid)[0]) &&\r
698 (((INT32 *)SearchGuid)[1] == ((INT32 *)CheckGuid)[1]) &&\r
699 (((INT32 *)SearchGuid)[2] == ((INT32 *)CheckGuid)[2]) &&\r
700 (((INT32 *)SearchGuid)[3] == ((INT32 *)CheckGuid)[3])) {\r
0e549d5b 701 DEBUG ((EFI_D_INFO, "Notify: PPI Guid: %g, Peim notify entry point: %p\n",\r
58dcdada 702 SearchGuid,\r
192f6d4c 703 NotifyDescriptor->Notify\r
704 ));\r
705 NotifyDescriptor->Notify (\r
284c8400 706 (EFI_PEI_SERVICES **) GetPeiServicesTablePointer (),\r
192f6d4c 707 NotifyDescriptor,\r
708 (PrivateData->PpiData.PpiListPtrs[Index2].Ppi)->Ppi\r
709 );\r
710 }\r
711 }\r
712 }\r
192f6d4c 713}\r
714\r
884200f9
SZ
715/**\r
716 Process PpiList from SEC phase.\r
717\r
718 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
719 @param PpiList Points to a list of one or more PPI descriptors to be installed initially by the PEI core.\r
720 These PPI's will be installed and/or immediately signaled if they are notification type.\r
721\r
722**/\r
723VOID\r
724ProcessPpiListFromSec (\r
725 IN CONST EFI_PEI_SERVICES **PeiServices,\r
726 IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList\r
727 )\r
728{\r
729 EFI_STATUS Status;\r
730\r
731 for (;;) {\r
732 if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_TYPES) != 0) {\r
733 //\r
734 // It is a notification PPI.\r
735 //\r
736 Status = InternalPeiNotifyPpi (PeiServices, (CONST EFI_PEI_NOTIFY_DESCRIPTOR *) PpiList, TRUE);\r
737 ASSERT_EFI_ERROR (Status);\r
738 } else {\r
739 //\r
740 // It is a normal PPI.\r
741 //\r
742 Status = InternalPeiInstallPpi (PeiServices, PpiList, TRUE);\r
743 ASSERT_EFI_ERROR (Status);\r
744 }\r
745\r
746 if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) == EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) {\r
747 //\r
748 // Continue until the end of the PPI List.\r
749 //\r
750 break;\r
751 }\r
752\r
753 PpiList++;\r
754 }\r
755}\r
756\r