Home | History | Annotate | Download | only in Dxe
      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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
   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
   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
   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 **
   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
   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