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