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