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