]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Pei/Ppi/Ppi.c
MdeModulePkg: Fix use-after-free error in InstallConfigurationTable()
[mirror_edk2.git] / MdeModulePkg / Core / Pei / Ppi / Ppi.c
CommitLineData
615c6dd0 1/** @file\r
b1f6a7c6 2 EFI PEI Core PPI services\r
3 \r
fe781940 4Copyright (c) 2006 - 2014, 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
b1f6a7c6 174\r
0f65cdaa 175 @retval EFI_SUCCESS if all PPIs in PpiList are successfully installed.\r
176 @retval EFI_INVALID_PARAMETER if PpiList is NULL pointer\r
731bd38e 177 if any PPI in PpiList is not valid\r
0f65cdaa 178 @retval EFI_OUT_OF_RESOURCES if there is no more memory resource to install PPI\r
b1f6a7c6 179\r
180**/\r
192f6d4c 181EFI_STATUS\r
182EFIAPI\r
183PeiInstallPpi (\r
0c2b5da8 184 IN CONST EFI_PEI_SERVICES **PeiServices,\r
185 IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList\r
192f6d4c 186 )\r
192f6d4c 187{\r
188 PEI_CORE_INSTANCE *PrivateData;\r
189 INTN Index;\r
190 INTN LastCallbackInstall;\r
191\r
192\r
193 if (PpiList == NULL) {\r
194 return EFI_INVALID_PARAMETER;\r
195 }\r
196\r
197 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);\r
198\r
199 Index = PrivateData->PpiData.PpiListEnd;\r
200 LastCallbackInstall = Index;\r
201\r
202 //\r
203 // This is loop installs all PPI descriptors in the PpiList. It is terminated\r
204 // by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last\r
205 // EFI_PEI_PPI_DESCRIPTOR in the list.\r
206 //\r
58dcdada 207\r
192f6d4c 208 for (;;) {\r
209 //\r
731bd38e 210 // Since PpiData is used for NotifyList and PpiList, max resource\r
192f6d4c 211 // is reached if the Install reaches the NotifyList\r
97b2c9b5 212 // PcdPeiCoreMaxPpiSupported can be set to a larger value in DSC to satisfy more PPI requirement.\r
192f6d4c 213 //\r
214 if (Index == PrivateData->PpiData.NotifyListEnd + 1) {\r
215 return EFI_OUT_OF_RESOURCES;\r
216 }\r
217 //\r
58dcdada 218 // Check if it is a valid PPI.\r
192f6d4c 219 // If not, rollback list to exclude all in this list.\r
220 // Try to indicate which item failed.\r
221 //\r
222 if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_PPI) == 0) {\r
223 PrivateData->PpiData.PpiListEnd = LastCallbackInstall;\r
0e549d5b 224 DEBUG((EFI_D_ERROR, "ERROR -> InstallPpi: %g %p\n", PpiList->Guid, PpiList->Ppi));\r
192f6d4c 225 return EFI_INVALID_PARAMETER;\r
226 }\r
227\r
58dcdada 228 DEBUG((EFI_D_INFO, "Install PPI: %g\n", PpiList->Guid));\r
229 PrivateData->PpiData.PpiListPtrs[Index].Ppi = (EFI_PEI_PPI_DESCRIPTOR*) PpiList;\r
192f6d4c 230 PrivateData->PpiData.PpiListEnd++;\r
58dcdada 231\r
192f6d4c 232 //\r
233 // Continue until the end of the PPI List.\r
234 //\r
58dcdada 235 if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) ==\r
192f6d4c 236 EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) {\r
237 break;\r
238 }\r
239 PpiList++;\r
240 Index++;\r
241 }\r
242\r
243 //\r
244 // Dispatch any callback level notifies for newly installed PPIs.\r
245 //\r
246 DispatchNotify (\r
b0d803fe 247 PrivateData,\r
192f6d4c 248 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,\r
249 LastCallbackInstall,\r
250 PrivateData->PpiData.PpiListEnd,\r
58dcdada 251 PrivateData->PpiData.DispatchListEnd,\r
192f6d4c 252 PrivateData->PpiData.NotifyListEnd\r
253 );\r
254\r
255\r
256 return EFI_SUCCESS;\r
257}\r
258\r
b1f6a7c6 259/**\r
260\r
0f65cdaa 261 This function reinstalls an interface in the PEI PPI database by GUID. \r
262 The purpose of the service is to publish an interface that other parties can \r
263 use to replace an interface of the same name in the protocol database with a \r
264 different interface.\r
b1f6a7c6 265\r
0f65cdaa 266 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
267 @param OldPpi Pointer to the old PEI PPI Descriptors.\r
268 @param NewPpi Pointer to the new PEI PPI Descriptors.\r
192f6d4c 269\r
0f65cdaa 270 @retval EFI_SUCCESS if the operation was successful\r
271 @retval EFI_INVALID_PARAMETER if OldPpi or NewPpi is NULL\r
272 @retval EFI_INVALID_PARAMETER if NewPpi is not valid\r
273 @retval EFI_NOT_FOUND if the PPI was not in the database\r
b1f6a7c6 274\r
275**/\r
192f6d4c 276EFI_STATUS\r
277EFIAPI\r
278PeiReInstallPpi (\r
0c2b5da8 279 IN CONST EFI_PEI_SERVICES **PeiServices,\r
280 IN CONST EFI_PEI_PPI_DESCRIPTOR *OldPpi,\r
281 IN CONST EFI_PEI_PPI_DESCRIPTOR *NewPpi\r
192f6d4c 282 )\r
192f6d4c 283{\r
284 PEI_CORE_INSTANCE *PrivateData;\r
285 INTN Index;\r
286\r
287\r
288 if ((OldPpi == NULL) || (NewPpi == NULL)) {\r
289 return EFI_INVALID_PARAMETER;\r
290 }\r
291\r
292 if ((NewPpi->Flags & EFI_PEI_PPI_DESCRIPTOR_PPI) == 0) {\r
293 return EFI_INVALID_PARAMETER;\r
294 }\r
295\r
296 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);\r
297\r
298 //\r
299 // Find the old PPI instance in the database. If we can not find it,\r
300 // return the EFI_NOT_FOUND error.\r
301 //\r
302 for (Index = 0; Index < PrivateData->PpiData.PpiListEnd; Index++) {\r
303 if (OldPpi == PrivateData->PpiData.PpiListPtrs[Index].Ppi) {\r
304 break;\r
305 }\r
306 }\r
307 if (Index == PrivateData->PpiData.PpiListEnd) {\r
308 return EFI_NOT_FOUND;\r
309 }\r
310\r
311 //\r
312 // Remove the old PPI from the database, add the new one.\r
58dcdada 313 //\r
192f6d4c 314 DEBUG((EFI_D_INFO, "Reinstall PPI: %g\n", NewPpi->Guid));\r
fe781940 315 ASSERT (Index < (INTN)(PcdGet32 (PcdPeiCoreMaxPpiSupported)));\r
0c2b5da8 316 PrivateData->PpiData.PpiListPtrs[Index].Ppi = (EFI_PEI_PPI_DESCRIPTOR *) NewPpi;\r
192f6d4c 317\r
318 //\r
319 // Dispatch any callback level notifies for the newly installed PPI.\r
320 //\r
321 DispatchNotify (\r
b0d803fe 322 PrivateData,\r
192f6d4c 323 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,\r
324 Index,\r
325 Index+1,\r
58dcdada 326 PrivateData->PpiData.DispatchListEnd,\r
192f6d4c 327 PrivateData->PpiData.NotifyListEnd\r
328 );\r
329\r
330\r
331 return EFI_SUCCESS;\r
332}\r
333\r
b1f6a7c6 334/**\r
335\r
336 Locate a given named PPI.\r
337\r
192f6d4c 338\r
0f65cdaa 339 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
340 @param Guid Pointer to GUID of the PPI.\r
341 @param Instance Instance Number to discover.\r
342 @param PpiDescriptor Pointer to reference the found descriptor. If not NULL,\r
343 returns a pointer to the descriptor (includes flags, etc)\r
344 @param Ppi Pointer to reference the found PPI\r
b1f6a7c6 345\r
346 @retval EFI_SUCCESS if the PPI is in the database\r
347 @retval EFI_NOT_FOUND if the PPI is not in the database\r
348\r
349**/\r
192f6d4c 350EFI_STATUS\r
351EFIAPI\r
352PeiLocatePpi (\r
0c2b5da8 353 IN CONST EFI_PEI_SERVICES **PeiServices,\r
354 IN CONST EFI_GUID *Guid,\r
0f65cdaa 355 IN UINTN Instance,\r
356 IN OUT EFI_PEI_PPI_DESCRIPTOR **PpiDescriptor,\r
357 IN OUT VOID **Ppi\r
192f6d4c 358 )\r
192f6d4c 359{\r
360 PEI_CORE_INSTANCE *PrivateData;\r
361 INTN Index;\r
362 EFI_GUID *CheckGuid;\r
363 EFI_PEI_PPI_DESCRIPTOR *TempPtr;\r
364\r
58dcdada 365\r
192f6d4c 366 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);\r
367\r
368 //\r
369 // Search the data base for the matching instance of the GUIDed PPI.\r
370 //\r
371 for (Index = 0; Index < PrivateData->PpiData.PpiListEnd; Index++) {\r
372 TempPtr = PrivateData->PpiData.PpiListPtrs[Index].Ppi;\r
373 CheckGuid = TempPtr->Guid;\r
374\r
375 //\r
376 // Don't use CompareGuid function here for performance reasons.\r
377 // Instead we compare the GUID as INT32 at a time and branch\r
378 // on the first failed comparison.\r
379 //\r
380 if ((((INT32 *)Guid)[0] == ((INT32 *)CheckGuid)[0]) &&\r
381 (((INT32 *)Guid)[1] == ((INT32 *)CheckGuid)[1]) &&\r
382 (((INT32 *)Guid)[2] == ((INT32 *)CheckGuid)[2]) &&\r
383 (((INT32 *)Guid)[3] == ((INT32 *)CheckGuid)[3])) {\r
384 if (Instance == 0) {\r
385\r
386 if (PpiDescriptor != NULL) {\r
387 *PpiDescriptor = TempPtr;\r
388 }\r
389\r
390 if (Ppi != NULL) {\r
391 *Ppi = TempPtr->Ppi;\r
392 }\r
393\r
394\r
395 return EFI_SUCCESS;\r
396 }\r
397 Instance--;\r
398 }\r
399 }\r
400\r
401 return EFI_NOT_FOUND;\r
402}\r
403\r
b1f6a7c6 404/**\r
192f6d4c 405\r
0f65cdaa 406 This function installs a notification service to be called back when a given \r
407 interface is installed or reinstalled. The purpose of the service is to publish \r
408 an interface that other parties can use to call additional PPIs that may materialize later.\r
b1f6a7c6 409\r
0f65cdaa 410 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
411 @param NotifyList Pointer to list of Descriptors to notify upon.\r
b1f6a7c6 412\r
413 @retval EFI_SUCCESS if successful\r
414 @retval EFI_OUT_OF_RESOURCES if no space in the database\r
415 @retval EFI_INVALID_PARAMETER if not a good decriptor\r
416\r
417**/\r
192f6d4c 418EFI_STATUS\r
419EFIAPI\r
420PeiNotifyPpi (\r
0c2b5da8 421 IN CONST EFI_PEI_SERVICES **PeiServices,\r
422 IN CONST EFI_PEI_NOTIFY_DESCRIPTOR *NotifyList\r
192f6d4c 423 )\r
192f6d4c 424{\r
425 PEI_CORE_INSTANCE *PrivateData;\r
426 INTN Index;\r
427 INTN NotifyIndex;\r
428 INTN LastCallbackNotify;\r
429 EFI_PEI_NOTIFY_DESCRIPTOR *NotifyPtr;\r
430 UINTN NotifyDispatchCount;\r
431\r
432\r
433 NotifyDispatchCount = 0;\r
434\r
435 if (NotifyList == NULL) {\r
436 return EFI_INVALID_PARAMETER;\r
437 }\r
438\r
439 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);\r
440\r
441 Index = PrivateData->PpiData.NotifyListEnd;\r
442 LastCallbackNotify = Index;\r
443\r
444 //\r
445 // This is loop installs all Notify descriptors in the NotifyList. It is\r
446 // terminated by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last\r
447 // EFI_PEI_NOTIFY_DESCRIPTOR in the list.\r
448 //\r
449\r
450 for (;;) {\r
451 //\r
452 // Since PpiData is used for NotifyList and InstallList, max resource\r
453 // is reached if the Install reaches the PpiList\r
97b2c9b5 454 // PcdPeiCoreMaxPpiSupported can be set to a larger value in DSC to satisfy more Notify PPIs requirement.\r
192f6d4c 455 //\r
456 if (Index == PrivateData->PpiData.PpiListEnd - 1) {\r
457 return EFI_OUT_OF_RESOURCES;\r
458 }\r
58dcdada 459\r
192f6d4c 460 //\r
461 // If some of the PPI data is invalid restore original Notify PPI database value\r
462 //\r
463 if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_TYPES) == 0) {\r
464 PrivateData->PpiData.NotifyListEnd = LastCallbackNotify;\r
0e549d5b 465 DEBUG((EFI_D_ERROR, "ERROR -> InstallNotify: %g %p\n", NotifyList->Guid, NotifyList->Notify));\r
192f6d4c 466 return EFI_INVALID_PARAMETER;\r
467 }\r
58dcdada 468\r
192f6d4c 469 if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH) != 0) {\r
58dcdada 470 NotifyDispatchCount ++;\r
471 }\r
472\r
473 PrivateData->PpiData.PpiListPtrs[Index].Notify = (EFI_PEI_NOTIFY_DESCRIPTOR *) NotifyList;\r
474\r
192f6d4c 475 PrivateData->PpiData.NotifyListEnd--;\r
476 DEBUG((EFI_D_INFO, "Register PPI Notify: %g\n", NotifyList->Guid));\r
477 if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) ==\r
478 EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) {\r
479 break;\r
480 }\r
481 //\r
482 // Go the next descriptor. Remember the NotifyList moves down.\r
483 //\r
484 NotifyList++;\r
485 Index--;\r
486 }\r
58dcdada 487\r
192f6d4c 488 //\r
58dcdada 489 // If there is Dispatch Notify PPI installed put them on the bottom\r
192f6d4c 490 //\r
491 if (NotifyDispatchCount > 0) {\r
58dcdada 492 for (NotifyIndex = LastCallbackNotify; NotifyIndex > PrivateData->PpiData.NotifyListEnd; NotifyIndex--) {\r
192f6d4c 493 if ((PrivateData->PpiData.PpiListPtrs[NotifyIndex].Notify->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH) != 0) {\r
494 NotifyPtr = PrivateData->PpiData.PpiListPtrs[NotifyIndex].Notify;\r
58dcdada 495\r
192f6d4c 496 for (Index = NotifyIndex; Index < PrivateData->PpiData.DispatchListEnd; Index++){\r
497 PrivateData->PpiData.PpiListPtrs[Index].Notify = PrivateData->PpiData.PpiListPtrs[Index + 1].Notify;\r
498 }\r
499 PrivateData->PpiData.PpiListPtrs[Index].Notify = NotifyPtr;\r
58dcdada 500 PrivateData->PpiData.DispatchListEnd--;\r
192f6d4c 501 }\r
502 }\r
58dcdada 503\r
504 LastCallbackNotify -= NotifyDispatchCount;\r
192f6d4c 505 }\r
58dcdada 506\r
192f6d4c 507 //\r
508 // Dispatch any callback level notifies for all previously installed PPIs.\r
509 //\r
510 DispatchNotify (\r
b0d803fe 511 PrivateData,\r
192f6d4c 512 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,\r
513 0,\r
514 PrivateData->PpiData.PpiListEnd,\r
515 LastCallbackNotify,\r
516 PrivateData->PpiData.NotifyListEnd\r
517 );\r
58dcdada 518\r
192f6d4c 519 return EFI_SUCCESS;\r
520}\r
521\r
522\r
b1f6a7c6 523/**\r
192f6d4c 524\r
525 Process the Notify List at dispatch level.\r
526\r
b1f6a7c6 527 @param PrivateData PeiCore's private data structure.\r
192f6d4c 528\r
b1f6a7c6 529**/\r
530VOID\r
531ProcessNotifyList (\r
532 IN PEI_CORE_INSTANCE *PrivateData\r
533 )\r
192f6d4c 534{\r
192f6d4c 535 INTN TempValue;\r
58dcdada 536\r
192f6d4c 537 while (TRUE) {\r
538 //\r
539 // Check if the PEIM that was just dispatched resulted in any\r
540 // Notifies getting installed. If so, go process any dispatch\r
541 // level Notifies that match the previouly installed PPIs.\r
58dcdada 542 // Use "while" instead of "if" since DispatchNotify can modify\r
192f6d4c 543 // DispatchListEnd (with NotifyPpi) so we have to iterate until the same.\r
544 //\r
545 while (PrivateData->PpiData.LastDispatchedNotify != PrivateData->PpiData.DispatchListEnd) {\r
546 TempValue = PrivateData->PpiData.DispatchListEnd;\r
547 DispatchNotify (\r
b0d803fe 548 PrivateData,\r
192f6d4c 549 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH,\r
550 0,\r
551 PrivateData->PpiData.LastDispatchedInstall,\r
552 PrivateData->PpiData.LastDispatchedNotify,\r
553 PrivateData->PpiData.DispatchListEnd\r
554 );\r
555 PrivateData->PpiData.LastDispatchedNotify = TempValue;\r
556 }\r
58dcdada 557\r
558\r
192f6d4c 559 //\r
560 // Check if the PEIM that was just dispatched resulted in any\r
561 // PPIs getting installed. If so, go process any dispatch\r
562 // level Notifies that match the installed PPIs.\r
58dcdada 563 // Use "while" instead of "if" since DispatchNotify can modify\r
192f6d4c 564 // PpiListEnd (with InstallPpi) so we have to iterate until the same.\r
565 //\r
566 while (PrivateData->PpiData.LastDispatchedInstall != PrivateData->PpiData.PpiListEnd) {\r
567 TempValue = PrivateData->PpiData.PpiListEnd;\r
568 DispatchNotify (\r
b0d803fe 569 PrivateData,\r
192f6d4c 570 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH,\r
571 PrivateData->PpiData.LastDispatchedInstall,\r
572 PrivateData->PpiData.PpiListEnd,\r
fe781940 573 PcdGet32 (PcdPeiCoreMaxPpiSupported)-1,\r
192f6d4c 574 PrivateData->PpiData.DispatchListEnd\r
575 );\r
576 PrivateData->PpiData.LastDispatchedInstall = TempValue;\r
577 }\r
58dcdada 578\r
192f6d4c 579 if (PrivateData->PpiData.LastDispatchedNotify == PrivateData->PpiData.DispatchListEnd) {\r
580 break;\r
581 }\r
58dcdada 582 }\r
192f6d4c 583 return;\r
584}\r
585\r
b1f6a7c6 586/**\r
587\r
588 Dispatch notifications.\r
589\r
590 @param PrivateData PeiCore's private data structure\r
591 @param NotifyType Type of notify to fire.\r
592 @param InstallStartIndex Install Beginning index.\r
593 @param InstallStopIndex Install Ending index.\r
594 @param NotifyStartIndex Notify Beginning index.\r
595 @param NotifyStopIndex Notify Ending index.\r
596\r
597**/\r
192f6d4c 598VOID\r
599DispatchNotify (\r
b0d803fe 600 IN PEI_CORE_INSTANCE *PrivateData,\r
192f6d4c 601 IN UINTN NotifyType,\r
602 IN INTN InstallStartIndex,\r
603 IN INTN InstallStopIndex,\r
604 IN INTN NotifyStartIndex,\r
605 IN INTN NotifyStopIndex\r
606 )\r
192f6d4c 607{\r
192f6d4c 608 INTN Index1;\r
609 INTN Index2;\r
610 EFI_GUID *SearchGuid;\r
611 EFI_GUID *CheckGuid;\r
612 EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor;\r
613\r
192f6d4c 614 //\r
615 // Remember that Installs moves up and Notifies moves down.\r
616 //\r
617 for (Index1 = NotifyStartIndex; Index1 > NotifyStopIndex; Index1--) {\r
618 NotifyDescriptor = PrivateData->PpiData.PpiListPtrs[Index1].Notify;\r
619\r
620 CheckGuid = NotifyDescriptor->Guid;\r
621\r
622 for (Index2 = InstallStartIndex; Index2 < InstallStopIndex; Index2++) {\r
623 SearchGuid = PrivateData->PpiData.PpiListPtrs[Index2].Ppi->Guid;\r
624 //\r
625 // Don't use CompareGuid function here for performance reasons.\r
626 // Instead we compare the GUID as INT32 at a time and branch\r
627 // on the first failed comparison.\r
628 //\r
629 if ((((INT32 *)SearchGuid)[0] == ((INT32 *)CheckGuid)[0]) &&\r
630 (((INT32 *)SearchGuid)[1] == ((INT32 *)CheckGuid)[1]) &&\r
631 (((INT32 *)SearchGuid)[2] == ((INT32 *)CheckGuid)[2]) &&\r
632 (((INT32 *)SearchGuid)[3] == ((INT32 *)CheckGuid)[3])) {\r
0e549d5b 633 DEBUG ((EFI_D_INFO, "Notify: PPI Guid: %g, Peim notify entry point: %p\n",\r
58dcdada 634 SearchGuid,\r
192f6d4c 635 NotifyDescriptor->Notify\r
636 ));\r
637 NotifyDescriptor->Notify (\r
284c8400 638 (EFI_PEI_SERVICES **) GetPeiServicesTablePointer (),\r
192f6d4c 639 NotifyDescriptor,\r
640 (PrivateData->PpiData.PpiListPtrs[Index2].Ppi)->Ppi\r
641 );\r
642 }\r
643 }\r
644 }\r
192f6d4c 645}\r
646\r