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