]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/Pei/Ppi/Ppi.c
Fix function comment to follows doxygen format.
[mirror_edk2.git] / MdeModulePkg / Core / Pei / Ppi / Ppi.c
1 /** @file
2 EFI PEI Core PPI services
3
4 Copyright (c) 2006, Intel Corporation
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include <PeiMain.h>
16
17 /**
18
19 Initialize PPI services.
20
21
22 @param PrivateData Pointer to the PEI Core data.
23 @param OldCoreData Pointer to old PEI Core data.
24 NULL if being run in non-permament memory mode.
25
26 **/
27 VOID
28 InitializePpiServices (
29 IN PEI_CORE_INSTANCE *PrivateData,
30 IN PEI_CORE_INSTANCE *OldCoreData
31 )
32 {
33 if (OldCoreData == NULL) {
34 PrivateData->PpiData.NotifyListEnd = FixedPcdGet32 (PcdPeiCoreMaxPpiSupported)-1;
35 PrivateData->PpiData.DispatchListEnd = FixedPcdGet32 (PcdPeiCoreMaxPpiSupported)-1;
36 PrivateData->PpiData.LastDispatchedNotify = FixedPcdGet32 (PcdPeiCoreMaxPpiSupported)-1;
37 }
38 }
39
40 /**
41
42 Migrate the Hob list from the CAR stack to PEI installed memory.
43
44 @param PeiServices The PEI core services table.
45 @param OldCheckingBottom The old checking bottom.
46 @param OldCheckingTop The old checking top.
47 @param NewHandOffHob The new handoff HOB list.
48
49 **/
50 VOID
51 ConvertPpiPointers (
52 IN CONST EFI_PEI_SERVICES **PeiServices,
53 IN UINTN OldCheckingBottom,
54 IN UINTN OldCheckingTop,
55 IN EFI_HOB_HANDOFF_INFO_TABLE *NewHandOffHob
56 )
57 {
58 PEI_CORE_INSTANCE *PrivateData;
59 UINT8 Index;
60 PEI_PPI_LIST_POINTERS *PpiPointer;
61 UINTN Fixup;
62
63 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);
64
65 Fixup = (UINTN)NewHandOffHob - OldCheckingBottom;
66
67 for (Index = 0; Index < FixedPcdGet32 (PcdPeiCoreMaxPpiSupported); Index++) {
68 if (Index < PrivateData->PpiData.PpiListEnd ||
69 Index > PrivateData->PpiData.NotifyListEnd) {
70 PpiPointer = &PrivateData->PpiData.PpiListPtrs[Index];
71
72 if (((UINTN)PpiPointer->Raw < OldCheckingTop) &&
73 ((UINTN)PpiPointer->Raw >= OldCheckingBottom)) {
74 //
75 // Convert the pointer to the PEIM descriptor from the old HOB heap
76 // to the relocated HOB heap.
77 //
78 PpiPointer->Raw = (VOID *) ((UINTN)PpiPointer->Raw + Fixup);
79
80 //
81 // Only when the PEIM descriptor is in the old HOB should it be necessary
82 // to try to convert the pointers in the PEIM descriptor
83 //
84
85 if (((UINTN)PpiPointer->Ppi->Guid < OldCheckingTop) &&
86 ((UINTN)PpiPointer->Ppi->Guid >= OldCheckingBottom)) {
87 //
88 // Convert the pointer to the GUID in the PPI or NOTIFY descriptor
89 // from the old HOB heap to the relocated HOB heap.
90 //
91 PpiPointer->Ppi->Guid = (VOID *) ((UINTN)PpiPointer->Ppi->Guid + Fixup);
92 }
93
94 //
95 // Assume that no code is located in the temporary memory, so the pointer to
96 // the notification function in the NOTIFY descriptor needs not be converted.
97 //
98 if (Index < PrivateData->PpiData.PpiListEnd &&
99 (UINTN)PpiPointer->Ppi->Ppi < OldCheckingTop &&
100 (UINTN)PpiPointer->Ppi->Ppi >= OldCheckingBottom) {
101 //
102 // Convert the pointer to the PPI interface structure in the PPI descriptor
103 // from the old HOB heap to the relocated HOB heap.
104 //
105 PpiPointer->Ppi->Ppi = (VOID *) ((UINTN)PpiPointer->Ppi->Ppi+ Fixup);
106 }
107 }
108 }
109 }
110 }
111
112 /**
113
114 Install PPI services.
115
116 @param PeiServices - Pointer to the PEI Service Table
117 @param PpiList - Pointer to a list of PEI PPI Descriptors.
118
119 @retval EFI_SUCCESS - if all PPIs in PpiList are successfully installed.
120 @retval EFI_INVALID_PARAMETER - if PpiList is NULL pointer
121 @retval EFI_INVALID_PARAMETER - if any PPI in PpiList is not valid
122 @retval EFI_OUT_OF_RESOURCES - if there is no more memory resource to install PPI
123
124 **/
125 EFI_STATUS
126 EFIAPI
127 PeiInstallPpi (
128 IN CONST EFI_PEI_SERVICES **PeiServices,
129 IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList
130 )
131 {
132 PEI_CORE_INSTANCE *PrivateData;
133 INTN Index;
134 INTN LastCallbackInstall;
135
136
137 if (PpiList == NULL) {
138 return EFI_INVALID_PARAMETER;
139 }
140
141 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);
142
143 Index = PrivateData->PpiData.PpiListEnd;
144 LastCallbackInstall = Index;
145
146 //
147 // This is loop installs all PPI descriptors in the PpiList. It is terminated
148 // by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last
149 // EFI_PEI_PPI_DESCRIPTOR in the list.
150 //
151
152 for (;;) {
153 //
154 // Since PpiData is used for NotifyList and InstallList, max resource
155 // is reached if the Install reaches the NotifyList
156 //
157 if (Index == PrivateData->PpiData.NotifyListEnd + 1) {
158 return EFI_OUT_OF_RESOURCES;
159 }
160 //
161 // Check if it is a valid PPI.
162 // If not, rollback list to exclude all in this list.
163 // Try to indicate which item failed.
164 //
165 if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_PPI) == 0) {
166 PrivateData->PpiData.PpiListEnd = LastCallbackInstall;
167 DEBUG((EFI_D_ERROR, "ERROR -> InstallPpi: %g %x\n", PpiList->Guid, PpiList->Ppi));
168 return EFI_INVALID_PARAMETER;
169 }
170
171 DEBUG((EFI_D_INFO, "Install PPI: %g\n", PpiList->Guid));
172 PrivateData->PpiData.PpiListPtrs[Index].Ppi = (EFI_PEI_PPI_DESCRIPTOR*) PpiList;
173 PrivateData->PpiData.PpiListEnd++;
174
175 //
176 // Continue until the end of the PPI List.
177 //
178 if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) ==
179 EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) {
180 break;
181 }
182 PpiList++;
183 Index++;
184 }
185
186 //
187 // Dispatch any callback level notifies for newly installed PPIs.
188 //
189 DispatchNotify (
190 PrivateData,
191 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,
192 LastCallbackInstall,
193 PrivateData->PpiData.PpiListEnd,
194 PrivateData->PpiData.DispatchListEnd,
195 PrivateData->PpiData.NotifyListEnd
196 );
197
198
199 return EFI_SUCCESS;
200 }
201
202 /**
203
204 Re-Install PPI services.
205
206 @param PeiServices - Pointer to the PEI Service Table
207 @param OldPpi - Pointer to the old PEI PPI Descriptors.
208 @param NewPpi - Pointer to the new PEI PPI Descriptors.
209
210 @retval EFI_SUCCESS - if the operation was successful
211 @retval EFI_INVALID_PARAMETER - if OldPpi or NewPpi is NULL
212 @retval EFI_INVALID_PARAMETER - if NewPpi is not valid
213 @retval EFI_NOT_FOUND - if the PPI was not in the database
214
215 **/
216 EFI_STATUS
217 EFIAPI
218 PeiReInstallPpi (
219 IN CONST EFI_PEI_SERVICES **PeiServices,
220 IN CONST EFI_PEI_PPI_DESCRIPTOR *OldPpi,
221 IN CONST EFI_PEI_PPI_DESCRIPTOR *NewPpi
222 )
223 {
224 PEI_CORE_INSTANCE *PrivateData;
225 INTN Index;
226
227
228 if ((OldPpi == NULL) || (NewPpi == NULL)) {
229 return EFI_INVALID_PARAMETER;
230 }
231
232 if ((NewPpi->Flags & EFI_PEI_PPI_DESCRIPTOR_PPI) == 0) {
233 return EFI_INVALID_PARAMETER;
234 }
235
236 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);
237
238 //
239 // Find the old PPI instance in the database. If we can not find it,
240 // return the EFI_NOT_FOUND error.
241 //
242 for (Index = 0; Index < PrivateData->PpiData.PpiListEnd; Index++) {
243 if (OldPpi == PrivateData->PpiData.PpiListPtrs[Index].Ppi) {
244 break;
245 }
246 }
247 if (Index == PrivateData->PpiData.PpiListEnd) {
248 return EFI_NOT_FOUND;
249 }
250
251 //
252 // Remove the old PPI from the database, add the new one.
253 //
254 DEBUG((EFI_D_INFO, "Reinstall PPI: %g\n", NewPpi->Guid));
255 PrivateData->PpiData.PpiListPtrs[Index].Ppi = (EFI_PEI_PPI_DESCRIPTOR *) NewPpi;
256
257 //
258 // Dispatch any callback level notifies for the newly installed PPI.
259 //
260 DispatchNotify (
261 PrivateData,
262 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,
263 Index,
264 Index+1,
265 PrivateData->PpiData.DispatchListEnd,
266 PrivateData->PpiData.NotifyListEnd
267 );
268
269
270 return EFI_SUCCESS;
271 }
272
273 /**
274
275 Locate a given named PPI.
276
277
278 @param PeiServices - Pointer to the PEI Service Table
279 @param Guid - Pointer to GUID of the PPI.
280 @param Instance - Instance Number to discover.
281 @param PpiDescriptor - Pointer to reference the found descriptor. If not NULL,
282 returns a pointer to the descriptor (includes flags, etc)
283 @param Ppi - Pointer to reference the found PPI
284
285 @retval EFI_SUCCESS if the PPI is in the database
286 @retval EFI_NOT_FOUND if the PPI is not in the database
287
288 **/
289 EFI_STATUS
290 EFIAPI
291 PeiLocatePpi (
292 IN CONST EFI_PEI_SERVICES **PeiServices,
293 IN CONST EFI_GUID *Guid,
294 IN UINTN Instance,
295 IN OUT EFI_PEI_PPI_DESCRIPTOR **PpiDescriptor,
296 IN OUT VOID **Ppi
297 )
298 {
299 PEI_CORE_INSTANCE *PrivateData;
300 INTN Index;
301 EFI_GUID *CheckGuid;
302 EFI_PEI_PPI_DESCRIPTOR *TempPtr;
303
304
305 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);
306
307 //
308 // Search the data base for the matching instance of the GUIDed PPI.
309 //
310 for (Index = 0; Index < PrivateData->PpiData.PpiListEnd; Index++) {
311 TempPtr = PrivateData->PpiData.PpiListPtrs[Index].Ppi;
312 CheckGuid = TempPtr->Guid;
313
314 //
315 // Don't use CompareGuid function here for performance reasons.
316 // Instead we compare the GUID as INT32 at a time and branch
317 // on the first failed comparison.
318 //
319 if ((((INT32 *)Guid)[0] == ((INT32 *)CheckGuid)[0]) &&
320 (((INT32 *)Guid)[1] == ((INT32 *)CheckGuid)[1]) &&
321 (((INT32 *)Guid)[2] == ((INT32 *)CheckGuid)[2]) &&
322 (((INT32 *)Guid)[3] == ((INT32 *)CheckGuid)[3])) {
323 if (Instance == 0) {
324
325 if (PpiDescriptor != NULL) {
326 *PpiDescriptor = TempPtr;
327 }
328
329 if (Ppi != NULL) {
330 *Ppi = TempPtr->Ppi;
331 }
332
333
334 return EFI_SUCCESS;
335 }
336 Instance--;
337 }
338 }
339
340 return EFI_NOT_FOUND;
341 }
342
343 /**
344
345 Install a notification for a given PPI.
346
347
348 @param PeiServices - Pointer to the PEI Service Table
349 @param NotifyList - Pointer to list of Descriptors to notify upon.
350
351 @retval EFI_SUCCESS if successful
352 @retval EFI_OUT_OF_RESOURCES if no space in the database
353 @retval EFI_INVALID_PARAMETER if not a good decriptor
354
355 **/
356 EFI_STATUS
357 EFIAPI
358 PeiNotifyPpi (
359 IN CONST EFI_PEI_SERVICES **PeiServices,
360 IN CONST EFI_PEI_NOTIFY_DESCRIPTOR *NotifyList
361 )
362 {
363 PEI_CORE_INSTANCE *PrivateData;
364 INTN Index;
365 INTN NotifyIndex;
366 INTN LastCallbackNotify;
367 EFI_PEI_NOTIFY_DESCRIPTOR *NotifyPtr;
368 UINTN NotifyDispatchCount;
369
370
371 NotifyDispatchCount = 0;
372
373 if (NotifyList == NULL) {
374 return EFI_INVALID_PARAMETER;
375 }
376
377 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);
378
379 Index = PrivateData->PpiData.NotifyListEnd;
380 LastCallbackNotify = Index;
381
382 //
383 // This is loop installs all Notify descriptors in the NotifyList. It is
384 // terminated by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last
385 // EFI_PEI_NOTIFY_DESCRIPTOR in the list.
386 //
387
388 for (;;) {
389 //
390 // Since PpiData is used for NotifyList and InstallList, max resource
391 // is reached if the Install reaches the PpiList
392 //
393 if (Index == PrivateData->PpiData.PpiListEnd - 1) {
394 return EFI_OUT_OF_RESOURCES;
395 }
396
397 //
398 // If some of the PPI data is invalid restore original Notify PPI database value
399 //
400 if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_TYPES) == 0) {
401 PrivateData->PpiData.NotifyListEnd = LastCallbackNotify;
402 DEBUG((EFI_D_ERROR, "ERROR -> InstallNotify: %g %x\n", NotifyList->Guid, NotifyList->Notify));
403 return EFI_INVALID_PARAMETER;
404 }
405
406 if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH) != 0) {
407 NotifyDispatchCount ++;
408 }
409
410 PrivateData->PpiData.PpiListPtrs[Index].Notify = (EFI_PEI_NOTIFY_DESCRIPTOR *) NotifyList;
411
412 PrivateData->PpiData.NotifyListEnd--;
413 DEBUG((EFI_D_INFO, "Register PPI Notify: %g\n", NotifyList->Guid));
414 if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) ==
415 EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) {
416 break;
417 }
418 //
419 // Go the next descriptor. Remember the NotifyList moves down.
420 //
421 NotifyList++;
422 Index--;
423 }
424
425 //
426 // If there is Dispatch Notify PPI installed put them on the bottom
427 //
428 if (NotifyDispatchCount > 0) {
429 for (NotifyIndex = LastCallbackNotify; NotifyIndex > PrivateData->PpiData.NotifyListEnd; NotifyIndex--) {
430 if ((PrivateData->PpiData.PpiListPtrs[NotifyIndex].Notify->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH) != 0) {
431 NotifyPtr = PrivateData->PpiData.PpiListPtrs[NotifyIndex].Notify;
432
433 for (Index = NotifyIndex; Index < PrivateData->PpiData.DispatchListEnd; Index++){
434 PrivateData->PpiData.PpiListPtrs[Index].Notify = PrivateData->PpiData.PpiListPtrs[Index + 1].Notify;
435 }
436 PrivateData->PpiData.PpiListPtrs[Index].Notify = NotifyPtr;
437 PrivateData->PpiData.DispatchListEnd--;
438 }
439 }
440
441 LastCallbackNotify -= NotifyDispatchCount;
442 }
443
444 //
445 // Dispatch any callback level notifies for all previously installed PPIs.
446 //
447 DispatchNotify (
448 PrivateData,
449 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,
450 0,
451 PrivateData->PpiData.PpiListEnd,
452 LastCallbackNotify,
453 PrivateData->PpiData.NotifyListEnd
454 );
455
456
457 return EFI_SUCCESS;
458 }
459
460
461 /**
462
463 Process the Notify List at dispatch level.
464
465 @param PrivateData PeiCore's private data structure.
466
467 **/
468 VOID
469 ProcessNotifyList (
470 IN PEI_CORE_INSTANCE *PrivateData
471 )
472 {
473 INTN TempValue;
474
475 while (TRUE) {
476 //
477 // Check if the PEIM that was just dispatched resulted in any
478 // Notifies getting installed. If so, go process any dispatch
479 // level Notifies that match the previouly installed PPIs.
480 // Use "while" instead of "if" since DispatchNotify can modify
481 // DispatchListEnd (with NotifyPpi) so we have to iterate until the same.
482 //
483 while (PrivateData->PpiData.LastDispatchedNotify != PrivateData->PpiData.DispatchListEnd) {
484 TempValue = PrivateData->PpiData.DispatchListEnd;
485 DispatchNotify (
486 PrivateData,
487 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH,
488 0,
489 PrivateData->PpiData.LastDispatchedInstall,
490 PrivateData->PpiData.LastDispatchedNotify,
491 PrivateData->PpiData.DispatchListEnd
492 );
493 PrivateData->PpiData.LastDispatchedNotify = TempValue;
494 }
495
496
497 //
498 // Check if the PEIM that was just dispatched resulted in any
499 // PPIs getting installed. If so, go process any dispatch
500 // level Notifies that match the installed PPIs.
501 // Use "while" instead of "if" since DispatchNotify can modify
502 // PpiListEnd (with InstallPpi) so we have to iterate until the same.
503 //
504 while (PrivateData->PpiData.LastDispatchedInstall != PrivateData->PpiData.PpiListEnd) {
505 TempValue = PrivateData->PpiData.PpiListEnd;
506 DispatchNotify (
507 PrivateData,
508 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH,
509 PrivateData->PpiData.LastDispatchedInstall,
510 PrivateData->PpiData.PpiListEnd,
511 FixedPcdGet32 (PcdPeiCoreMaxPpiSupported)-1,
512 PrivateData->PpiData.DispatchListEnd
513 );
514 PrivateData->PpiData.LastDispatchedInstall = TempValue;
515 }
516
517 if (PrivateData->PpiData.LastDispatchedNotify == PrivateData->PpiData.DispatchListEnd) {
518 break;
519 }
520 }
521 return;
522 }
523
524 /**
525
526 Dispatch notifications.
527
528 @param PrivateData PeiCore's private data structure
529 @param NotifyType Type of notify to fire.
530 @param InstallStartIndex Install Beginning index.
531 @param InstallStopIndex Install Ending index.
532 @param NotifyStartIndex Notify Beginning index.
533 @param NotifyStopIndex Notify Ending index.
534
535 **/
536 VOID
537 DispatchNotify (
538 IN PEI_CORE_INSTANCE *PrivateData,
539 IN UINTN NotifyType,
540 IN INTN InstallStartIndex,
541 IN INTN InstallStopIndex,
542 IN INTN NotifyStartIndex,
543 IN INTN NotifyStopIndex
544 )
545 {
546 INTN Index1;
547 INTN Index2;
548 EFI_GUID *SearchGuid;
549 EFI_GUID *CheckGuid;
550 EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor;
551
552 //
553 // Remember that Installs moves up and Notifies moves down.
554 //
555 for (Index1 = NotifyStartIndex; Index1 > NotifyStopIndex; Index1--) {
556 NotifyDescriptor = PrivateData->PpiData.PpiListPtrs[Index1].Notify;
557
558 CheckGuid = NotifyDescriptor->Guid;
559
560 for (Index2 = InstallStartIndex; Index2 < InstallStopIndex; Index2++) {
561 SearchGuid = PrivateData->PpiData.PpiListPtrs[Index2].Ppi->Guid;
562 //
563 // Don't use CompareGuid function here for performance reasons.
564 // Instead we compare the GUID as INT32 at a time and branch
565 // on the first failed comparison.
566 //
567 if ((((INT32 *)SearchGuid)[0] == ((INT32 *)CheckGuid)[0]) &&
568 (((INT32 *)SearchGuid)[1] == ((INT32 *)CheckGuid)[1]) &&
569 (((INT32 *)SearchGuid)[2] == ((INT32 *)CheckGuid)[2]) &&
570 (((INT32 *)SearchGuid)[3] == ((INT32 *)CheckGuid)[3])) {
571 DEBUG ((EFI_D_INFO, "Notify: PPI Guid: %g, Peim notify entry point: %x\n",
572 SearchGuid,
573 NotifyDescriptor->Notify
574 ));
575 NotifyDescriptor->Notify (
576 GetPeiServicesTablePointer (),
577 NotifyDescriptor,
578 (PrivateData->PpiData.PpiListPtrs[Index2].Ppi)->Ppi
579 );
580 }
581 }
582 }
583
584 return;
585 }
586