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