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