]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/PCD/Dxe/Pcd.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / MdeModulePkg / Universal / PCD / Dxe / Pcd.c
1 /** @file
2 PCD DXE driver manage all PCD entry initialized in PEI phase and DXE phase, and
3 produce the implementation of native PCD protocol and EFI_PCD_PROTOCOL defined in
4 PI 1.4a Vol3.
5
6 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
7 SPDX-License-Identifier: BSD-2-Clause-Patent
8
9 **/
10
11 #include "Service.h"
12
13 ///
14 /// PCD database lock.
15 ///
16 EFI_LOCK mPcdDatabaseLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY);
17
18 ///
19 /// PCD_PROTOCOL the EDKII native implementation which support dynamic
20 /// type and dynamicEx type PCDs.
21 ///
22 PCD_PROTOCOL mPcdInstance = {
23 DxePcdSetSku,
24
25 DxePcdGet8,
26 DxePcdGet16,
27 DxePcdGet32,
28 DxePcdGet64,
29 DxePcdGetPtr,
30 DxePcdGetBool,
31 DxePcdGetSize,
32
33 DxePcdGet8Ex,
34 DxePcdGet16Ex,
35 DxePcdGet32Ex,
36 DxePcdGet64Ex,
37 DxePcdGetPtrEx,
38 DxePcdGetBoolEx,
39 DxePcdGetSizeEx,
40
41 DxePcdSet8,
42 DxePcdSet16,
43 DxePcdSet32,
44 DxePcdSet64,
45 DxePcdSetPtr,
46 DxePcdSetBool,
47
48 DxePcdSet8Ex,
49 DxePcdSet16Ex,
50 DxePcdSet32Ex,
51 DxePcdSet64Ex,
52 DxePcdSetPtrEx,
53 DxePcdSetBoolEx,
54
55 DxeRegisterCallBackOnSet,
56 DxeUnRegisterCallBackOnSet,
57 DxePcdGetNextToken,
58 DxePcdGetNextTokenSpace
59 };
60
61 ///
62 /// EFI_PCD_PROTOCOL is defined in PI 1.2 Vol 3 which only support dynamicEx type
63 /// PCD.
64 ///
65 EFI_PCD_PROTOCOL mEfiPcdInstance = {
66 DxePcdSetSku,
67 DxePcdGet8Ex,
68 DxePcdGet16Ex,
69 DxePcdGet32Ex,
70 DxePcdGet64Ex,
71 DxePcdGetPtrEx,
72 DxePcdGetBoolEx,
73 DxePcdGetSizeEx,
74 DxePcdSet8Ex,
75 DxePcdSet16Ex,
76 DxePcdSet32Ex,
77 DxePcdSet64Ex,
78 DxePcdSetPtrEx,
79 DxePcdSetBoolEx,
80 (EFI_PCD_PROTOCOL_CALLBACK_ON_SET)DxeRegisterCallBackOnSet,
81 (EFI_PCD_PROTOCOL_CANCEL_CALLBACK)DxeUnRegisterCallBackOnSet,
82 DxePcdGetNextToken,
83 DxePcdGetNextTokenSpace
84 };
85
86 ///
87 /// Instance of GET_PCD_INFO_PROTOCOL protocol is EDKII native implementation.
88 /// This protocol instance support dynamic and dynamicEx type PCDs.
89 ///
90 GET_PCD_INFO_PROTOCOL mGetPcdInfoInstance = {
91 DxeGetPcdInfoGetInfo,
92 DxeGetPcdInfoGetInfoEx,
93 DxeGetPcdInfoGetSku
94 };
95
96 ///
97 /// Instance of EFI_GET_PCD_INFO_PROTOCOL which is defined in PI 1.2.1 Vol 3.
98 /// This PPI instance only support dyanmicEx type PCD.
99 ///
100 EFI_GET_PCD_INFO_PROTOCOL mEfiGetPcdInfoInstance = {
101 DxeGetPcdInfoGetInfoEx,
102 DxeGetPcdInfoGetSku
103 };
104
105 EFI_HANDLE mPcdHandle = NULL;
106 UINTN mVpdBaseAddress = 0;
107
108 /**
109 Main entry for PCD DXE driver.
110
111 This routine initialize the PCD database and install PCD_PROTOCOL.
112
113 @param ImageHandle Image handle for PCD DXE driver.
114 @param SystemTable Pointer to SystemTable.
115
116 @return Status of gBS->InstallProtocolInterface()
117
118 **/
119 EFI_STATUS
120 EFIAPI
121 PcdDxeInit (
122 IN EFI_HANDLE ImageHandle,
123 IN EFI_SYSTEM_TABLE *SystemTable
124 )
125 {
126 EFI_STATUS Status;
127 VOID *Registration;
128
129 //
130 // Make sure the Pcd Protocol is not already installed in the system
131 //
132
133 ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gPcdProtocolGuid);
134
135 BuildPcdDxeDataBase ();
136
137 //
138 // Install PCD_PROTOCOL to handle dynamic type PCD
139 // Install EFI_PCD_PROTOCOL to handle dynamicEx type PCD
140 //
141 Status = gBS->InstallMultipleProtocolInterfaces (
142 &mPcdHandle,
143 &gPcdProtocolGuid,
144 &mPcdInstance,
145 &gEfiPcdProtocolGuid,
146 &mEfiPcdInstance,
147 NULL
148 );
149 ASSERT_EFI_ERROR (Status);
150
151 //
152 // Install GET_PCD_INFO_PROTOCOL to handle dynamic type PCD
153 // Install EFI_GET_PCD_INFO_PROTOCOL to handle dynamicEx type PCD
154 //
155 Status = gBS->InstallMultipleProtocolInterfaces (
156 &mPcdHandle,
157 &gGetPcdInfoProtocolGuid,
158 &mGetPcdInfoInstance,
159 &gEfiGetPcdInfoProtocolGuid,
160 &mEfiGetPcdInfoInstance,
161 NULL
162 );
163 ASSERT_EFI_ERROR (Status);
164
165 //
166 // Register callback function upon VariableLockProtocol
167 // to lock the variables referenced by DynamicHii PCDs with RO property set in *.dsc.
168 //
169 EfiCreateProtocolNotifyEvent (
170 &gEdkiiVariableLockProtocolGuid,
171 TPL_CALLBACK,
172 VariableLockCallBack,
173 NULL,
174 &Registration
175 );
176
177 //
178 // Cache VpdBaseAddress in entry point for the following usage.
179 //
180
181 //
182 // PcdVpdBaseAddress64 is DynamicEx PCD only. So, DxePcdGet64Ex() is used to get its value.
183 //
184 mVpdBaseAddress = (UINTN)DxePcdGet64Ex (&gEfiMdeModulePkgTokenSpaceGuid, PcdToken (PcdVpdBaseAddress64));
185 if (mVpdBaseAddress == 0) {
186 //
187 // PcdVpdBaseAddress64 is not set, get value from PcdVpdBaseAddress.
188 //
189 mVpdBaseAddress = (UINTN)PcdGet32 (PcdVpdBaseAddress);
190 }
191
192 return Status;
193 }
194
195 /**
196 Retrieve additional information associated with a PCD token in the default token space.
197
198 This includes information such as the type of value the TokenNumber is associated with as well as possible
199 human readable name that is associated with the token.
200
201 @param[in] TokenNumber The PCD token number.
202 @param[out] PcdInfo The returned information associated with the requested TokenNumber.
203 The caller is responsible for freeing the buffer that is allocated by callee for PcdInfo->PcdName.
204
205 @retval EFI_SUCCESS The PCD information was returned successfully.
206 @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
207 **/
208 EFI_STATUS
209 EFIAPI
210 DxeGetPcdInfoGetInfo (
211 IN UINTN TokenNumber,
212 OUT EFI_PCD_INFO *PcdInfo
213 )
214 {
215 return DxeGetPcdInfo (NULL, TokenNumber, PcdInfo);
216 }
217
218 /**
219 Retrieve additional information associated with a PCD token.
220
221 This includes information such as the type of value the TokenNumber is associated with as well as possible
222 human readable name that is associated with the token.
223
224 @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
225 @param[in] TokenNumber The PCD token number.
226 @param[out] PcdInfo The returned information associated with the requested TokenNumber.
227 The caller is responsible for freeing the buffer that is allocated by callee for PcdInfo->PcdName.
228
229 @retval EFI_SUCCESS The PCD information was returned successfully.
230 @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
231 **/
232 EFI_STATUS
233 EFIAPI
234 DxeGetPcdInfoGetInfoEx (
235 IN CONST EFI_GUID *Guid,
236 IN UINTN TokenNumber,
237 OUT EFI_PCD_INFO *PcdInfo
238 )
239 {
240 return DxeGetPcdInfo (Guid, TokenNumber, PcdInfo);
241 }
242
243 /**
244 Retrieve the currently set SKU Id.
245
246 @return The currently set SKU Id. If the platform has not set at a SKU Id, then the
247 default SKU Id value of 0 is returned. If the platform has set a SKU Id, then the currently set SKU
248 Id is returned.
249 **/
250 UINTN
251 EFIAPI
252 DxeGetPcdInfoGetSku (
253 VOID
254 )
255 {
256 return (UINTN)mPcdDatabase.DxeDb->SystemSkuId;
257 }
258
259 /**
260 Sets the SKU value for subsequent calls to set or get PCD token values.
261
262 SetSku() sets the SKU Id to be used for subsequent calls to set or get PCD values.
263 SetSku() is normally called only once by the system.
264
265 For each item (token), the database can hold a single value that applies to all SKUs,
266 or multiple values, where each value is associated with a specific SKU Id. Items with multiple,
267 SKU-specific values are called SKU enabled.
268
269 The SKU Id of zero is reserved as a default.
270 For tokens that are not SKU enabled, the system ignores any set SKU Id and works with the
271 single value for that token. For SKU-enabled tokens, the system will use the SKU Id set by the
272 last call to SetSku(). If no SKU Id is set or the currently set SKU Id isn't valid for the specified token,
273 the system uses the default SKU Id. If the system attempts to use the default SKU Id and no value has been
274 set for that Id, the results are unpredictable.
275
276 @param[in] SkuId The SKU value that will be used when the PCD service will retrieve and
277 set values associated with a PCD token.
278
279 **/
280 VOID
281 EFIAPI
282 DxePcdSetSku (
283 IN UINTN SkuId
284 )
285 {
286 SKU_ID *SkuIdTable;
287 UINTN Index;
288 EFI_STATUS Status;
289
290 DEBUG ((DEBUG_INFO, "PcdDxe - SkuId 0x%lx is to be set.\n", (SKU_ID)SkuId));
291
292 if (SkuId == mPcdDatabase.DxeDb->SystemSkuId) {
293 //
294 // The input SKU Id is equal to current SKU Id, return directly.
295 //
296 DEBUG ((DEBUG_INFO, "PcdDxe - SkuId is same to current system Sku.\n"));
297 return;
298 }
299
300 if (mPcdDatabase.DxeDb->SystemSkuId != (SKU_ID)0) {
301 DEBUG ((DEBUG_ERROR, "PcdDxe - The SKU Id could be changed only once."));
302 DEBUG ((
303 DEBUG_ERROR,
304 "PcdDxe - The SKU Id was set to 0x%lx already, it could not be set to 0x%lx any more.",
305 mPcdDatabase.DxeDb->SystemSkuId,
306 (SKU_ID)SkuId
307 ));
308 ASSERT (FALSE);
309 return;
310 }
311
312 SkuIdTable = (SKU_ID *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->SkuIdTableOffset);
313 for (Index = 0; Index < SkuIdTable[0]; Index++) {
314 if (SkuId == SkuIdTable[Index + 1]) {
315 DEBUG ((DEBUG_INFO, "PcdDxe - SkuId is found in SkuId table.\n"));
316 Status = UpdatePcdDatabase (SkuId, TRUE);
317 if (!EFI_ERROR (Status)) {
318 mPcdDatabase.DxeDb->SystemSkuId = (SKU_ID)SkuId;
319 DEBUG ((DEBUG_INFO, "PcdDxe - Set current SKU Id to 0x%lx.\n", (SKU_ID)SkuId));
320 return;
321 }
322 }
323 }
324
325 //
326 // Invalid input SkuId, the default SKU Id will be still used for the system.
327 //
328 DEBUG ((DEBUG_ERROR, "PcdDxe - Invalid input SkuId, the default SKU Id will be still used.\n"));
329 return;
330 }
331
332 /**
333 Retrieves an 8-bit value for a given PCD token.
334
335 Retrieves the current byte-sized value for a PCD token number.
336 If the TokenNumber is invalid, the results are unpredictable.
337
338 @param[in] TokenNumber The PCD token number.
339
340 @return The UINT8 value.
341
342 **/
343 UINT8
344 EFIAPI
345 DxePcdGet8 (
346 IN UINTN TokenNumber
347 )
348 {
349 return *((UINT8 *)GetWorker (TokenNumber, sizeof (UINT8)));
350 }
351
352 /**
353 Retrieves an 16-bit value for a given PCD token.
354
355 Retrieves the current 16-bits value for a PCD token number.
356 If the TokenNumber is invalid, the results are unpredictable.
357
358 @param[in] TokenNumber The PCD token number.
359
360 @return The UINT16 value.
361
362 **/
363 UINT16
364 EFIAPI
365 DxePcdGet16 (
366 IN UINTN TokenNumber
367 )
368 {
369 return ReadUnaligned16 (GetWorker (TokenNumber, sizeof (UINT16)));
370 }
371
372 /**
373 Retrieves an 32-bit value for a given PCD token.
374
375 Retrieves the current 32-bits value for a PCD token number.
376 If the TokenNumber is invalid, the results are unpredictable.
377
378 @param[in] TokenNumber The PCD token number.
379
380 @return The UINT32 value.
381
382 **/
383 UINT32
384 EFIAPI
385 DxePcdGet32 (
386 IN UINTN TokenNumber
387 )
388 {
389 return ReadUnaligned32 (GetWorker (TokenNumber, sizeof (UINT32)));
390 }
391
392 /**
393 Retrieves an 64-bit value for a given PCD token.
394
395 Retrieves the current 64-bits value for a PCD token number.
396 If the TokenNumber is invalid, the results are unpredictable.
397
398 @param[in] TokenNumber The PCD token number.
399
400 @return The UINT64 value.
401
402 **/
403 UINT64
404 EFIAPI
405 DxePcdGet64 (
406 IN UINTN TokenNumber
407 )
408 {
409 return ReadUnaligned64 (GetWorker (TokenNumber, sizeof (UINT64)));
410 }
411
412 /**
413 Retrieves a pointer to a value for a given PCD token.
414
415 Retrieves the current pointer to the buffer for a PCD token number.
416 Do not make any assumptions about the alignment of the pointer that
417 is returned by this function call. If the TokenNumber is invalid,
418 the results are unpredictable.
419
420 @param[in] TokenNumber The PCD token number.
421
422 @return The pointer to the buffer to be retrived.
423
424 **/
425 VOID *
426 EFIAPI
427 DxePcdGetPtr (
428 IN UINTN TokenNumber
429 )
430 {
431 return GetWorker (TokenNumber, 0);
432 }
433
434 /**
435 Retrieves a Boolean value for a given PCD token.
436
437 Retrieves the current boolean value for a PCD token number.
438 Do not make any assumptions about the alignment of the pointer that
439 is returned by this function call. If the TokenNumber is invalid,
440 the results are unpredictable.
441
442 @param[in] TokenNumber The PCD token number.
443
444 @return The Boolean value.
445
446 **/
447 BOOLEAN
448 EFIAPI
449 DxePcdGetBool (
450 IN UINTN TokenNumber
451 )
452 {
453 return *((BOOLEAN *)GetWorker (TokenNumber, sizeof (BOOLEAN)));
454 }
455
456 /**
457 Retrieves the size of the value for a given PCD token.
458
459 Retrieves the current size of a particular PCD token.
460 If the TokenNumber is invalid, the results are unpredictable.
461
462 @param[in] TokenNumber The PCD token number.
463
464 @return The size of the value for the PCD token.
465
466 **/
467 UINTN
468 EFIAPI
469 DxePcdGetSize (
470 IN UINTN TokenNumber
471 )
472 {
473 UINTN Size;
474 UINT32 *LocalTokenNumberTable;
475 BOOLEAN IsPeiDb;
476 UINTN MaxSize;
477 UINTN TmpTokenNumber;
478
479 //
480 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
481 // We have to decrement TokenNumber by 1 to make it usable
482 // as the array index.
483 //
484 TokenNumber--;
485
486 //
487 // Backup the TokenNumber passed in as GetPtrTypeSize need the original TokenNumber
488 //
489 TmpTokenNumber = TokenNumber;
490
491 // EBC compiler is very choosy. It may report warning about comparison
492 // between UINTN and 0 . So we add 1 in each size of the
493 // comparison.
494 ASSERT (TokenNumber + 1 < mPcdTotalTokenCount + 1);
495
496 // EBC compiler is very choosy. It may report warning about comparison
497 // between UINTN and 0 . So we add 1 in each size of the
498 // comparison.
499 IsPeiDb = (BOOLEAN)(TokenNumber + 1 < mPeiLocalTokenCount + 1);
500
501 TokenNumber = IsPeiDb ? TokenNumber :
502 (TokenNumber - mPeiLocalTokenCount);
503
504 LocalTokenNumberTable = IsPeiDb ? (UINT32 *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->LocalTokenNumberTableOffset)
505 : (UINT32 *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->LocalTokenNumberTableOffset);
506
507 Size = (LocalTokenNumberTable[TokenNumber] & PCD_DATUM_TYPE_ALL_SET) >> PCD_DATUM_TYPE_SHIFT;
508
509 if (Size == 0) {
510 //
511 // For pointer type, we need to scan the SIZE_TABLE to get the current size.
512 //
513 return GetPtrTypeSize (TmpTokenNumber, &MaxSize);
514 } else {
515 return Size;
516 }
517 }
518
519 /**
520 Retrieves an 8-bit value for a given PCD token.
521
522 Retrieves the 8-bit value of a particular PCD token.
523 If the TokenNumber is invalid or the token space
524 specified by Guid does not exist, the results are
525 unpredictable.
526
527 @param[in] Guid The token space for the token number.
528 @param[in] ExTokenNumber The PCD token number.
529
530 @return The size 8-bit value for the PCD token.
531
532 **/
533 UINT8
534 EFIAPI
535 DxePcdGet8Ex (
536 IN CONST EFI_GUID *Guid,
537 IN UINTN ExTokenNumber
538 )
539 {
540 return *((UINT8 *)ExGetWorker (Guid, ExTokenNumber, sizeof (UINT8)));
541 }
542
543 /**
544 Retrieves an 16-bit value for a given PCD token.
545
546 Retrieves the 16-bit value of a particular PCD token.
547 If the TokenNumber is invalid or the token space
548 specified by Guid does not exist, the results are
549 unpredictable.
550
551 @param[in] Guid The token space for the token number.
552 @param[in] ExTokenNumber The PCD token number.
553
554 @return The size 16-bit value for the PCD token.
555
556 **/
557 UINT16
558 EFIAPI
559 DxePcdGet16Ex (
560 IN CONST EFI_GUID *Guid,
561 IN UINTN ExTokenNumber
562 )
563 {
564 return ReadUnaligned16 (ExGetWorker (Guid, ExTokenNumber, sizeof (UINT16)));
565 }
566
567 /**
568 Retrieves an 32-bit value for a given PCD token.
569
570 Retrieves the 32-bit value of a particular PCD token.
571 If the TokenNumber is invalid or the token space
572 specified by Guid does not exist, the results are
573 unpredictable.
574
575 @param[in] Guid The token space for the token number.
576 @param[in] ExTokenNumber The PCD token number.
577
578 @return The size 32-bit value for the PCD token.
579
580 **/
581 UINT32
582 EFIAPI
583 DxePcdGet32Ex (
584 IN CONST EFI_GUID *Guid,
585 IN UINTN ExTokenNumber
586 )
587 {
588 return ReadUnaligned32 (ExGetWorker (Guid, ExTokenNumber, sizeof (UINT32)));
589 }
590
591 /**
592 Retrieves an 64-bit value for a given PCD token.
593
594 Retrieves the 64-bit value of a particular PCD token.
595 If the TokenNumber is invalid or the token space
596 specified by Guid does not exist, the results are
597 unpredictable.
598
599 @param[in] Guid The token space for the token number.
600 @param[in] ExTokenNumber The PCD token number.
601
602 @return The size 64-bit value for the PCD token.
603
604 **/
605 UINT64
606 EFIAPI
607 DxePcdGet64Ex (
608 IN CONST EFI_GUID *Guid,
609 IN UINTN ExTokenNumber
610 )
611 {
612 return ReadUnaligned64 (ExGetWorker (Guid, ExTokenNumber, sizeof (UINT64)));
613 }
614
615 /**
616 Retrieves a pointer to a value for a given PCD token.
617
618 Retrieves the current pointer to the buffer for a PCD token number.
619 Do not make any assumptions about the alignment of the pointer that
620 is returned by this function call. If the TokenNumber is invalid,
621 the results are unpredictable.
622
623 @param[in] Guid The token space for the token number.
624 @param[in] ExTokenNumber The PCD token number.
625
626 @return The pointer to the buffer to be retrived.
627
628 **/
629 VOID *
630 EFIAPI
631 DxePcdGetPtrEx (
632 IN CONST EFI_GUID *Guid,
633 IN UINTN ExTokenNumber
634 )
635 {
636 return ExGetWorker (Guid, ExTokenNumber, 0);
637 }
638
639 /**
640 Retrieves an Boolean value for a given PCD token.
641
642 Retrieves the Boolean value of a particular PCD token.
643 If the TokenNumber is invalid or the token space
644 specified by Guid does not exist, the results are
645 unpredictable.
646
647 @param[in] Guid The token space for the token number.
648 @param[in] ExTokenNumber The PCD token number.
649
650 @return The size Boolean value for the PCD token.
651
652 **/
653 BOOLEAN
654 EFIAPI
655 DxePcdGetBoolEx (
656 IN CONST EFI_GUID *Guid,
657 IN UINTN ExTokenNumber
658 )
659 {
660 return *((BOOLEAN *)ExGetWorker (Guid, ExTokenNumber, sizeof (BOOLEAN)));
661 }
662
663 /**
664 Retrieves the size of the value for a given PCD token.
665
666 Retrieves the current size of a particular PCD token.
667 If the TokenNumber is invalid, the results are unpredictable.
668
669 @param[in] Guid The token space for the token number.
670 @param[in] ExTokenNumber The PCD token number.
671
672 @return The size of the value for the PCD token.
673
674 **/
675 UINTN
676 EFIAPI
677 DxePcdGetSizeEx (
678 IN CONST EFI_GUID *Guid,
679 IN UINTN ExTokenNumber
680 )
681 {
682 return DxePcdGetSize (GetExPcdTokenNumber (Guid, (UINT32)ExTokenNumber));
683 }
684
685 /**
686 Sets an 8-bit value for a given PCD token.
687
688 When the PCD service sets a value, it will check to ensure that the
689 size of the value being set is compatible with the Token's existing definition.
690 If it is not, an error will be returned.
691
692 @param[in] TokenNumber The PCD token number.
693 @param[in] Value The value to set for the PCD token.
694
695 @retval EFI_SUCCESS Procedure returned successfully.
696 @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
697 being set was incompatible with a call to this function.
698 Use GetSize() to retrieve the size of the target data.
699 @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
700
701 **/
702 EFI_STATUS
703 EFIAPI
704 DxePcdSet8 (
705 IN UINTN TokenNumber,
706 IN UINT8 Value
707 )
708 {
709 return SetValueWorker (TokenNumber, &Value, sizeof (Value));
710 }
711
712 /**
713 Sets an 16-bit value for a given PCD token.
714
715 When the PCD service sets a value, it will check to ensure that the
716 size of the value being set is compatible with the Token's existing definition.
717 If it is not, an error will be returned.
718
719 @param[in] TokenNumber The PCD token number.
720 @param[in] Value The value to set for the PCD token.
721
722 @retval EFI_SUCCESS Procedure returned successfully.
723 @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
724 being set was incompatible with a call to this function.
725 Use GetSize() to retrieve the size of the target data.
726 @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
727
728 **/
729 EFI_STATUS
730 EFIAPI
731 DxePcdSet16 (
732 IN UINTN TokenNumber,
733 IN UINT16 Value
734 )
735 {
736 return SetValueWorker (TokenNumber, &Value, sizeof (Value));
737 }
738
739 /**
740 Sets an 32-bit value for a given PCD token.
741
742 When the PCD service sets a value, it will check to ensure that the
743 size of the value being set is compatible with the Token's existing definition.
744 If it is not, an error will be returned.
745
746 @param[in] TokenNumber The PCD token number.
747 @param[in] Value The value to set for the PCD token.
748
749 @retval EFI_SUCCESS Procedure returned successfully.
750 @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
751 being set was incompatible with a call to this function.
752 Use GetSize() to retrieve the size of the target data.
753 @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
754
755 **/
756 EFI_STATUS
757 EFIAPI
758 DxePcdSet32 (
759 IN UINTN TokenNumber,
760 IN UINT32 Value
761 )
762 {
763 return SetValueWorker (TokenNumber, &Value, sizeof (Value));
764 }
765
766 /**
767 Sets an 64-bit value for a given PCD token.
768
769 When the PCD service sets a value, it will check to ensure that the
770 size of the value being set is compatible with the Token's existing definition.
771 If it is not, an error will be returned.
772
773 @param[in] TokenNumber The PCD token number.
774 @param[in] Value The value to set for the PCD token.
775
776 @retval EFI_SUCCESS Procedure returned successfully.
777 @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
778 being set was incompatible with a call to this function.
779 Use GetSize() to retrieve the size of the target data.
780 @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
781
782 **/
783 EFI_STATUS
784 EFIAPI
785 DxePcdSet64 (
786 IN UINTN TokenNumber,
787 IN UINT64 Value
788 )
789 {
790 return SetValueWorker (TokenNumber, &Value, sizeof (Value));
791 }
792
793 /**
794 Sets a value of a specified size for a given PCD token.
795
796 When the PCD service sets a value, it will check to ensure that the
797 size of the value being set is compatible with the Token's existing definition.
798 If it is not, an error will be returned.
799
800 @param[in] TokenNumber The PCD token number.
801 @param[in, out] SizeOfBuffer A pointer to the length of the value being set for the PCD token.
802 On input, if the SizeOfValue is greater than the maximum size supported
803 for this TokenNumber then the output value of SizeOfValue will reflect
804 the maximum size supported for this TokenNumber.
805 @param[in] Buffer The buffer to set for the PCD token.
806
807 @retval EFI_SUCCESS Procedure returned successfully.
808 @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
809 being set was incompatible with a call to this function.
810 Use GetSize() to retrieve the size of the target data.
811 @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
812
813 **/
814 EFI_STATUS
815 EFIAPI
816 DxePcdSetPtr (
817 IN UINTN TokenNumber,
818 IN OUT UINTN *SizeOfBuffer,
819 IN VOID *Buffer
820 )
821 {
822 return SetWorker (TokenNumber, Buffer, SizeOfBuffer, TRUE);
823 }
824
825 /**
826 Sets an Boolean value for a given PCD token.
827
828 When the PCD service sets a value, it will check to ensure that the
829 size of the value being set is compatible with the Token's existing definition.
830 If it is not, an error will be returned.
831
832 @param[in] TokenNumber The PCD token number.
833 @param[in] Value The value to set for the PCD token.
834
835 @retval EFI_SUCCESS Procedure returned successfully.
836 @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
837 being set was incompatible with a call to this function.
838 Use GetSize() to retrieve the size of the target data.
839 @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
840
841 **/
842 EFI_STATUS
843 EFIAPI
844 DxePcdSetBool (
845 IN UINTN TokenNumber,
846 IN BOOLEAN Value
847 )
848 {
849 return SetValueWorker (TokenNumber, &Value, sizeof (Value));
850 }
851
852 /**
853 Sets an 8-bit value for a given PCD token.
854
855 When the PCD service sets a value, it will check to ensure that the
856 size of the value being set is compatible with the Token's existing definition.
857 If it is not, an error will be returned.
858
859 @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
860 @param[in] ExTokenNumber The PCD token number.
861 @param[in] Value The value to set for the PCD token.
862
863 @retval EFI_SUCCESS Procedure returned successfully.
864 @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
865 being set was incompatible with a call to this function.
866 Use GetSize() to retrieve the size of the target data.
867 @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
868
869 **/
870 EFI_STATUS
871 EFIAPI
872 DxePcdSet8Ex (
873 IN CONST EFI_GUID *Guid,
874 IN UINTN ExTokenNumber,
875 IN UINT8 Value
876 )
877 {
878 return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));
879 }
880
881 /**
882 Sets an 16-bit value for a given PCD token.
883
884 When the PCD service sets a value, it will check to ensure that the
885 size of the value being set is compatible with the Token's existing definition.
886 If it is not, an error will be returned.
887
888 @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
889 @param[in] ExTokenNumber The PCD token number.
890 @param[in] Value The value to set for the PCD token.
891
892 @retval EFI_SUCCESS Procedure returned successfully.
893 @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
894 being set was incompatible with a call to this function.
895 Use GetSize() to retrieve the size of the target data.
896 @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
897
898 **/
899 EFI_STATUS
900 EFIAPI
901 DxePcdSet16Ex (
902 IN CONST EFI_GUID *Guid,
903 IN UINTN ExTokenNumber,
904 IN UINT16 Value
905 )
906 {
907 //
908 // PcdSetNvStoreDefaultId should be set in PEI phase to take effect.
909 //
910 ASSERT (
911 !(CompareGuid (Guid, &gEfiMdeModulePkgTokenSpaceGuid) &&
912 (ExTokenNumber == PcdToken (PcdSetNvStoreDefaultId)))
913 );
914 return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));
915 }
916
917 /**
918 Sets an 32-bit value for a given PCD token.
919
920 When the PCD service sets a value, it will check to ensure that the
921 size of the value being set is compatible with the Token's existing definition.
922 If it is not, an error will be returned.
923
924 @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
925 @param[in] ExTokenNumber The PCD token number.
926 @param[in] Value The value to set for the PCD token.
927
928 @retval EFI_SUCCESS Procedure returned successfully.
929 @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
930 being set was incompatible with a call to this function.
931 Use GetSize() to retrieve the size of the target data.
932 @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
933
934 **/
935 EFI_STATUS
936 EFIAPI
937 DxePcdSet32Ex (
938 IN CONST EFI_GUID *Guid,
939 IN UINTN ExTokenNumber,
940 IN UINT32 Value
941 )
942 {
943 return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));
944 }
945
946 /**
947 Sets an 64-bit value for a given PCD token.
948
949 When the PCD service sets a value, it will check to ensure that the
950 size of the value being set is compatible with the Token's existing definition.
951 If it is not, an error will be returned.
952
953 @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
954 @param[in] ExTokenNumber The PCD token number.
955 @param[in] Value The value to set for the PCD token.
956
957 @retval EFI_SUCCESS Procedure returned successfully.
958 @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
959 being set was incompatible with a call to this function.
960 Use GetSize() to retrieve the size of the target data.
961 @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
962
963 **/
964 EFI_STATUS
965 EFIAPI
966 DxePcdSet64Ex (
967 IN CONST EFI_GUID *Guid,
968 IN UINTN ExTokenNumber,
969 IN UINT64 Value
970 )
971 {
972 return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));
973 }
974
975 /**
976 Sets a value of a specified size for a given PCD token.
977
978 When the PCD service sets a value, it will check to ensure that the
979 size of the value being set is compatible with the Token's existing definition.
980 If it is not, an error will be returned.
981
982 @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
983 @param[in] ExTokenNumber The PCD token number.
984 @param[in, out] SizeOfBuffer A pointer to the length of the value being set for the PCD token.
985 On input, if the SizeOfValue is greater than the maximum size supported
986 for this TokenNumber then the output value of SizeOfValue will reflect
987 the maximum size supported for this TokenNumber.
988 @param[in] Buffer The buffer to set for the PCD token.
989
990 @retval EFI_SUCCESS Procedure returned successfully.
991 @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
992 being set was incompatible with a call to this function.
993 Use GetSize() to retrieve the size of the target data.
994 @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
995
996 **/
997 EFI_STATUS
998 EFIAPI
999 DxePcdSetPtrEx (
1000 IN CONST EFI_GUID *Guid,
1001 IN UINTN ExTokenNumber,
1002 IN OUT UINTN *SizeOfBuffer,
1003 IN VOID *Buffer
1004 )
1005 {
1006 return ExSetWorker (ExTokenNumber, Guid, Buffer, SizeOfBuffer, TRUE);
1007 }
1008
1009 /**
1010 Sets an Boolean value for a given PCD token.
1011
1012 When the PCD service sets a value, it will check to ensure that the
1013 size of the value being set is compatible with the Token's existing definition.
1014 If it is not, an error will be returned.
1015
1016 @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
1017 @param[in] ExTokenNumber The PCD token number.
1018 @param[in] Value The value to set for the PCD token.
1019
1020 @retval EFI_SUCCESS Procedure returned successfully.
1021 @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
1022 being set was incompatible with a call to this function.
1023 Use GetSize() to retrieve the size of the target data.
1024 @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
1025
1026 **/
1027 EFI_STATUS
1028 EFIAPI
1029 DxePcdSetBoolEx (
1030 IN CONST EFI_GUID *Guid,
1031 IN UINTN ExTokenNumber,
1032 IN BOOLEAN Value
1033 )
1034 {
1035 return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));
1036 }
1037
1038 /**
1039 Specifies a function to be called anytime the value of a designated token is changed.
1040
1041 @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
1042 @param[in] TokenNumber The PCD token number.
1043 @param[in] CallBackFunction The function prototype called when the value associated with the CallBackToken is set.
1044
1045 @retval EFI_SUCCESS The PCD service has successfully established a call event
1046 for the CallBackToken requested.
1047 @retval EFI_NOT_FOUND The PCD service could not find the referenced token number.
1048
1049 **/
1050 EFI_STATUS
1051 EFIAPI
1052 DxeRegisterCallBackOnSet (
1053 IN CONST EFI_GUID *Guid OPTIONAL,
1054 IN UINTN TokenNumber,
1055 IN PCD_PROTOCOL_CALLBACK CallBackFunction
1056 )
1057 {
1058 EFI_STATUS Status;
1059
1060 if (CallBackFunction == NULL) {
1061 return EFI_INVALID_PARAMETER;
1062 }
1063
1064 //
1065 // Aquire lock to prevent reentrance from TPL_CALLBACK level
1066 //
1067 EfiAcquireLock (&mPcdDatabaseLock);
1068
1069 Status = DxeRegisterCallBackWorker (TokenNumber, Guid, CallBackFunction);
1070
1071 EfiReleaseLock (&mPcdDatabaseLock);
1072
1073 return Status;
1074 }
1075
1076 /**
1077 Cancels a previously set callback function for a particular PCD token number.
1078
1079 @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
1080 @param[in] TokenNumber The PCD token number.
1081 @param[in] CallBackFunction The function prototype called when the value associated with the CallBackToken is set.
1082
1083 @retval EFI_SUCCESS The PCD service has successfully established a call event
1084 for the CallBackToken requested.
1085 @retval EFI_NOT_FOUND The PCD service could not find the referenced token number.
1086
1087 **/
1088 EFI_STATUS
1089 EFIAPI
1090 DxeUnRegisterCallBackOnSet (
1091 IN CONST EFI_GUID *Guid OPTIONAL,
1092 IN UINTN TokenNumber,
1093 IN PCD_PROTOCOL_CALLBACK CallBackFunction
1094 )
1095 {
1096 EFI_STATUS Status;
1097
1098 if (CallBackFunction == NULL) {
1099 return EFI_INVALID_PARAMETER;
1100 }
1101
1102 //
1103 // Aquire lock to prevent reentrance from TPL_CALLBACK level
1104 //
1105 EfiAcquireLock (&mPcdDatabaseLock);
1106
1107 Status = DxeUnRegisterCallBackWorker (TokenNumber, Guid, CallBackFunction);
1108
1109 EfiReleaseLock (&mPcdDatabaseLock);
1110
1111 return Status;
1112 }
1113
1114 /**
1115 Retrieves the next valid token number in a given namespace.
1116
1117 This is useful since the PCD infrastructure contains a sparse list of token numbers,
1118 and one cannot a priori know what token numbers are valid in the database.
1119
1120 If TokenNumber is 0 and Guid is not NULL, then the first token from the token space specified by Guid is returned.
1121 If TokenNumber is not 0 and Guid is not NULL, then the next token in the token space specified by Guid is returned.
1122 If TokenNumber is 0 and Guid is NULL, then the first token in the default token space is returned.
1123 If TokenNumber is not 0 and Guid is NULL, then the next token in the default token space is returned.
1124 The token numbers in the default token space may not be related to token numbers in token spaces that are named by Guid.
1125 If the next token number can be retrieved, then it is returned in TokenNumber, and EFI_SUCCESS is returned.
1126 If TokenNumber represents the last token number in the token space specified by Guid, then EFI_NOT_FOUND is returned.
1127 If TokenNumber is not present in the token space specified by Guid, then EFI_NOT_FOUND is returned.
1128
1129
1130 @param[in] Guid The 128-bit unique value that designates the namespace from which to retrieve the next token.
1131 This is an optional parameter that may be NULL. If this parameter is NULL, then a request is
1132 being made to retrieve tokens from the default token space.
1133 @param[in, out] TokenNumber
1134 A pointer to the PCD token number to use to find the subsequent token number.
1135
1136 @retval EFI_SUCCESS The PCD service has retrieved the next valid token number.
1137 @retval EFI_NOT_FOUND The PCD service could not find data from the requested token number.
1138
1139 **/
1140 EFI_STATUS
1141 EFIAPI
1142 DxePcdGetNextToken (
1143 IN CONST EFI_GUID *Guid OPTIONAL,
1144 IN OUT UINTN *TokenNumber
1145 )
1146 {
1147 EFI_STATUS Status;
1148 BOOLEAN PeiExMapTableEmpty;
1149 BOOLEAN DxeExMapTableEmpty;
1150
1151 Status = EFI_NOT_FOUND;
1152 PeiExMapTableEmpty = mPeiExMapTableEmpty;
1153 DxeExMapTableEmpty = mDxeExMapTableEmpty;
1154
1155 //
1156 // Scan the local token space
1157 //
1158 if (Guid == NULL) {
1159 // EBC compiler is very choosy. It may report warning about comparison
1160 // between UINTN and 0 . So we add 1 in each size of the
1161 // comparison.
1162 if (((*TokenNumber + 1 > mPeiNexTokenCount + 1) && (*TokenNumber + 1 <= mPeiLocalTokenCount + 1)) ||
1163 ((*TokenNumber + 1 > (mPeiLocalTokenCount + mDxeNexTokenCount + 1))))
1164 {
1165 return EFI_NOT_FOUND;
1166 }
1167
1168 (*TokenNumber)++;
1169 if ((*TokenNumber + 1 > mPeiNexTokenCount + 1) &&
1170 (*TokenNumber + 1 <= mPeiLocalTokenCount + 1))
1171 {
1172 //
1173 // The first Non-Ex type Token Number for DXE PCD
1174 // database is mPeiLocalTokenCount + 1
1175 //
1176 if (mDxeNexTokenCount > 0) {
1177 *TokenNumber = mPeiLocalTokenCount + 1;
1178 } else {
1179 *TokenNumber = PCD_INVALID_TOKEN_NUMBER;
1180 return EFI_NOT_FOUND;
1181 }
1182 } else if (*TokenNumber + 1 > mDxeNexTokenCount + mPeiLocalTokenCount + 1) {
1183 *TokenNumber = PCD_INVALID_TOKEN_NUMBER;
1184 return EFI_NOT_FOUND;
1185 }
1186
1187 return EFI_SUCCESS;
1188 }
1189
1190 if (PeiExMapTableEmpty && DxeExMapTableEmpty) {
1191 return EFI_NOT_FOUND;
1192 }
1193
1194 if (!PeiExMapTableEmpty) {
1195 Status = ExGetNextTokeNumber (
1196 Guid,
1197 TokenNumber,
1198 (EFI_GUID *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->GuidTableOffset),
1199 mPeiGuidTableSize,
1200 (DYNAMICEX_MAPPING *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->ExMapTableOffset),
1201 mPeiExMapppingTableSize
1202 );
1203 }
1204
1205 if (Status == EFI_SUCCESS) {
1206 return Status;
1207 }
1208
1209 if (!DxeExMapTableEmpty) {
1210 Status = ExGetNextTokeNumber (
1211 Guid,
1212 TokenNumber,
1213 (EFI_GUID *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->GuidTableOffset),
1214 mDxeGuidTableSize,
1215 (DYNAMICEX_MAPPING *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->ExMapTableOffset),
1216 mDxeExMapppingTableSize
1217 );
1218 }
1219
1220 return Status;
1221 }
1222
1223 /**
1224 Get all token space guid table which is different with given token space guid.
1225
1226 @param ExMapTableSize The size of ExMapTable in item
1227 @param ExMapTable Token space guid table that want to be scaned.
1228 @param GuidTable Guid table
1229
1230 @return all token space guid table which is different with given token space guid.
1231
1232 **/
1233 EFI_GUID **
1234 GetDistinctTokenSpace (
1235 IN OUT UINTN *ExMapTableSize,
1236 IN DYNAMICEX_MAPPING *ExMapTable,
1237 IN EFI_GUID *GuidTable
1238 )
1239 {
1240 EFI_GUID **DistinctTokenSpace;
1241 UINTN OldGuidIndex;
1242 UINTN TsIdx;
1243 UINTN TempTsIdx;
1244 UINTN Idx;
1245 BOOLEAN Match;
1246
1247 DistinctTokenSpace = AllocateZeroPool (*ExMapTableSize * sizeof (EFI_GUID *));
1248 ASSERT (DistinctTokenSpace != NULL);
1249
1250 TsIdx = 0;
1251 OldGuidIndex = ExMapTable[0].ExGuidIndex;
1252 DistinctTokenSpace[TsIdx] = &GuidTable[OldGuidIndex];
1253 for (Idx = 1; Idx < *ExMapTableSize; Idx++) {
1254 Match = FALSE;
1255 OldGuidIndex = ExMapTable[Idx].ExGuidIndex;
1256 for (TempTsIdx = 0; TempTsIdx <= TsIdx; TempTsIdx++) {
1257 if (&GuidTable[OldGuidIndex] == DistinctTokenSpace[TempTsIdx]) {
1258 //
1259 // Have recorded this GUID.
1260 //
1261 Match = TRUE;
1262 break;
1263 }
1264 }
1265
1266 if (!Match) {
1267 DistinctTokenSpace[++TsIdx] = &GuidTable[OldGuidIndex];
1268 }
1269 }
1270
1271 //
1272 // The total number of Distinct Token Space
1273 // is TsIdx + 1 because we use TsIdx as a index
1274 // to the DistinctTokenSpace[]
1275 //
1276 *ExMapTableSize = TsIdx + 1;
1277 return DistinctTokenSpace;
1278 }
1279
1280 /**
1281 Retrieves the next valid PCD token namespace for a given namespace.
1282
1283 Gets the next valid token namespace for a given namespace. This is useful to traverse the valid
1284 token namespaces on a platform.
1285
1286 @param[in, out] Guid An indirect pointer to EFI_GUID. On input it designates a known token
1287 namespace from which the search will start. On output, it designates the next valid
1288 token namespace on the platform. If *Guid is NULL, then the GUID of the first token
1289 space of the current platform is returned. If the search cannot locate the next valid
1290 token namespace, an error is returned and the value of *Guid is undefined.
1291
1292 @retval EFI_SUCCESS The PCD service retrieved the value requested.
1293 @retval EFI_NOT_FOUND The PCD service could not find the next valid token namespace.
1294
1295 **/
1296 EFI_STATUS
1297 EFIAPI
1298 DxePcdGetNextTokenSpace (
1299 IN OUT CONST EFI_GUID **Guid
1300 )
1301 {
1302 UINTN Idx;
1303 UINTN Idx2;
1304 UINTN Idx3;
1305 UINTN PeiTokenSpaceTableSize;
1306 UINTN DxeTokenSpaceTableSize;
1307 EFI_GUID **PeiTokenSpaceTable;
1308 EFI_GUID **DxeTokenSpaceTable;
1309 BOOLEAN Match;
1310 BOOLEAN PeiExMapTableEmpty;
1311 BOOLEAN DxeExMapTableEmpty;
1312
1313 ASSERT (Guid != NULL);
1314
1315 PeiExMapTableEmpty = mPeiExMapTableEmpty;
1316 DxeExMapTableEmpty = mDxeExMapTableEmpty;
1317
1318 if (PeiExMapTableEmpty && DxeExMapTableEmpty) {
1319 return EFI_NOT_FOUND;
1320 }
1321
1322 if (TmpTokenSpaceBuffer[0] == NULL) {
1323 PeiTokenSpaceTableSize = 0;
1324
1325 if (!PeiExMapTableEmpty) {
1326 PeiTokenSpaceTableSize = mPeiExMapppingTableSize / sizeof (DYNAMICEX_MAPPING);
1327 PeiTokenSpaceTable = GetDistinctTokenSpace (
1328 &PeiTokenSpaceTableSize,
1329 (DYNAMICEX_MAPPING *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->ExMapTableOffset),
1330 (EFI_GUID *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->GuidTableOffset)
1331 );
1332 CopyMem (TmpTokenSpaceBuffer, PeiTokenSpaceTable, sizeof (EFI_GUID *) * PeiTokenSpaceTableSize);
1333 TmpTokenSpaceBufferCount = PeiTokenSpaceTableSize;
1334 FreePool (PeiTokenSpaceTable);
1335 }
1336
1337 if (!DxeExMapTableEmpty) {
1338 DxeTokenSpaceTableSize = mDxeExMapppingTableSize / sizeof (DYNAMICEX_MAPPING);
1339 DxeTokenSpaceTable = GetDistinctTokenSpace (
1340 &DxeTokenSpaceTableSize,
1341 (DYNAMICEX_MAPPING *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->ExMapTableOffset),
1342 (EFI_GUID *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->GuidTableOffset)
1343 );
1344
1345 //
1346 // Make sure EFI_GUID in DxeTokenSpaceTable does not exist in PeiTokenSpaceTable
1347 //
1348 for (Idx2 = 0, Idx3 = PeiTokenSpaceTableSize; Idx2 < DxeTokenSpaceTableSize; Idx2++) {
1349 Match = FALSE;
1350 for (Idx = 0; Idx < PeiTokenSpaceTableSize; Idx++) {
1351 if (CompareGuid (TmpTokenSpaceBuffer[Idx], DxeTokenSpaceTable[Idx2])) {
1352 Match = TRUE;
1353 break;
1354 }
1355 }
1356
1357 if (!Match) {
1358 TmpTokenSpaceBuffer[Idx3++] = DxeTokenSpaceTable[Idx2];
1359 }
1360 }
1361
1362 TmpTokenSpaceBufferCount = Idx3;
1363 FreePool (DxeTokenSpaceTable);
1364 }
1365 }
1366
1367 if (*Guid == NULL) {
1368 *Guid = TmpTokenSpaceBuffer[0];
1369 return EFI_SUCCESS;
1370 }
1371
1372 for (Idx = 0; Idx < TmpTokenSpaceBufferCount; Idx++) {
1373 if (CompareGuid (*Guid, TmpTokenSpaceBuffer[Idx])) {
1374 if (Idx == TmpTokenSpaceBufferCount - 1) {
1375 //
1376 // It has been the last token namespace.
1377 //
1378 *Guid = NULL;
1379 return EFI_NOT_FOUND;
1380 } else {
1381 Idx++;
1382 *Guid = TmpTokenSpaceBuffer[Idx];
1383 return EFI_SUCCESS;
1384 }
1385 }
1386 }
1387
1388 return EFI_NOT_FOUND;
1389 }