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