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