/src/hbfa-fl/HBFA/UefiHostTestPkg/Library/PeiServicesTablePointerLibHost/Ppi.c
Line | Count | Source (jump to first uncovered line) |
1 | | /** @file |
2 | | EFI PEI Core PPI services |
3 | | |
4 | | Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR> |
5 | | SPDX-License-Identifier: BSD-2-Clause-Patent |
6 | | |
7 | | **/ |
8 | | |
9 | | #include "PeiMain.h" |
10 | | |
11 | | /** |
12 | | |
13 | | This function installs an interface in the PEI PPI database by GUID. |
14 | | The purpose of the service is to publish an interface that other parties |
15 | | can use to call additional PEIMs. |
16 | | |
17 | | @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. |
18 | | @param PpiList Pointer to a list of PEI PPI Descriptors. |
19 | | @param Single TRUE if only single entry in the PpiList. |
20 | | FALSE if the PpiList is ended with an entry which has the |
21 | | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST flag set in its Flags field. |
22 | | |
23 | | @retval EFI_SUCCESS if all PPIs in PpiList are successfully installed. |
24 | | @retval EFI_INVALID_PARAMETER if PpiList is NULL pointer |
25 | | if any PPI in PpiList is not valid |
26 | | @retval EFI_OUT_OF_RESOURCES if there is no more memory resource to install PPI |
27 | | |
28 | | **/ |
29 | | EFI_STATUS |
30 | | InternalPeiInstallPpi ( |
31 | | IN CONST EFI_PEI_SERVICES **PeiServices, |
32 | | IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList, |
33 | | IN BOOLEAN Single |
34 | | ) |
35 | 0 | { |
36 | 0 | PEI_CORE_INSTANCE *PrivateData; |
37 | 0 | PEI_PPI_LIST *PpiListPointer; |
38 | 0 | UINTN Index; |
39 | 0 | UINTN LastCount; |
40 | 0 | VOID *TempPtr; |
41 | |
|
42 | 0 | if (PpiList == NULL) { |
43 | 0 | return EFI_INVALID_PARAMETER; |
44 | 0 | } |
45 | | |
46 | 0 | PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); |
47 | |
|
48 | 0 | PpiListPointer = &PrivateData->PpiData.PpiList; |
49 | 0 | Index = PpiListPointer->CurrentCount; |
50 | 0 | LastCount = Index; |
51 | | |
52 | | // |
53 | | // This is loop installs all PPI descriptors in the PpiList. It is terminated |
54 | | // by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last |
55 | | // EFI_PEI_PPI_DESCRIPTOR in the list. |
56 | | // |
57 | |
|
58 | 0 | for (;;) { |
59 | | // |
60 | | // Check if it is a valid PPI. |
61 | | // If not, rollback list to exclude all in this list. |
62 | | // Try to indicate which item failed. |
63 | | // |
64 | 0 | if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_PPI) == 0) { |
65 | 0 | PpiListPointer->CurrentCount = LastCount; |
66 | 0 | DEBUG((EFI_D_ERROR, "ERROR -> InstallPpi: %g %p\n", PpiList->Guid, PpiList->Ppi)); |
67 | 0 | return EFI_INVALID_PARAMETER; |
68 | 0 | } |
69 | | |
70 | 0 | if (Index >= PpiListPointer->MaxCount) { |
71 | | // |
72 | | // Run out of room, grow the buffer. |
73 | | // |
74 | 0 | TempPtr = AllocateZeroPool ( |
75 | 0 | sizeof (PEI_PPI_LIST_POINTERS) * (PpiListPointer->MaxCount + PPI_GROWTH_STEP) |
76 | 0 | ); |
77 | 0 | ASSERT (TempPtr != NULL); |
78 | 0 | CopyMem ( |
79 | 0 | TempPtr, |
80 | 0 | PpiListPointer->PpiPtrs, |
81 | 0 | sizeof (PEI_PPI_LIST_POINTERS) * PpiListPointer->MaxCount |
82 | 0 | ); |
83 | 0 | PpiListPointer->PpiPtrs = TempPtr; |
84 | 0 | PpiListPointer->MaxCount = PpiListPointer->MaxCount + PPI_GROWTH_STEP; |
85 | 0 | } |
86 | |
|
87 | 0 | DEBUG((EFI_D_INFO, "Install PPI: %g\n", PpiList->Guid)); |
88 | 0 | PpiListPointer->PpiPtrs[Index].Ppi = (EFI_PEI_PPI_DESCRIPTOR *) PpiList; |
89 | 0 | Index++; |
90 | 0 | PpiListPointer->CurrentCount++; |
91 | |
|
92 | 0 | if (Single) { |
93 | | // |
94 | | // Only single entry in the PpiList. |
95 | | // |
96 | 0 | break; |
97 | 0 | } else if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) == |
98 | 0 | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) { |
99 | | // |
100 | | // Continue until the end of the PPI List. |
101 | | // |
102 | 0 | break; |
103 | 0 | } |
104 | | // |
105 | | // Go to the next descriptor. |
106 | | // |
107 | 0 | PpiList++; |
108 | 0 | } |
109 | | |
110 | | // |
111 | | // Process any callback level notifies for newly installed PPIs. |
112 | | // |
113 | 0 | ProcessNotify ( |
114 | 0 | PrivateData, |
115 | 0 | EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK, |
116 | 0 | LastCount, |
117 | 0 | PpiListPointer->CurrentCount, |
118 | 0 | 0, |
119 | 0 | PrivateData->PpiData.CallbackNotifyList.CurrentCount |
120 | 0 | ); |
121 | |
|
122 | 0 | return EFI_SUCCESS; |
123 | 0 | } |
124 | | |
125 | | /** |
126 | | |
127 | | This function installs an interface in the PEI PPI database by GUID. |
128 | | The purpose of the service is to publish an interface that other parties |
129 | | can use to call additional PEIMs. |
130 | | |
131 | | @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. |
132 | | @param PpiList Pointer to a list of PEI PPI Descriptors. |
133 | | |
134 | | @retval EFI_SUCCESS if all PPIs in PpiList are successfully installed. |
135 | | @retval EFI_INVALID_PARAMETER if PpiList is NULL pointer |
136 | | if any PPI in PpiList is not valid |
137 | | @retval EFI_OUT_OF_RESOURCES if there is no more memory resource to install PPI |
138 | | |
139 | | **/ |
140 | | EFI_STATUS |
141 | | EFIAPI |
142 | | PeiInstallPpi ( |
143 | | IN CONST EFI_PEI_SERVICES **PeiServices, |
144 | | IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList |
145 | | ) |
146 | 0 | { |
147 | 0 | return InternalPeiInstallPpi (PeiServices, PpiList, FALSE); |
148 | 0 | } |
149 | | |
150 | | /** |
151 | | |
152 | | This function reinstalls an interface in the PEI PPI database by GUID. |
153 | | The purpose of the service is to publish an interface that other parties can |
154 | | use to replace an interface of the same name in the protocol database with a |
155 | | different interface. |
156 | | |
157 | | @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. |
158 | | @param OldPpi Pointer to the old PEI PPI Descriptors. |
159 | | @param NewPpi Pointer to the new PEI PPI Descriptors. |
160 | | |
161 | | @retval EFI_SUCCESS if the operation was successful |
162 | | @retval EFI_INVALID_PARAMETER if OldPpi or NewPpi is NULL |
163 | | @retval EFI_INVALID_PARAMETER if NewPpi is not valid |
164 | | @retval EFI_NOT_FOUND if the PPI was not in the database |
165 | | |
166 | | **/ |
167 | | EFI_STATUS |
168 | | EFIAPI |
169 | | PeiReInstallPpi ( |
170 | | IN CONST EFI_PEI_SERVICES **PeiServices, |
171 | | IN CONST EFI_PEI_PPI_DESCRIPTOR *OldPpi, |
172 | | IN CONST EFI_PEI_PPI_DESCRIPTOR *NewPpi |
173 | | ) |
174 | 0 | { |
175 | 0 | PEI_CORE_INSTANCE *PrivateData; |
176 | 0 | UINTN Index; |
177 | | |
178 | |
|
179 | 0 | if ((OldPpi == NULL) || (NewPpi == NULL)) { |
180 | 0 | return EFI_INVALID_PARAMETER; |
181 | 0 | } |
182 | | |
183 | 0 | if ((NewPpi->Flags & EFI_PEI_PPI_DESCRIPTOR_PPI) == 0) { |
184 | 0 | return EFI_INVALID_PARAMETER; |
185 | 0 | } |
186 | | |
187 | 0 | PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); |
188 | | |
189 | | // |
190 | | // Find the old PPI instance in the database. If we can not find it, |
191 | | // return the EFI_NOT_FOUND error. |
192 | | // |
193 | 0 | for (Index = 0; Index < PrivateData->PpiData.PpiList.CurrentCount; Index++) { |
194 | 0 | if (OldPpi == PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi) { |
195 | 0 | break; |
196 | 0 | } |
197 | 0 | } |
198 | 0 | if (Index == PrivateData->PpiData.PpiList.CurrentCount) { |
199 | 0 | return EFI_NOT_FOUND; |
200 | 0 | } |
201 | | |
202 | | // |
203 | | // Replace the old PPI with the new one. |
204 | | // |
205 | 0 | DEBUG((EFI_D_INFO, "Reinstall PPI: %g\n", NewPpi->Guid)); |
206 | 0 | PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi = (EFI_PEI_PPI_DESCRIPTOR *) NewPpi; |
207 | | |
208 | | // |
209 | | // Process any callback level notifies for the newly installed PPI. |
210 | | // |
211 | 0 | ProcessNotify ( |
212 | 0 | PrivateData, |
213 | 0 | EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK, |
214 | 0 | Index, |
215 | 0 | Index+1, |
216 | 0 | 0, |
217 | 0 | PrivateData->PpiData.CallbackNotifyList.CurrentCount |
218 | 0 | ); |
219 | |
|
220 | 0 | return EFI_SUCCESS; |
221 | 0 | } |
222 | | |
223 | | /** |
224 | | |
225 | | Locate a given named PPI. |
226 | | |
227 | | |
228 | | @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. |
229 | | @param Guid Pointer to GUID of the PPI. |
230 | | @param Instance Instance Number to discover. |
231 | | @param PpiDescriptor Pointer to reference the found descriptor. If not NULL, |
232 | | returns a pointer to the descriptor (includes flags, etc) |
233 | | @param Ppi Pointer to reference the found PPI |
234 | | |
235 | | @retval EFI_SUCCESS if the PPI is in the database |
236 | | @retval EFI_NOT_FOUND if the PPI is not in the database |
237 | | |
238 | | **/ |
239 | | EFI_STATUS |
240 | | EFIAPI |
241 | | PeiLocatePpi ( |
242 | | IN CONST EFI_PEI_SERVICES **PeiServices, |
243 | | IN CONST EFI_GUID *Guid, |
244 | | IN UINTN Instance, |
245 | | IN OUT EFI_PEI_PPI_DESCRIPTOR **PpiDescriptor, |
246 | | IN OUT VOID **Ppi |
247 | | ) |
248 | 0 | { |
249 | 0 | PEI_CORE_INSTANCE *PrivateData; |
250 | 0 | UINTN Index; |
251 | 0 | EFI_GUID *CheckGuid; |
252 | 0 | EFI_PEI_PPI_DESCRIPTOR *TempPtr; |
253 | | |
254 | |
|
255 | 0 | PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); |
256 | | |
257 | | // |
258 | | // Search the data base for the matching instance of the GUIDed PPI. |
259 | | // |
260 | 0 | for (Index = 0; Index < PrivateData->PpiData.PpiList.CurrentCount; Index++) { |
261 | 0 | TempPtr = PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi; |
262 | 0 | CheckGuid = TempPtr->Guid; |
263 | | |
264 | | // |
265 | | // Don't use CompareGuid function here for performance reasons. |
266 | | // Instead we compare the GUID as INT32 at a time and branch |
267 | | // on the first failed comparison. |
268 | | // |
269 | 0 | if ((((INT32 *)Guid)[0] == ((INT32 *)CheckGuid)[0]) && |
270 | 0 | (((INT32 *)Guid)[1] == ((INT32 *)CheckGuid)[1]) && |
271 | 0 | (((INT32 *)Guid)[2] == ((INT32 *)CheckGuid)[2]) && |
272 | 0 | (((INT32 *)Guid)[3] == ((INT32 *)CheckGuid)[3])) { |
273 | 0 | if (Instance == 0) { |
274 | |
|
275 | 0 | if (PpiDescriptor != NULL) { |
276 | 0 | *PpiDescriptor = TempPtr; |
277 | 0 | } |
278 | |
|
279 | 0 | if (Ppi != NULL) { |
280 | 0 | *Ppi = TempPtr->Ppi; |
281 | 0 | } |
282 | | |
283 | |
|
284 | 0 | return EFI_SUCCESS; |
285 | 0 | } |
286 | 0 | Instance--; |
287 | 0 | } |
288 | 0 | } |
289 | | |
290 | 0 | return EFI_NOT_FOUND; |
291 | 0 | } |
292 | | |
293 | | /** |
294 | | |
295 | | This function installs a notification service to be called back when a given |
296 | | interface is installed or reinstalled. The purpose of the service is to publish |
297 | | an interface that other parties can use to call additional PPIs that may materialize later. |
298 | | |
299 | | @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. |
300 | | @param NotifyList Pointer to list of Descriptors to notify upon. |
301 | | @param Single TRUE if only single entry in the NotifyList. |
302 | | FALSE if the NotifyList is ended with an entry which has the |
303 | | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST flag set in its Flags field. |
304 | | |
305 | | @retval EFI_SUCCESS if successful |
306 | | @retval EFI_OUT_OF_RESOURCES if no space in the database |
307 | | @retval EFI_INVALID_PARAMETER if not a good descriptor |
308 | | |
309 | | **/ |
310 | | EFI_STATUS |
311 | | InternalPeiNotifyPpi ( |
312 | | IN CONST EFI_PEI_SERVICES **PeiServices, |
313 | | IN CONST EFI_PEI_NOTIFY_DESCRIPTOR *NotifyList, |
314 | | IN BOOLEAN Single |
315 | | ) |
316 | 0 | { |
317 | 0 | PEI_CORE_INSTANCE *PrivateData; |
318 | 0 | PEI_CALLBACK_NOTIFY_LIST *CallbackNotifyListPointer; |
319 | 0 | UINTN CallbackNotifyIndex; |
320 | 0 | UINTN LastCallbackNotifyCount; |
321 | 0 | PEI_DISPATCH_NOTIFY_LIST *DispatchNotifyListPointer; |
322 | 0 | UINTN DispatchNotifyIndex; |
323 | 0 | UINTN LastDispatchNotifyCount; |
324 | 0 | VOID *TempPtr; |
325 | |
|
326 | 0 | if (NotifyList == NULL) { |
327 | 0 | return EFI_INVALID_PARAMETER; |
328 | 0 | } |
329 | | |
330 | 0 | PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); |
331 | |
|
332 | 0 | CallbackNotifyListPointer = &PrivateData->PpiData.CallbackNotifyList; |
333 | 0 | CallbackNotifyIndex = CallbackNotifyListPointer->CurrentCount; |
334 | 0 | LastCallbackNotifyCount = CallbackNotifyIndex; |
335 | |
|
336 | 0 | DispatchNotifyListPointer = &PrivateData->PpiData.DispatchNotifyList; |
337 | 0 | DispatchNotifyIndex = DispatchNotifyListPointer->CurrentCount; |
338 | 0 | LastDispatchNotifyCount = DispatchNotifyIndex; |
339 | | |
340 | | // |
341 | | // This is loop installs all Notify descriptors in the NotifyList. It is |
342 | | // terminated by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last |
343 | | // EFI_PEI_NOTIFY_DESCRIPTOR in the list. |
344 | | // |
345 | |
|
346 | 0 | for (;;) { |
347 | | // |
348 | | // If some of the PPI data is invalid restore original Notify PPI database value |
349 | | // |
350 | 0 | if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_TYPES) == 0) { |
351 | 0 | CallbackNotifyListPointer->CurrentCount = LastCallbackNotifyCount; |
352 | 0 | DispatchNotifyListPointer->CurrentCount = LastDispatchNotifyCount; |
353 | 0 | DEBUG((DEBUG_ERROR, "ERROR -> NotifyPpi: %g %p\n", NotifyList->Guid, NotifyList->Notify)); |
354 | 0 | return EFI_INVALID_PARAMETER; |
355 | 0 | } |
356 | | |
357 | 0 | if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK) != 0) { |
358 | 0 | if (CallbackNotifyIndex >= CallbackNotifyListPointer->MaxCount) { |
359 | | // |
360 | | // Run out of room, grow the buffer. |
361 | | // |
362 | 0 | TempPtr = AllocateZeroPool ( |
363 | 0 | sizeof (PEI_PPI_LIST_POINTERS) * (CallbackNotifyListPointer->MaxCount + CALLBACK_NOTIFY_GROWTH_STEP) |
364 | 0 | ); |
365 | 0 | ASSERT (TempPtr != NULL); |
366 | 0 | CopyMem ( |
367 | 0 | TempPtr, |
368 | 0 | CallbackNotifyListPointer->NotifyPtrs, |
369 | 0 | sizeof (PEI_PPI_LIST_POINTERS) * CallbackNotifyListPointer->MaxCount |
370 | 0 | ); |
371 | 0 | CallbackNotifyListPointer->NotifyPtrs = TempPtr; |
372 | 0 | CallbackNotifyListPointer->MaxCount = CallbackNotifyListPointer->MaxCount + CALLBACK_NOTIFY_GROWTH_STEP; |
373 | 0 | } |
374 | 0 | CallbackNotifyListPointer->NotifyPtrs[CallbackNotifyIndex].Notify = (EFI_PEI_NOTIFY_DESCRIPTOR *) NotifyList; |
375 | 0 | CallbackNotifyIndex++; |
376 | 0 | CallbackNotifyListPointer->CurrentCount++; |
377 | 0 | } else { |
378 | 0 | if (DispatchNotifyIndex >= DispatchNotifyListPointer->MaxCount) { |
379 | | // |
380 | | // Run out of room, grow the buffer. |
381 | | // |
382 | 0 | TempPtr = AllocateZeroPool ( |
383 | 0 | sizeof (PEI_PPI_LIST_POINTERS) * (DispatchNotifyListPointer->MaxCount + DISPATCH_NOTIFY_GROWTH_STEP) |
384 | 0 | ); |
385 | 0 | ASSERT (TempPtr != NULL); |
386 | 0 | CopyMem ( |
387 | 0 | TempPtr, |
388 | 0 | DispatchNotifyListPointer->NotifyPtrs, |
389 | 0 | sizeof (PEI_PPI_LIST_POINTERS) * DispatchNotifyListPointer->MaxCount |
390 | 0 | ); |
391 | 0 | DispatchNotifyListPointer->NotifyPtrs = TempPtr; |
392 | 0 | DispatchNotifyListPointer->MaxCount = DispatchNotifyListPointer->MaxCount + DISPATCH_NOTIFY_GROWTH_STEP; |
393 | 0 | } |
394 | 0 | DispatchNotifyListPointer->NotifyPtrs[DispatchNotifyIndex].Notify = (EFI_PEI_NOTIFY_DESCRIPTOR *) NotifyList; |
395 | 0 | DispatchNotifyIndex++; |
396 | 0 | DispatchNotifyListPointer->CurrentCount++; |
397 | 0 | } |
398 | |
|
399 | 0 | DEBUG((EFI_D_INFO, "Register PPI Notify: %g\n", NotifyList->Guid)); |
400 | |
|
401 | 0 | if (Single) { |
402 | | // |
403 | | // Only single entry in the NotifyList. |
404 | | // |
405 | 0 | break; |
406 | 0 | } else if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) == |
407 | 0 | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) { |
408 | | // |
409 | | // Continue until the end of the Notify List. |
410 | | // |
411 | 0 | break; |
412 | 0 | } |
413 | | // |
414 | | // Go to the next descriptor. |
415 | | // |
416 | 0 | NotifyList++; |
417 | 0 | } |
418 | | |
419 | | // |
420 | | // Process any callback level notifies for all previously installed PPIs. |
421 | | // |
422 | 0 | ProcessNotify ( |
423 | 0 | PrivateData, |
424 | 0 | EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK, |
425 | 0 | 0, |
426 | 0 | PrivateData->PpiData.PpiList.CurrentCount, |
427 | 0 | LastCallbackNotifyCount, |
428 | 0 | CallbackNotifyListPointer->CurrentCount |
429 | 0 | ); |
430 | |
|
431 | 0 | return EFI_SUCCESS; |
432 | 0 | } |
433 | | |
434 | | /** |
435 | | |
436 | | This function installs a notification service to be called back when a given |
437 | | interface is installed or reinstalled. The purpose of the service is to publish |
438 | | an interface that other parties can use to call additional PPIs that may materialize later. |
439 | | |
440 | | @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. |
441 | | @param NotifyList Pointer to list of Descriptors to notify upon. |
442 | | |
443 | | @retval EFI_SUCCESS if successful |
444 | | @retval EFI_OUT_OF_RESOURCES if no space in the database |
445 | | @retval EFI_INVALID_PARAMETER if not a good descriptor |
446 | | |
447 | | **/ |
448 | | EFI_STATUS |
449 | | EFIAPI |
450 | | PeiNotifyPpi ( |
451 | | IN CONST EFI_PEI_SERVICES **PeiServices, |
452 | | IN CONST EFI_PEI_NOTIFY_DESCRIPTOR *NotifyList |
453 | | ) |
454 | 0 | { |
455 | 0 | return InternalPeiNotifyPpi (PeiServices, NotifyList, FALSE); |
456 | 0 | } |
457 | | |
458 | | /** |
459 | | |
460 | | Process the Notify List at dispatch level. |
461 | | |
462 | | @param PrivateData PeiCore's private data structure. |
463 | | |
464 | | **/ |
465 | | VOID |
466 | | ProcessDispatchNotifyList ( |
467 | | IN PEI_CORE_INSTANCE *PrivateData |
468 | | ) |
469 | 0 | { |
470 | 0 | UINTN TempValue; |
471 | |
|
472 | 0 | while (TRUE) { |
473 | | // |
474 | | // Check if the PEIM that was just dispatched resulted in any |
475 | | // Notifies getting installed. If so, go process any dispatch |
476 | | // level Notifies that match the previouly installed PPIs. |
477 | | // Use "while" instead of "if" since ProcessNotify can modify |
478 | | // DispatchNotifyList.CurrentCount (with NotifyPpi) so we have |
479 | | // to iterate until the same. |
480 | | // |
481 | 0 | while (PrivateData->PpiData.DispatchNotifyList.LastDispatchedCount != PrivateData->PpiData.DispatchNotifyList.CurrentCount) { |
482 | 0 | TempValue = PrivateData->PpiData.DispatchNotifyList.CurrentCount; |
483 | 0 | ProcessNotify ( |
484 | 0 | PrivateData, |
485 | 0 | EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH, |
486 | 0 | 0, |
487 | 0 | PrivateData->PpiData.PpiList.LastDispatchedCount, |
488 | 0 | PrivateData->PpiData.DispatchNotifyList.LastDispatchedCount, |
489 | 0 | PrivateData->PpiData.DispatchNotifyList.CurrentCount |
490 | 0 | ); |
491 | 0 | PrivateData->PpiData.DispatchNotifyList.LastDispatchedCount = TempValue; |
492 | 0 | } |
493 | | |
494 | | // |
495 | | // Check if the PEIM that was just dispatched resulted in any |
496 | | // PPIs getting installed. If so, go process any dispatch |
497 | | // level Notifies that match the installed PPIs. |
498 | | // Use "while" instead of "if" since ProcessNotify can modify |
499 | | // PpiList.CurrentCount (with InstallPpi) so we have to iterate |
500 | | // until the same. |
501 | | // |
502 | 0 | while (PrivateData->PpiData.PpiList.LastDispatchedCount != PrivateData->PpiData.PpiList.CurrentCount) { |
503 | 0 | TempValue = PrivateData->PpiData.PpiList.CurrentCount; |
504 | 0 | ProcessNotify ( |
505 | 0 | PrivateData, |
506 | 0 | EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH, |
507 | 0 | PrivateData->PpiData.PpiList.LastDispatchedCount, |
508 | 0 | PrivateData->PpiData.PpiList.CurrentCount, |
509 | 0 | 0, |
510 | 0 | PrivateData->PpiData.DispatchNotifyList.LastDispatchedCount |
511 | 0 | ); |
512 | 0 | PrivateData->PpiData.PpiList.LastDispatchedCount = TempValue; |
513 | 0 | } |
514 | |
|
515 | 0 | if (PrivateData->PpiData.DispatchNotifyList.LastDispatchedCount == PrivateData->PpiData.DispatchNotifyList.CurrentCount) { |
516 | 0 | break; |
517 | 0 | } |
518 | 0 | } |
519 | 0 | return; |
520 | 0 | } |
521 | | |
522 | | /** |
523 | | |
524 | | Process notifications. |
525 | | |
526 | | @param PrivateData PeiCore's private data structure |
527 | | @param NotifyType Type of notify to fire. |
528 | | @param InstallStartIndex Install Beginning index. |
529 | | @param InstallStopIndex Install Ending index. |
530 | | @param NotifyStartIndex Notify Beginning index. |
531 | | @param NotifyStopIndex Notify Ending index. |
532 | | |
533 | | **/ |
534 | | VOID |
535 | | ProcessNotify ( |
536 | | IN PEI_CORE_INSTANCE *PrivateData, |
537 | | IN UINTN NotifyType, |
538 | | IN INTN InstallStartIndex, |
539 | | IN INTN InstallStopIndex, |
540 | | IN INTN NotifyStartIndex, |
541 | | IN INTN NotifyStopIndex |
542 | | ) |
543 | 0 | { |
544 | 0 | INTN Index1; |
545 | 0 | INTN Index2; |
546 | 0 | EFI_GUID *SearchGuid; |
547 | 0 | EFI_GUID *CheckGuid; |
548 | 0 | EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor; |
549 | |
|
550 | 0 | for (Index1 = NotifyStartIndex; Index1 < NotifyStopIndex; Index1++) { |
551 | 0 | if (NotifyType == EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK) { |
552 | 0 | NotifyDescriptor = PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index1].Notify; |
553 | 0 | } else { |
554 | 0 | NotifyDescriptor = PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index1].Notify; |
555 | 0 | } |
556 | |
|
557 | 0 | CheckGuid = NotifyDescriptor->Guid; |
558 | |
|
559 | 0 | for (Index2 = InstallStartIndex; Index2 < InstallStopIndex; Index2++) { |
560 | 0 | SearchGuid = PrivateData->PpiData.PpiList.PpiPtrs[Index2].Ppi->Guid; |
561 | | // |
562 | | // Don't use CompareGuid function here for performance reasons. |
563 | | // Instead we compare the GUID as INT32 at a time and branch |
564 | | // on the first failed comparison. |
565 | | // |
566 | 0 | if ((((INT32 *)SearchGuid)[0] == ((INT32 *)CheckGuid)[0]) && |
567 | 0 | (((INT32 *)SearchGuid)[1] == ((INT32 *)CheckGuid)[1]) && |
568 | 0 | (((INT32 *)SearchGuid)[2] == ((INT32 *)CheckGuid)[2]) && |
569 | 0 | (((INT32 *)SearchGuid)[3] == ((INT32 *)CheckGuid)[3])) { |
570 | 0 | DEBUG ((EFI_D_INFO, "Notify: PPI Guid: %g, Peim notify entry point: %p\n", |
571 | 0 | SearchGuid, |
572 | 0 | NotifyDescriptor->Notify |
573 | 0 | )); |
574 | 0 | NotifyDescriptor->Notify ( |
575 | 0 | (EFI_PEI_SERVICES **) GetPeiServicesTablePointer (), |
576 | 0 | NotifyDescriptor, |
577 | 0 | (PrivateData->PpiData.PpiList.PpiPtrs[Index2].Ppi)->Ppi |
578 | 0 | ); |
579 | 0 | } |
580 | 0 | } |
581 | 0 | } |
582 | 0 | } |
583 | | |