]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Pei/Ppi/Ppi.c
IntelSiliconPkg: Clean up source files
[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
b2374cec 106 Migrate PPI Pointers from the temporary memory 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 123 if (Index < PrivateData->PpiData.PpiListEnd || Index > PrivateData->PpiData.NotifyListEnd) {\r
b2374cec
SZ
124 if (PrivateData->MemoryPages.Size != 0) {\r
125 //\r
126 // Convert PPI pointer in old memory pages\r
127 // It needs to be done before Convert PPI pointer in old Heap\r
128 //\r
129 ConvertSinglePpiPointer (\r
130 &PrivateData->PpiData.PpiListPtrs[Index],\r
131 (UINTN)PrivateData->MemoryPages.Base,\r
132 (UINTN)PrivateData->MemoryPages.Base + PrivateData->MemoryPages.Size,\r
133 PrivateData->MemoryPages.Offset,\r
134 PrivateData->MemoryPages.OffsetPositive\r
135 );\r
136 }\r
137\r
0f9ebb32
LG
138 //\r
139 // Convert PPI pointer in old Heap\r
140 //\r
de74668f 141 ConvertSinglePpiPointer (\r
0f9ebb32
LG
142 &PrivateData->PpiData.PpiListPtrs[Index],\r
143 (UINTN)SecCoreData->PeiTemporaryRamBase,\r
144 (UINTN)SecCoreData->PeiTemporaryRamBase + SecCoreData->PeiTemporaryRamSize,\r
145 PrivateData->HeapOffset,\r
146 PrivateData->HeapOffsetPositive\r
147 );\r
148 \r
149 //\r
150 // Convert PPI pointer in old Stack\r
151 //\r
de74668f 152 ConvertSinglePpiPointer (\r
0f9ebb32
LG
153 &PrivateData->PpiData.PpiListPtrs[Index],\r
154 (UINTN)SecCoreData->StackBase,\r
155 (UINTN)SecCoreData->StackBase + SecCoreData->StackSize,\r
156 PrivateData->StackOffset,\r
157 PrivateData->StackOffsetPositive\r
158 );\r
159 \r
160 //\r
161 // Convert PPI pointer in old TempRam Hole\r
162 //\r
163 for (IndexHole = 0; IndexHole < HOLE_MAX_NUMBER; IndexHole ++) {\r
164 if (PrivateData->HoleData[IndexHole].Size == 0) {\r
165 continue;\r
2740a797 166 }\r
0f9ebb32 167 \r
de74668f 168 ConvertSinglePpiPointer (\r
0f9ebb32
LG
169 &PrivateData->PpiData.PpiListPtrs[Index],\r
170 (UINTN)PrivateData->HoleData[IndexHole].Base,\r
171 (UINTN)PrivateData->HoleData[IndexHole].Base + PrivateData->HoleData[IndexHole].Size,\r
172 PrivateData->HoleData[IndexHole].Offset,\r
173 PrivateData->HoleData[IndexHole].OffsetPositive\r
174 );\r
192f6d4c 175 }\r
176 }\r
177 }\r
178}\r
179\r
b1f6a7c6 180/**\r
192f6d4c 181\r
0f65cdaa 182 This function installs an interface in the PEI PPI database by GUID. \r
183 The purpose of the service is to publish an interface that other parties\r
184 can use to call additional PEIMs.\r
192f6d4c 185\r
0f65cdaa 186 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
187 @param PpiList Pointer to a list of PEI PPI Descriptors.\r
884200f9
SZ
188 @param Single TRUE if only single entry in the PpiList.\r
189 FALSE if the PpiList is ended with an entry which has the\r
190 EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST flag set in its Flags field.\r
b1f6a7c6 191\r
0f65cdaa 192 @retval EFI_SUCCESS if all PPIs in PpiList are successfully installed.\r
193 @retval EFI_INVALID_PARAMETER if PpiList is NULL pointer\r
731bd38e 194 if any PPI in PpiList is not valid\r
0f65cdaa 195 @retval EFI_OUT_OF_RESOURCES if there is no more memory resource to install PPI\r
b1f6a7c6 196\r
197**/\r
192f6d4c 198EFI_STATUS\r
884200f9 199InternalPeiInstallPpi (\r
0c2b5da8 200 IN CONST EFI_PEI_SERVICES **PeiServices,\r
884200f9
SZ
201 IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList,\r
202 IN BOOLEAN Single\r
192f6d4c 203 )\r
192f6d4c 204{\r
205 PEI_CORE_INSTANCE *PrivateData;\r
206 INTN Index;\r
207 INTN LastCallbackInstall;\r
208\r
209\r
210 if (PpiList == NULL) {\r
211 return EFI_INVALID_PARAMETER;\r
212 }\r
213\r
214 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);\r
215\r
216 Index = PrivateData->PpiData.PpiListEnd;\r
217 LastCallbackInstall = Index;\r
218\r
219 //\r
220 // This is loop installs all PPI descriptors in the PpiList. It is terminated\r
221 // by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last\r
222 // EFI_PEI_PPI_DESCRIPTOR in the list.\r
223 //\r
58dcdada 224\r
192f6d4c 225 for (;;) {\r
226 //\r
731bd38e 227 // Since PpiData is used for NotifyList and PpiList, max resource\r
192f6d4c 228 // is reached if the Install reaches the NotifyList\r
97b2c9b5 229 // PcdPeiCoreMaxPpiSupported can be set to a larger value in DSC to satisfy more PPI requirement.\r
192f6d4c 230 //\r
231 if (Index == PrivateData->PpiData.NotifyListEnd + 1) {\r
232 return EFI_OUT_OF_RESOURCES;\r
233 }\r
234 //\r
58dcdada 235 // Check if it is a valid PPI.\r
192f6d4c 236 // If not, rollback list to exclude all in this list.\r
237 // Try to indicate which item failed.\r
238 //\r
239 if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_PPI) == 0) {\r
240 PrivateData->PpiData.PpiListEnd = LastCallbackInstall;\r
0e549d5b 241 DEBUG((EFI_D_ERROR, "ERROR -> InstallPpi: %g %p\n", PpiList->Guid, PpiList->Ppi));\r
192f6d4c 242 return EFI_INVALID_PARAMETER;\r
243 }\r
244\r
58dcdada 245 DEBUG((EFI_D_INFO, "Install PPI: %g\n", PpiList->Guid));\r
246 PrivateData->PpiData.PpiListPtrs[Index].Ppi = (EFI_PEI_PPI_DESCRIPTOR*) PpiList;\r
192f6d4c 247 PrivateData->PpiData.PpiListEnd++;\r
58dcdada 248\r
884200f9
SZ
249 if (Single) {\r
250 //\r
251 // Only single entry in the PpiList.\r
252 //\r
253 break;\r
254 } else if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) ==\r
255 EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) {\r
256 //\r
257 // Continue until the end of the PPI List.\r
258 //\r
192f6d4c 259 break;\r
260 }\r
261 PpiList++;\r
262 Index++;\r
263 }\r
264\r
265 //\r
266 // Dispatch any callback level notifies for newly installed PPIs.\r
267 //\r
268 DispatchNotify (\r
b0d803fe 269 PrivateData,\r
192f6d4c 270 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,\r
271 LastCallbackInstall,\r
272 PrivateData->PpiData.PpiListEnd,\r
58dcdada 273 PrivateData->PpiData.DispatchListEnd,\r
192f6d4c 274 PrivateData->PpiData.NotifyListEnd\r
275 );\r
276\r
277\r
278 return EFI_SUCCESS;\r
279}\r
280\r
884200f9
SZ
281/**\r
282\r
283 This function installs an interface in the PEI PPI database by GUID. \r
284 The purpose of the service is to publish an interface that other parties\r
285 can use to call additional PEIMs.\r
286\r
287 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
288 @param PpiList Pointer to a list of PEI PPI Descriptors.\r
289\r
290 @retval EFI_SUCCESS if all PPIs in PpiList are successfully installed.\r
291 @retval EFI_INVALID_PARAMETER if PpiList is NULL pointer\r
292 if any PPI in PpiList is not valid\r
293 @retval EFI_OUT_OF_RESOURCES if there is no more memory resource to install PPI\r
294\r
295**/\r
296EFI_STATUS\r
297EFIAPI\r
298PeiInstallPpi (\r
299 IN CONST EFI_PEI_SERVICES **PeiServices,\r
300 IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList\r
301 )\r
302{\r
303 return InternalPeiInstallPpi (PeiServices, PpiList, FALSE);\r
304}\r
305\r
b1f6a7c6 306/**\r
307\r
0f65cdaa 308 This function reinstalls an interface in the PEI PPI database by GUID. \r
309 The purpose of the service is to publish an interface that other parties can \r
310 use to replace an interface of the same name in the protocol database with a \r
311 different interface.\r
b1f6a7c6 312\r
0f65cdaa 313 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
314 @param OldPpi Pointer to the old PEI PPI Descriptors.\r
315 @param NewPpi Pointer to the new PEI PPI Descriptors.\r
192f6d4c 316\r
0f65cdaa 317 @retval EFI_SUCCESS if the operation was successful\r
318 @retval EFI_INVALID_PARAMETER if OldPpi or NewPpi is NULL\r
319 @retval EFI_INVALID_PARAMETER if NewPpi is not valid\r
320 @retval EFI_NOT_FOUND if the PPI was not in the database\r
b1f6a7c6 321\r
322**/\r
192f6d4c 323EFI_STATUS\r
324EFIAPI\r
325PeiReInstallPpi (\r
0c2b5da8 326 IN CONST EFI_PEI_SERVICES **PeiServices,\r
327 IN CONST EFI_PEI_PPI_DESCRIPTOR *OldPpi,\r
328 IN CONST EFI_PEI_PPI_DESCRIPTOR *NewPpi\r
192f6d4c 329 )\r
192f6d4c 330{\r
331 PEI_CORE_INSTANCE *PrivateData;\r
332 INTN Index;\r
333\r
334\r
335 if ((OldPpi == NULL) || (NewPpi == NULL)) {\r
336 return EFI_INVALID_PARAMETER;\r
337 }\r
338\r
339 if ((NewPpi->Flags & EFI_PEI_PPI_DESCRIPTOR_PPI) == 0) {\r
340 return EFI_INVALID_PARAMETER;\r
341 }\r
342\r
343 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);\r
344\r
345 //\r
346 // Find the old PPI instance in the database. If we can not find it,\r
347 // return the EFI_NOT_FOUND error.\r
348 //\r
349 for (Index = 0; Index < PrivateData->PpiData.PpiListEnd; Index++) {\r
350 if (OldPpi == PrivateData->PpiData.PpiListPtrs[Index].Ppi) {\r
351 break;\r
352 }\r
353 }\r
354 if (Index == PrivateData->PpiData.PpiListEnd) {\r
355 return EFI_NOT_FOUND;\r
356 }\r
357\r
358 //\r
359 // Remove the old PPI from the database, add the new one.\r
58dcdada 360 //\r
192f6d4c 361 DEBUG((EFI_D_INFO, "Reinstall PPI: %g\n", NewPpi->Guid));\r
fe781940 362 ASSERT (Index < (INTN)(PcdGet32 (PcdPeiCoreMaxPpiSupported)));\r
0c2b5da8 363 PrivateData->PpiData.PpiListPtrs[Index].Ppi = (EFI_PEI_PPI_DESCRIPTOR *) NewPpi;\r
192f6d4c 364\r
365 //\r
366 // Dispatch any callback level notifies for the newly installed PPI.\r
367 //\r
368 DispatchNotify (\r
b0d803fe 369 PrivateData,\r
192f6d4c 370 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,\r
371 Index,\r
372 Index+1,\r
58dcdada 373 PrivateData->PpiData.DispatchListEnd,\r
192f6d4c 374 PrivateData->PpiData.NotifyListEnd\r
375 );\r
376\r
377\r
378 return EFI_SUCCESS;\r
379}\r
380\r
b1f6a7c6 381/**\r
382\r
383 Locate a given named PPI.\r
384\r
192f6d4c 385\r
0f65cdaa 386 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
387 @param Guid Pointer to GUID of the PPI.\r
388 @param Instance Instance Number to discover.\r
389 @param PpiDescriptor Pointer to reference the found descriptor. If not NULL,\r
390 returns a pointer to the descriptor (includes flags, etc)\r
391 @param Ppi Pointer to reference the found PPI\r
b1f6a7c6 392\r
393 @retval EFI_SUCCESS if the PPI is in the database\r
394 @retval EFI_NOT_FOUND if the PPI is not in the database\r
395\r
396**/\r
192f6d4c 397EFI_STATUS\r
398EFIAPI\r
399PeiLocatePpi (\r
0c2b5da8 400 IN CONST EFI_PEI_SERVICES **PeiServices,\r
401 IN CONST EFI_GUID *Guid,\r
0f65cdaa 402 IN UINTN Instance,\r
403 IN OUT EFI_PEI_PPI_DESCRIPTOR **PpiDescriptor,\r
404 IN OUT VOID **Ppi\r
192f6d4c 405 )\r
192f6d4c 406{\r
407 PEI_CORE_INSTANCE *PrivateData;\r
408 INTN Index;\r
409 EFI_GUID *CheckGuid;\r
410 EFI_PEI_PPI_DESCRIPTOR *TempPtr;\r
411\r
58dcdada 412\r
192f6d4c 413 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);\r
414\r
415 //\r
416 // Search the data base for the matching instance of the GUIDed PPI.\r
417 //\r
418 for (Index = 0; Index < PrivateData->PpiData.PpiListEnd; Index++) {\r
419 TempPtr = PrivateData->PpiData.PpiListPtrs[Index].Ppi;\r
420 CheckGuid = TempPtr->Guid;\r
421\r
422 //\r
423 // Don't use CompareGuid function here for performance reasons.\r
424 // Instead we compare the GUID as INT32 at a time and branch\r
425 // on the first failed comparison.\r
426 //\r
427 if ((((INT32 *)Guid)[0] == ((INT32 *)CheckGuid)[0]) &&\r
428 (((INT32 *)Guid)[1] == ((INT32 *)CheckGuid)[1]) &&\r
429 (((INT32 *)Guid)[2] == ((INT32 *)CheckGuid)[2]) &&\r
430 (((INT32 *)Guid)[3] == ((INT32 *)CheckGuid)[3])) {\r
431 if (Instance == 0) {\r
432\r
433 if (PpiDescriptor != NULL) {\r
434 *PpiDescriptor = TempPtr;\r
435 }\r
436\r
437 if (Ppi != NULL) {\r
438 *Ppi = TempPtr->Ppi;\r
439 }\r
440\r
441\r
442 return EFI_SUCCESS;\r
443 }\r
444 Instance--;\r
445 }\r
446 }\r
447\r
448 return EFI_NOT_FOUND;\r
449}\r
450\r
b1f6a7c6 451/**\r
192f6d4c 452\r
0f65cdaa 453 This function installs a notification service to be called back when a given \r
454 interface is installed or reinstalled. The purpose of the service is to publish \r
455 an interface that other parties can use to call additional PPIs that may materialize later.\r
b1f6a7c6 456\r
0f65cdaa 457 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
458 @param NotifyList Pointer to list of Descriptors to notify upon.\r
884200f9
SZ
459 @param Single TRUE if only single entry in the NotifyList.\r
460 FALSE if the NotifyList is ended with an entry which has the\r
461 EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST flag set in its Flags field.\r
b1f6a7c6 462\r
463 @retval EFI_SUCCESS if successful\r
464 @retval EFI_OUT_OF_RESOURCES if no space in the database\r
884200f9 465 @retval EFI_INVALID_PARAMETER if not a good descriptor\r
b1f6a7c6 466\r
467**/\r
192f6d4c 468EFI_STATUS\r
884200f9 469InternalPeiNotifyPpi (\r
0c2b5da8 470 IN CONST EFI_PEI_SERVICES **PeiServices,\r
884200f9
SZ
471 IN CONST EFI_PEI_NOTIFY_DESCRIPTOR *NotifyList,\r
472 IN BOOLEAN Single\r
192f6d4c 473 )\r
192f6d4c 474{\r
475 PEI_CORE_INSTANCE *PrivateData;\r
476 INTN Index;\r
477 INTN NotifyIndex;\r
478 INTN LastCallbackNotify;\r
479 EFI_PEI_NOTIFY_DESCRIPTOR *NotifyPtr;\r
480 UINTN NotifyDispatchCount;\r
481\r
482\r
483 NotifyDispatchCount = 0;\r
484\r
485 if (NotifyList == NULL) {\r
486 return EFI_INVALID_PARAMETER;\r
487 }\r
488\r
489 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);\r
490\r
491 Index = PrivateData->PpiData.NotifyListEnd;\r
492 LastCallbackNotify = Index;\r
493\r
494 //\r
495 // This is loop installs all Notify descriptors in the NotifyList. It is\r
496 // terminated by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last\r
497 // EFI_PEI_NOTIFY_DESCRIPTOR in the list.\r
498 //\r
499\r
500 for (;;) {\r
501 //\r
502 // Since PpiData is used for NotifyList and InstallList, max resource\r
503 // is reached if the Install reaches the PpiList\r
97b2c9b5 504 // PcdPeiCoreMaxPpiSupported can be set to a larger value in DSC to satisfy more Notify PPIs requirement.\r
192f6d4c 505 //\r
506 if (Index == PrivateData->PpiData.PpiListEnd - 1) {\r
507 return EFI_OUT_OF_RESOURCES;\r
508 }\r
58dcdada 509\r
192f6d4c 510 //\r
511 // If some of the PPI data is invalid restore original Notify PPI database value\r
512 //\r
513 if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_TYPES) == 0) {\r
514 PrivateData->PpiData.NotifyListEnd = LastCallbackNotify;\r
0e549d5b 515 DEBUG((EFI_D_ERROR, "ERROR -> InstallNotify: %g %p\n", NotifyList->Guid, NotifyList->Notify));\r
192f6d4c 516 return EFI_INVALID_PARAMETER;\r
517 }\r
58dcdada 518\r
192f6d4c 519 if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH) != 0) {\r
58dcdada 520 NotifyDispatchCount ++;\r
521 }\r
522\r
523 PrivateData->PpiData.PpiListPtrs[Index].Notify = (EFI_PEI_NOTIFY_DESCRIPTOR *) NotifyList;\r
524\r
192f6d4c 525 PrivateData->PpiData.NotifyListEnd--;\r
526 DEBUG((EFI_D_INFO, "Register PPI Notify: %g\n", NotifyList->Guid));\r
884200f9
SZ
527 if (Single) {\r
528 //\r
529 // Only single entry in the NotifyList.\r
530 //\r
531 break;\r
532 } else if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) ==\r
533 EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) {\r
534 //\r
535 // Continue until the end of the Notify List.\r
536 //\r
192f6d4c 537 break;\r
538 }\r
539 //\r
540 // Go the next descriptor. Remember the NotifyList moves down.\r
541 //\r
542 NotifyList++;\r
543 Index--;\r
544 }\r
58dcdada 545\r
192f6d4c 546 //\r
58dcdada 547 // If there is Dispatch Notify PPI installed put them on the bottom\r
192f6d4c 548 //\r
549 if (NotifyDispatchCount > 0) {\r
58dcdada 550 for (NotifyIndex = LastCallbackNotify; NotifyIndex > PrivateData->PpiData.NotifyListEnd; NotifyIndex--) {\r
192f6d4c 551 if ((PrivateData->PpiData.PpiListPtrs[NotifyIndex].Notify->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH) != 0) {\r
552 NotifyPtr = PrivateData->PpiData.PpiListPtrs[NotifyIndex].Notify;\r
58dcdada 553\r
192f6d4c 554 for (Index = NotifyIndex; Index < PrivateData->PpiData.DispatchListEnd; Index++){\r
555 PrivateData->PpiData.PpiListPtrs[Index].Notify = PrivateData->PpiData.PpiListPtrs[Index + 1].Notify;\r
556 }\r
557 PrivateData->PpiData.PpiListPtrs[Index].Notify = NotifyPtr;\r
58dcdada 558 PrivateData->PpiData.DispatchListEnd--;\r
192f6d4c 559 }\r
560 }\r
58dcdada 561\r
562 LastCallbackNotify -= NotifyDispatchCount;\r
192f6d4c 563 }\r
58dcdada 564\r
192f6d4c 565 //\r
566 // Dispatch any callback level notifies for all previously installed PPIs.\r
567 //\r
568 DispatchNotify (\r
b0d803fe 569 PrivateData,\r
192f6d4c 570 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,\r
571 0,\r
572 PrivateData->PpiData.PpiListEnd,\r
573 LastCallbackNotify,\r
574 PrivateData->PpiData.NotifyListEnd\r
575 );\r
58dcdada 576\r
192f6d4c 577 return EFI_SUCCESS;\r
578}\r
579\r
884200f9
SZ
580/**\r
581\r
582 This function installs a notification service to be called back when a given \r
583 interface is installed or reinstalled. The purpose of the service is to publish \r
584 an interface that other parties can use to call additional PPIs that may materialize later.\r
585\r
586 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
587 @param NotifyList Pointer to list of Descriptors to notify upon.\r
588\r
589 @retval EFI_SUCCESS if successful\r
590 @retval EFI_OUT_OF_RESOURCES if no space in the database\r
591 @retval EFI_INVALID_PARAMETER if not a good descriptor\r
592\r
593**/\r
594EFI_STATUS\r
595EFIAPI\r
596PeiNotifyPpi (\r
597 IN CONST EFI_PEI_SERVICES **PeiServices,\r
598 IN CONST EFI_PEI_NOTIFY_DESCRIPTOR *NotifyList\r
599 )\r
600{\r
601 return InternalPeiNotifyPpi (PeiServices, NotifyList, FALSE);\r
602}\r
603\r
192f6d4c 604\r
b1f6a7c6 605/**\r
192f6d4c 606\r
607 Process the Notify List at dispatch level.\r
608\r
b1f6a7c6 609 @param PrivateData PeiCore's private data structure.\r
192f6d4c 610\r
b1f6a7c6 611**/\r
612VOID\r
613ProcessNotifyList (\r
614 IN PEI_CORE_INSTANCE *PrivateData\r
615 )\r
192f6d4c 616{\r
192f6d4c 617 INTN TempValue;\r
58dcdada 618\r
192f6d4c 619 while (TRUE) {\r
620 //\r
621 // Check if the PEIM that was just dispatched resulted in any\r
622 // Notifies getting installed. If so, go process any dispatch\r
623 // level Notifies that match the previouly installed PPIs.\r
58dcdada 624 // Use "while" instead of "if" since DispatchNotify can modify\r
192f6d4c 625 // DispatchListEnd (with NotifyPpi) so we have to iterate until the same.\r
626 //\r
627 while (PrivateData->PpiData.LastDispatchedNotify != PrivateData->PpiData.DispatchListEnd) {\r
628 TempValue = PrivateData->PpiData.DispatchListEnd;\r
629 DispatchNotify (\r
b0d803fe 630 PrivateData,\r
192f6d4c 631 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH,\r
632 0,\r
633 PrivateData->PpiData.LastDispatchedInstall,\r
634 PrivateData->PpiData.LastDispatchedNotify,\r
635 PrivateData->PpiData.DispatchListEnd\r
636 );\r
637 PrivateData->PpiData.LastDispatchedNotify = TempValue;\r
638 }\r
58dcdada 639\r
640\r
192f6d4c 641 //\r
642 // Check if the PEIM that was just dispatched resulted in any\r
643 // PPIs getting installed. If so, go process any dispatch\r
644 // level Notifies that match the installed PPIs.\r
58dcdada 645 // Use "while" instead of "if" since DispatchNotify can modify\r
192f6d4c 646 // PpiListEnd (with InstallPpi) so we have to iterate until the same.\r
647 //\r
648 while (PrivateData->PpiData.LastDispatchedInstall != PrivateData->PpiData.PpiListEnd) {\r
649 TempValue = PrivateData->PpiData.PpiListEnd;\r
650 DispatchNotify (\r
b0d803fe 651 PrivateData,\r
192f6d4c 652 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH,\r
653 PrivateData->PpiData.LastDispatchedInstall,\r
654 PrivateData->PpiData.PpiListEnd,\r
fe781940 655 PcdGet32 (PcdPeiCoreMaxPpiSupported)-1,\r
192f6d4c 656 PrivateData->PpiData.DispatchListEnd\r
657 );\r
658 PrivateData->PpiData.LastDispatchedInstall = TempValue;\r
659 }\r
58dcdada 660\r
192f6d4c 661 if (PrivateData->PpiData.LastDispatchedNotify == PrivateData->PpiData.DispatchListEnd) {\r
662 break;\r
663 }\r
58dcdada 664 }\r
192f6d4c 665 return;\r
666}\r
667\r
b1f6a7c6 668/**\r
669\r
670 Dispatch notifications.\r
671\r
672 @param PrivateData PeiCore's private data structure\r
673 @param NotifyType Type of notify to fire.\r
674 @param InstallStartIndex Install Beginning index.\r
675 @param InstallStopIndex Install Ending index.\r
676 @param NotifyStartIndex Notify Beginning index.\r
677 @param NotifyStopIndex Notify Ending index.\r
678\r
679**/\r
192f6d4c 680VOID\r
681DispatchNotify (\r
b0d803fe 682 IN PEI_CORE_INSTANCE *PrivateData,\r
192f6d4c 683 IN UINTN NotifyType,\r
684 IN INTN InstallStartIndex,\r
685 IN INTN InstallStopIndex,\r
686 IN INTN NotifyStartIndex,\r
687 IN INTN NotifyStopIndex\r
688 )\r
192f6d4c 689{\r
192f6d4c 690 INTN Index1;\r
691 INTN Index2;\r
692 EFI_GUID *SearchGuid;\r
693 EFI_GUID *CheckGuid;\r
694 EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor;\r
695\r
192f6d4c 696 //\r
697 // Remember that Installs moves up and Notifies moves down.\r
698 //\r
699 for (Index1 = NotifyStartIndex; Index1 > NotifyStopIndex; Index1--) {\r
700 NotifyDescriptor = PrivateData->PpiData.PpiListPtrs[Index1].Notify;\r
701\r
702 CheckGuid = NotifyDescriptor->Guid;\r
703\r
704 for (Index2 = InstallStartIndex; Index2 < InstallStopIndex; Index2++) {\r
705 SearchGuid = PrivateData->PpiData.PpiListPtrs[Index2].Ppi->Guid;\r
706 //\r
707 // Don't use CompareGuid function here for performance reasons.\r
708 // Instead we compare the GUID as INT32 at a time and branch\r
709 // on the first failed comparison.\r
710 //\r
711 if ((((INT32 *)SearchGuid)[0] == ((INT32 *)CheckGuid)[0]) &&\r
712 (((INT32 *)SearchGuid)[1] == ((INT32 *)CheckGuid)[1]) &&\r
713 (((INT32 *)SearchGuid)[2] == ((INT32 *)CheckGuid)[2]) &&\r
714 (((INT32 *)SearchGuid)[3] == ((INT32 *)CheckGuid)[3])) {\r
0e549d5b 715 DEBUG ((EFI_D_INFO, "Notify: PPI Guid: %g, Peim notify entry point: %p\n",\r
58dcdada 716 SearchGuid,\r
192f6d4c 717 NotifyDescriptor->Notify\r
718 ));\r
719 NotifyDescriptor->Notify (\r
284c8400 720 (EFI_PEI_SERVICES **) GetPeiServicesTablePointer (),\r
192f6d4c 721 NotifyDescriptor,\r
722 (PrivateData->PpiData.PpiListPtrs[Index2].Ppi)->Ppi\r
723 );\r
724 }\r
725 }\r
726 }\r
192f6d4c 727}\r
728\r
884200f9
SZ
729/**\r
730 Process PpiList from SEC phase.\r
731\r
732 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
733 @param PpiList Points to a list of one or more PPI descriptors to be installed initially by the PEI core.\r
734 These PPI's will be installed and/or immediately signaled if they are notification type.\r
735\r
736**/\r
737VOID\r
738ProcessPpiListFromSec (\r
739 IN CONST EFI_PEI_SERVICES **PeiServices,\r
740 IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList\r
741 )\r
742{\r
483e2cdd
SZ
743 EFI_STATUS Status;\r
744 EFI_SEC_HOB_DATA_PPI *SecHobDataPpi;\r
745 EFI_HOB_GENERIC_HEADER *SecHobList;\r
884200f9
SZ
746\r
747 for (;;) {\r
748 if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_TYPES) != 0) {\r
749 //\r
750 // It is a notification PPI.\r
751 //\r
752 Status = InternalPeiNotifyPpi (PeiServices, (CONST EFI_PEI_NOTIFY_DESCRIPTOR *) PpiList, TRUE);\r
753 ASSERT_EFI_ERROR (Status);\r
754 } else {\r
755 //\r
756 // It is a normal PPI.\r
757 //\r
758 Status = InternalPeiInstallPpi (PeiServices, PpiList, TRUE);\r
759 ASSERT_EFI_ERROR (Status);\r
760 }\r
761\r
762 if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) == EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) {\r
763 //\r
764 // Continue until the end of the PPI List.\r
765 //\r
766 break;\r
767 }\r
768\r
769 PpiList++;\r
770 }\r
483e2cdd
SZ
771\r
772 //\r
773 // If the EFI_SEC_HOB_DATA_PPI is in the list of PPIs passed to the PEI entry point,\r
774 // the PEI Foundation will call the GetHobs() member function and install all HOBs\r
775 // returned into the HOB list. It does this after installing all PPIs passed from SEC\r
776 // into the PPI database and before dispatching any PEIMs.\r
777 //\r
778 Status = PeiLocatePpi (PeiServices, &gEfiSecHobDataPpiGuid, 0, NULL, (VOID **) &SecHobDataPpi);\r
779 if (!EFI_ERROR (Status)) {\r
780 Status = SecHobDataPpi->GetHobs (SecHobDataPpi, &SecHobList);\r
781 if (!EFI_ERROR (Status)) {\r
782 Status = PeiInstallSecHobData (PeiServices, SecHobList);\r
783 ASSERT_EFI_ERROR (Status);\r
784 }\r
785 }\r
884200f9
SZ
786}\r
787\r