]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/PCD/Pei/Pcd.c
f31e0be35f2f53bd9fc9ad646e60c5274d928277
[mirror_edk2.git] / MdeModulePkg / Universal / PCD / Pei / Pcd.c
1 /** @file
2 All Pcd Ppi services are implemented here.
3
4 Copyright (c) 2006 - 2021, 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
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
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
335 PcdPeimInit (
336 IN EFI_PEI_FILE_HANDLE FileHandle,
337 IN CONST EFI_PEI_SERVICES **PeiServices
338 )
339 {
340 EFI_STATUS Status;
341
342 Status = PeiServicesRegisterForShadow (FileHandle);
343 if (Status == EFI_ALREADY_STARTED) {
344 //
345 // This is now starting in memory, the second time starting.
346 //
347 EFI_PEI_PPI_DESCRIPTOR *OldPpiList;
348 EFI_PEI_PPI_DESCRIPTOR *OldPpiList2;
349 VOID *Ppi;
350 VOID *Ppi2;
351
352 OldPpiList = NULL;
353 Status = PeiServicesLocatePpi (
354 &gPcdPpiGuid,
355 0,
356 &OldPpiList,
357 &Ppi
358 );
359 ASSERT_EFI_ERROR (Status);
360
361 if (OldPpiList != NULL) {
362 Status = PeiServicesReInstallPpi (OldPpiList, &mPpiList[0]);
363 ASSERT_EFI_ERROR (Status);
364 }
365
366 OldPpiList2 = NULL;
367 Status = PeiServicesLocatePpi (
368 &gGetPcdInfoPpiGuid,
369 0,
370 &OldPpiList2,
371 &Ppi2
372 );
373 ASSERT_EFI_ERROR (Status);
374
375 if (OldPpiList2 != NULL) {
376 Status = PeiServicesReInstallPpi (OldPpiList2, &mPpiList2[0]);
377 ASSERT_EFI_ERROR (Status);
378 }
379
380 OldPpiList = NULL;
381 Status = PeiServicesLocatePpi (
382 &gEfiPeiPcdPpiGuid,
383 0,
384 &OldPpiList,
385 &Ppi
386 );
387 ASSERT_EFI_ERROR (Status);
388
389 if (OldPpiList != NULL) {
390 Status = PeiServicesReInstallPpi (OldPpiList, &mPpiList[1]);
391 ASSERT_EFI_ERROR (Status);
392 }
393
394 OldPpiList2 = NULL;
395 Status = PeiServicesLocatePpi (
396 &gEfiGetPcdInfoPpiGuid,
397 0,
398 &OldPpiList2,
399 &Ppi2
400 );
401 ASSERT_EFI_ERROR (Status);
402
403 if (OldPpiList2 != NULL) {
404 Status = PeiServicesReInstallPpi (OldPpiList2, &mPpiList2[1]);
405 ASSERT_EFI_ERROR (Status);
406 }
407
408 return Status;
409 }
410
411 BuildPcdDatabase (FileHandle);
412
413 //
414 // Install PCD_PPI and EFI_PEI_PCD_PPI.
415 //
416 Status = PeiServicesInstallPpi (&mPpiList[0]);
417 ASSERT_EFI_ERROR (Status);
418
419 //
420 // Install GET_PCD_INFO_PPI and EFI_GET_PCD_INFO_PPI.
421 //
422 Status = PeiServicesInstallPpi (&mPpiList2[0]);
423 ASSERT_EFI_ERROR (Status);
424
425 Status = PeiServicesNotifyPpi (&mEndOfPeiSignalPpiNotifyList[0]);
426 ASSERT_EFI_ERROR (Status);
427
428 Status = PeiRegisterCallBackOnSet (
429 &gEfiMdeModulePkgTokenSpaceGuid,
430 PcdToken(PcdSetNvStoreDefaultId),
431 PcdSetNvStoreDefaultIdCallBack
432 );
433 ASSERT_EFI_ERROR (Status);
434
435 return Status;
436 }
437
438 /**
439 Retrieve additional information associated with a PCD token in the default token space.
440
441 This includes information such as the type of value the TokenNumber is associated with as well as possible
442 human readable name that is associated with the token.
443
444 @param[in] TokenNumber The PCD token number.
445 @param[out] PcdInfo The returned information associated with the requested TokenNumber.
446 The caller is responsible for freeing the buffer that is allocated by callee for PcdInfo->PcdName.
447
448 @retval EFI_SUCCESS The PCD information was returned successfully.
449 @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
450 **/
451 EFI_STATUS
452 EFIAPI
453 PeiGetPcdInfoGetInfo (
454 IN UINTN TokenNumber,
455 OUT EFI_PCD_INFO *PcdInfo
456 )
457 {
458 return PeiGetPcdInfo (NULL, TokenNumber, PcdInfo);
459 }
460
461 /**
462 Retrieve additional information associated with a PCD token.
463
464 This includes information such as the type of value the TokenNumber is associated with as well as possible
465 human readable name that is associated with the token.
466
467 @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
468 @param[in] TokenNumber The PCD token number.
469 @param[out] PcdInfo The returned information associated with the requested TokenNumber.
470 The caller is responsible for freeing the buffer that is allocated by callee for PcdInfo->PcdName.
471
472 @retval EFI_SUCCESS The PCD information was returned successfully.
473 @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
474 **/
475 EFI_STATUS
476 EFIAPI
477 PeiGetPcdInfoGetInfoEx (
478 IN CONST EFI_GUID *Guid,
479 IN UINTN TokenNumber,
480 OUT EFI_PCD_INFO *PcdInfo
481 )
482 {
483 return PeiGetPcdInfo (Guid, TokenNumber, PcdInfo);
484 }
485
486 /**
487 Retrieve the currently set SKU Id.
488
489 @return The currently set SKU Id. If the platform has not set at a SKU Id, then the
490 default SKU Id value of 0 is returned. If the platform has set a SKU Id, then the currently set SKU
491 Id is returned.
492 **/
493 UINTN
494 EFIAPI
495 PeiGetPcdInfoGetSku (
496 VOID
497 )
498 {
499 return (UINTN) GetPcdDatabase()->SystemSkuId;
500 }
501
502 /**
503 Sets the SKU value for subsequent calls to set or get PCD token values.
504
505 SetSku() sets the SKU Id to be used for subsequent calls to set or get PCD values.
506 SetSku() is normally called only once by the system.
507
508 For each item (token), the database can hold a single value that applies to all SKUs,
509 or multiple values, where each value is associated with a specific SKU Id. Items with multiple,
510 SKU-specific values are called SKU enabled.
511
512 The SKU Id of zero is reserved as a default.
513 For tokens that are not SKU enabled, the system ignores any set SKU Id and works with the
514 single value for that token. For SKU-enabled tokens, the system will use the SKU Id set by the
515 last call to SetSku(). If no SKU Id is set or the currently set SKU Id isn't valid for the specified token,
516 the system uses the default SKU Id. If the system attempts to use the default SKU Id and no value has been
517 set for that Id, the results are unpredictable.
518
519 @param[in] SkuId The SKU value that will be used when the PCD service will retrieve and
520 set values associated with a PCD token.
521
522 **/
523 VOID
524 EFIAPI
525 PeiPcdSetSku (
526 IN UINTN SkuId
527 )
528 {
529 PEI_PCD_DATABASE *PeiPcdDb;
530 SKU_ID *SkuIdTable;
531 UINTN Index;
532 EFI_STATUS Status;
533 UINTN Instance;
534 EFI_PEI_FV_HANDLE VolumeHandle;
535 EFI_PEI_FILE_HANDLE FileHandle;
536 VOID *PcdDb;
537 UINT32 Length;
538 PCD_DATABASE_SKU_DELTA *SkuDelta;
539 PCD_DATA_DELTA *SkuDeltaData;
540
541 DEBUG ((DEBUG_INFO, "PcdPei - SkuId 0x%lx is to be set.\n", (SKU_ID) SkuId));
542
543 PeiPcdDb = GetPcdDatabase();
544
545 if (SkuId == PeiPcdDb->SystemSkuId) {
546 //
547 // The input SKU Id is equal to current SKU Id, return directly.
548 //
549 DEBUG ((DEBUG_INFO, "PcdPei - SkuId is same to current system Sku.\n"));
550 return;
551 }
552
553 if (PeiPcdDb->SystemSkuId != (SKU_ID) 0) {
554 DEBUG ((DEBUG_ERROR, "PcdPei - The SKU Id could be changed only once."));
555 DEBUG ((
556 DEBUG_ERROR,
557 "PcdPei - The SKU Id was set to 0x%lx already, it could not be set to 0x%lx any more.",
558 PeiPcdDb->SystemSkuId,
559 (SKU_ID) SkuId
560 ));
561 ASSERT (FALSE);
562 return;
563 }
564
565 SkuIdTable = (SKU_ID *) ((UINT8 *) PeiPcdDb + PeiPcdDb->SkuIdTableOffset);
566 for (Index = 0; Index < SkuIdTable[0]; Index++) {
567 if (SkuId == SkuIdTable[Index + 1]) {
568 DEBUG ((DEBUG_INFO, "PcdPei - SkuId is found in SkuId table.\n"));
569 break;
570 }
571 }
572
573 if (Index < SkuIdTable[0]) {
574 //
575 // Get full PCD database from PcdPeim FileHandle
576 //
577 Instance = 0;
578 FileHandle = NULL;
579 while (TRUE) {
580 //
581 // Traverse all firmware volume instances
582 //
583 Status = PeiServicesFfsFindNextVolume (Instance, &VolumeHandle);
584 //
585 // Error should not happen
586 //
587 ASSERT_EFI_ERROR (Status);
588
589 //
590 // Find PcdDb file from the beginning in this firmware volume.
591 //
592 FileHandle = NULL;
593 Status = PeiServicesFfsFindFileByName (&gEfiCallerIdGuid, VolumeHandle, &FileHandle);
594 if (!EFI_ERROR (Status)) {
595 //
596 // Find PcdPeim FileHandle in this volume
597 //
598 break;
599 }
600 //
601 // We cannot find PcdPeim in this firmware volume, then search the next volume.
602 //
603 Instance++;
604 }
605
606 //
607 // Find the delta data between the different Skus
608 //
609 Status = PeiServicesFfsFindSectionData (EFI_SECTION_RAW, FileHandle, &PcdDb);
610 ASSERT_EFI_ERROR (Status);
611 Length = PeiPcdDb->LengthForAllSkus;
612 Index = (PeiPcdDb->Length + 7) & (~7);
613 SkuDelta = NULL;
614 while (Index < Length) {
615 SkuDelta = (PCD_DATABASE_SKU_DELTA *) ((UINT8 *) PcdDb + Index);
616 if (SkuDelta->SkuId == SkuId && SkuDelta->SkuIdCompared == 0) {
617 break;
618 }
619 Index = (Index + SkuDelta->Length + 7) & (~7);
620 }
621
622 //
623 // Patch the delta data into current PCD database
624 //
625 if (Index < Length && SkuDelta != NULL) {
626 SkuDeltaData = (PCD_DATA_DELTA *) (SkuDelta + 1);
627 while ((UINT8 *) SkuDeltaData < (UINT8 *) SkuDelta + SkuDelta->Length) {
628 *((UINT8 *) PeiPcdDb + SkuDeltaData->Offset) = (UINT8) SkuDeltaData->Value;
629 SkuDeltaData ++;
630 }
631 PeiPcdDb->SystemSkuId = (SKU_ID) SkuId;
632 DEBUG ((DEBUG_INFO, "PcdPei - Set current SKU Id to 0x%lx.\n", (SKU_ID) SkuId));
633 return;
634 }
635 }
636
637 //
638 // Invalid input SkuId, the default SKU Id will be still used for the system.
639 //
640 DEBUG ((DEBUG_ERROR, "PcdPei - Invalid input SkuId, the default SKU Id will be still used.\n"));
641
642 return;
643 }
644
645 /**
646 Retrieves an 8-bit value for a given PCD token.
647
648 Retrieves the current byte-sized value for a PCD token number.
649 If the TokenNumber is invalid, the results are unpredictable.
650
651 @param[in] TokenNumber The PCD token number.
652
653 @return The UINT8 value.
654
655 **/
656 UINT8
657 EFIAPI
658 PeiPcdGet8 (
659 IN UINTN TokenNumber
660 )
661 {
662 return *((UINT8 *) GetWorker (TokenNumber, sizeof (UINT8)));
663 }
664
665 /**
666 Retrieves an 16-bit value for a given PCD token.
667
668 Retrieves the current 16-bits value for a PCD token number.
669 If the TokenNumber is invalid, the results are unpredictable.
670
671 @param[in] TokenNumber The PCD token number.
672
673 @return The UINT16 value.
674
675 **/
676 UINT16
677 EFIAPI
678 PeiPcdGet16 (
679 IN UINTN TokenNumber
680 )
681 {
682 return ReadUnaligned16 (GetWorker (TokenNumber, sizeof (UINT16)));
683 }
684
685 /**
686 Retrieves an 32-bit value for a given PCD token.
687
688 Retrieves the current 32-bits value for a PCD token number.
689 If the TokenNumber is invalid, the results are unpredictable.
690
691 @param[in] TokenNumber The PCD token number.
692
693 @return The UINT32 value.
694
695 **/
696 UINT32
697 EFIAPI
698 PeiPcdGet32 (
699 IN UINTN TokenNumber
700 )
701 {
702 return ReadUnaligned32 (GetWorker (TokenNumber, sizeof (UINT32)));
703 }
704
705 /**
706 Retrieves an 64-bit value for a given PCD token.
707
708 Retrieves the current 64-bits value for a PCD token number.
709 If the TokenNumber is invalid, the results are unpredictable.
710
711 @param[in] TokenNumber The PCD token number.
712
713 @return The UINT64 value.
714
715 **/
716 UINT64
717 EFIAPI
718 PeiPcdGet64 (
719 IN UINTN TokenNumber
720 )
721 {
722 return ReadUnaligned64 (GetWorker (TokenNumber, sizeof (UINT64)));
723 }
724
725 /**
726 Retrieves a pointer to a value for a given PCD token.
727
728 Retrieves the current pointer to the buffer for a PCD token number.
729 Do not make any assumptions about the alignment of the pointer that
730 is returned by this function call. If the TokenNumber is invalid,
731 the results are unpredictable.
732
733 @param[in] TokenNumber The PCD token number.
734
735 @return The pointer to the buffer to be retrieved.
736
737 **/
738 VOID *
739 EFIAPI
740 PeiPcdGetPtr (
741 IN UINTN TokenNumber
742 )
743 {
744 return GetWorker (TokenNumber, 0);
745 }
746
747 /**
748 Retrieves a Boolean value for a given PCD token.
749
750 Retrieves the current boolean value for a PCD token number.
751 Do not make any assumptions about the alignment of the pointer that
752 is returned by this function call. If the TokenNumber is invalid,
753 the results are unpredictable.
754
755 @param[in] TokenNumber The PCD token number.
756
757 @return The Boolean value.
758
759 **/
760 BOOLEAN
761 EFIAPI
762 PeiPcdGetBool (
763 IN UINTN TokenNumber
764 )
765 {
766 return *((BOOLEAN *) GetWorker (TokenNumber, sizeof (BOOLEAN)));
767 }
768
769 /**
770 Retrieves the size of the value for a given PCD token.
771
772 Retrieves the current size of a particular PCD token.
773 If the TokenNumber is invalid, the results are unpredictable.
774
775 @param[in] TokenNumber The PCD token number.
776
777 @return The size of the value for the PCD token.
778
779 **/
780 UINTN
781 EFIAPI
782 PeiPcdGetSize (
783 IN UINTN TokenNumber
784 )
785 {
786 PEI_PCD_DATABASE *PeiPcdDb;
787 UINTN Size;
788 UINTN MaxSize;
789 UINT32 LocalTokenCount;
790
791 PeiPcdDb = GetPcdDatabase ();
792 LocalTokenCount = PeiPcdDb->LocalTokenCount;
793 //
794 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
795 // We have to decrement TokenNumber by 1 to make it usable
796 // as the array index.
797 //
798 TokenNumber--;
799
800 // EBC compiler is very choosy. It may report warning about comparison
801 // between UINTN and 0 . So we add 1 in each size of the
802 // comparison.
803 ASSERT (TokenNumber + 1 < (LocalTokenCount + 1));
804
805 Size = (*((UINT32 *)((UINT8 *)PeiPcdDb + PeiPcdDb->LocalTokenNumberTableOffset) + TokenNumber) & PCD_DATUM_TYPE_ALL_SET) >> PCD_DATUM_TYPE_SHIFT;
806
807 if (Size == 0) {
808 //
809 // For pointer type, we need to scan the SIZE_TABLE to get the current size.
810 //
811 return GetPtrTypeSize (TokenNumber, &MaxSize, PeiPcdDb);
812 } else {
813 return Size;
814 }
815
816 }
817
818 /**
819 Retrieves an 8-bit value for a given PCD token.
820
821 Retrieves the 8-bit value of a particular PCD token.
822 If the TokenNumber is invalid or the token space
823 specified by Guid does not exist, the results are
824 unpredictable.
825
826 @param[in] Guid The token space for the token number.
827 @param[in] ExTokenNumber The PCD token number.
828
829 @return The size 8-bit value for the PCD token.
830
831 **/
832 UINT8
833 EFIAPI
834 PeiPcdGet8Ex (
835 IN CONST EFI_GUID *Guid,
836 IN UINTN ExTokenNumber
837 )
838 {
839 return *((UINT8 *) ExGetWorker (Guid, ExTokenNumber, sizeof (UINT8)));
840 }
841
842 /**
843 Retrieves an 16-bit value for a given PCD token.
844
845 Retrieves the 16-bit value of a particular PCD token.
846 If the TokenNumber is invalid or the token space
847 specified by Guid does not exist, the results are
848 unpredictable.
849
850 @param[in] Guid The token space for the token number.
851 @param[in] ExTokenNumber The PCD token number.
852
853 @return The size 16-bit value for the PCD token.
854
855 **/
856 UINT16
857 EFIAPI
858 PeiPcdGet16Ex (
859 IN CONST EFI_GUID *Guid,
860 IN UINTN ExTokenNumber
861 )
862 {
863 return ReadUnaligned16 (ExGetWorker (Guid, ExTokenNumber, sizeof (UINT16)));
864 }
865
866 /**
867 Retrieves an 32-bit value for a given PCD token.
868
869 Retrieves the 32-bit value of a particular PCD token.
870 If the TokenNumber is invalid or the token space
871 specified by Guid does not exist, the results are
872 unpredictable.
873
874 @param[in] Guid The token space for the token number.
875 @param[in] ExTokenNumber The PCD token number.
876
877 @return The size 32-bit value for the PCD token.
878
879 **/
880 UINT32
881 EFIAPI
882 PeiPcdGet32Ex (
883 IN CONST EFI_GUID *Guid,
884 IN UINTN ExTokenNumber
885 )
886 {
887 return ReadUnaligned32 (ExGetWorker (Guid, ExTokenNumber, sizeof (UINT32)));
888 }
889
890 /**
891 Retrieves an 64-bit value for a given PCD token.
892
893 Retrieves the 64-bit value of a particular PCD token.
894 If the TokenNumber is invalid or the token space
895 specified by Guid does not exist, the results are
896 unpredictable.
897
898 @param[in] Guid The token space for the token number.
899 @param[in] ExTokenNumber The PCD token number.
900
901 @return The size 64-bit value for the PCD token.
902
903 **/
904 UINT64
905 EFIAPI
906 PeiPcdGet64Ex (
907 IN CONST EFI_GUID *Guid,
908 IN UINTN ExTokenNumber
909 )
910 {
911 return ReadUnaligned64 (ExGetWorker (Guid, ExTokenNumber, sizeof (UINT64)));
912 }
913
914 /**
915 Retrieves a pointer to a value for a given PCD token.
916
917 Retrieves the current pointer to the buffer for a PCD token number.
918 Do not make any assumptions about the alignment of the pointer that
919 is returned by this function call. If the TokenNumber is invalid,
920 the results are unpredictable.
921
922 @param[in] Guid The token space for the token number.
923 @param[in] ExTokenNumber The PCD token number.
924
925 @return The pointer to the buffer to be retrieved.
926
927 **/
928 VOID *
929 EFIAPI
930 PeiPcdGetPtrEx (
931 IN CONST EFI_GUID *Guid,
932 IN UINTN ExTokenNumber
933 )
934 {
935 return ExGetWorker (Guid, ExTokenNumber, 0);
936 }
937
938 /**
939 Retrieves an Boolean value for a given PCD token.
940
941 Retrieves the Boolean value of a particular PCD token.
942 If the TokenNumber is invalid or the token space
943 specified by Guid does not exist, the results are
944 unpredictable.
945
946 @param[in] Guid The token space for the token number.
947 @param[in] ExTokenNumber The PCD token number.
948
949 @return The size Boolean value for the PCD token.
950
951 **/
952 BOOLEAN
953 EFIAPI
954 PeiPcdGetBoolEx (
955 IN CONST EFI_GUID *Guid,
956 IN UINTN ExTokenNumber
957 )
958 {
959 return *((BOOLEAN *) ExGetWorker (Guid, ExTokenNumber, sizeof (BOOLEAN)));
960 }
961
962 /**
963 Retrieves the size of the value for a given PCD token.
964
965 Retrieves the current size of a particular PCD token.
966 If the TokenNumber is invalid, the results are unpredictable.
967
968 @param[in] Guid The token space for the token number.
969 @param[in] ExTokenNumber The PCD token number.
970
971 @return The size of the value for the PCD token.
972
973 **/
974 UINTN
975 EFIAPI
976 PeiPcdGetSizeEx (
977 IN CONST EFI_GUID *Guid,
978 IN UINTN ExTokenNumber
979 )
980 {
981 return PeiPcdGetSize (GetExPcdTokenNumber (Guid, ExTokenNumber));
982 }
983
984 /**
985 Sets an 8-bit value for a given PCD token.
986
987 When the PCD service sets a value, it will check to ensure that the
988 size of the value being set is compatible with the Token's existing definition.
989 If it is not, an error will be returned.
990
991 @param[in] TokenNumber The PCD token number.
992 @param[in] Value The value to set for the PCD token.
993
994 @retval EFI_SUCCESS Procedure returned successfully.
995 @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
996 being set was incompatible with a call to this function.
997 Use GetSize() to retrieve the size of the target data.
998 @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
999
1000 **/
1001 EFI_STATUS
1002 EFIAPI
1003 PeiPcdSet8 (
1004 IN UINTN TokenNumber,
1005 IN UINT8 Value
1006 )
1007 {
1008 return SetValueWorker (TokenNumber, &Value, sizeof (Value));
1009 }
1010
1011 /**
1012 Sets an 16-bit value for a given PCD token.
1013
1014 When the PCD service sets a value, it will check to ensure that the
1015 size of the value being set is compatible with the Token's existing definition.
1016 If it is not, an error will be returned.
1017
1018 @param[in] TokenNumber The PCD token number.
1019 @param[in] Value The value to set for the PCD token.
1020
1021 @retval EFI_SUCCESS Procedure returned successfully.
1022 @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
1023 being set was incompatible with a call to this function.
1024 Use GetSize() to retrieve the size of the target data.
1025 @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
1026
1027 **/
1028 EFI_STATUS
1029 EFIAPI
1030 PeiPcdSet16 (
1031 IN UINTN TokenNumber,
1032 IN UINT16 Value
1033 )
1034 {
1035 return SetValueWorker (TokenNumber, &Value, sizeof (Value));
1036 }
1037
1038 /**
1039 Sets an 32-bit value for a given PCD token.
1040
1041 When the PCD service sets a value, it will check to ensure that the
1042 size of the value being set is compatible with the Token's existing definition.
1043 If it is not, an error will be returned.
1044
1045 @param[in] TokenNumber The PCD token number.
1046 @param[in] Value The value to set for the PCD token.
1047
1048 @retval EFI_SUCCESS Procedure returned successfully.
1049 @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
1050 being set was incompatible with a call to this function.
1051 Use GetSize() to retrieve the size of the target data.
1052 @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
1053
1054 **/
1055 EFI_STATUS
1056 EFIAPI
1057 PeiPcdSet32 (
1058 IN UINTN TokenNumber,
1059 IN UINT32 Value
1060 )
1061 {
1062 return SetValueWorker (TokenNumber, &Value, sizeof (Value));
1063 }
1064
1065 /**
1066 Sets an 64-bit value for a given PCD token.
1067
1068 When the PCD service sets a value, it will check to ensure that the
1069 size of the value being set is compatible with the Token's existing definition.
1070 If it is not, an error will be returned.
1071
1072 @param[in] TokenNumber The PCD token number.
1073 @param[in] Value The value to set for the PCD token.
1074
1075 @retval EFI_SUCCESS Procedure returned successfully.
1076 @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
1077 being set was incompatible with a call to this function.
1078 Use GetSize() to retrieve the size of the target data.
1079 @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
1080
1081 **/
1082 EFI_STATUS
1083 EFIAPI
1084 PeiPcdSet64 (
1085 IN UINTN TokenNumber,
1086 IN UINT64 Value
1087 )
1088 {
1089 return SetValueWorker (TokenNumber, &Value, sizeof (Value));
1090 }
1091
1092 /**
1093 Sets a value of a specified size for a given PCD token.
1094
1095 When the PCD service sets a value, it will check to ensure that the
1096 size of the value being set is compatible with the Token's existing definition.
1097 If it is not, an error will be returned.
1098
1099 @param[in] TokenNumber The PCD token number.
1100 @param[in, out] SizeOfBuffer A pointer to the length of the value being set for the PCD token.
1101 On input, if the SizeOfValue is greater than the maximum size supported
1102 for this TokenNumber then the output value of SizeOfValue will reflect
1103 the maximum size supported for this TokenNumber.
1104 @param[in] Buffer The buffer to set for the PCD token.
1105
1106 @retval EFI_SUCCESS Procedure returned successfully.
1107 @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
1108 being set was incompatible with a call to this function.
1109 Use GetSize() to retrieve the size of the target data.
1110 @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
1111
1112 **/
1113 EFI_STATUS
1114 EFIAPI
1115 PeiPcdSetPtr (
1116 IN UINTN TokenNumber,
1117 IN OUT UINTN *SizeOfBuffer,
1118 IN VOID *Buffer
1119 )
1120 {
1121 return SetWorker (TokenNumber, Buffer, SizeOfBuffer, TRUE);
1122 }
1123
1124 /**
1125 Sets an Boolean value for a given PCD token.
1126
1127 When the PCD service sets a value, it will check to ensure that the
1128 size of the value being set is compatible with the Token's existing definition.
1129 If it is not, an error will be returned.
1130
1131 @param[in] TokenNumber The PCD token number.
1132 @param[in] Value The value to set for the PCD token.
1133
1134 @retval EFI_SUCCESS Procedure returned successfully.
1135 @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
1136 being set was incompatible with a call to this function.
1137 Use GetSize() to retrieve the size of the target data.
1138 @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
1139
1140 **/
1141 EFI_STATUS
1142 EFIAPI
1143 PeiPcdSetBool (
1144 IN UINTN TokenNumber,
1145 IN BOOLEAN Value
1146 )
1147 {
1148 return SetValueWorker (TokenNumber, &Value, sizeof (Value));
1149 }
1150
1151 /**
1152 Sets an 8-bit value for a given PCD token.
1153
1154 When the PCD service sets a value, it will check to ensure that the
1155 size of the value being set is compatible with the Token's existing definition.
1156 If it is not, an error will be returned.
1157
1158 @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
1159 @param[in] ExTokenNumber The PCD token number.
1160 @param[in] Value The value to set for the PCD token.
1161
1162 @retval EFI_SUCCESS Procedure returned successfully.
1163 @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
1164 being set was incompatible with a call to this function.
1165 Use GetSize() to retrieve the size of the target data.
1166 @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
1167
1168 **/
1169 EFI_STATUS
1170 EFIAPI
1171 PeiPcdSet8Ex (
1172 IN CONST EFI_GUID *Guid,
1173 IN UINTN ExTokenNumber,
1174 IN UINT8 Value
1175 )
1176 {
1177 return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));
1178 }
1179
1180 /**
1181 Sets an 16-bit value for a given PCD token.
1182
1183 When the PCD service sets a value, it will check to ensure that the
1184 size of the value being set is compatible with the Token's existing definition.
1185 If it is not, an error will be returned.
1186
1187 @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
1188 @param[in] ExTokenNumber The PCD token number.
1189 @param[in] Value The value to set for the PCD token.
1190
1191 @retval EFI_SUCCESS Procedure returned successfully.
1192 @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
1193 being set was incompatible with a call to this function.
1194 Use GetSize() to retrieve the size of the target data.
1195 @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
1196
1197 **/
1198 EFI_STATUS
1199 EFIAPI
1200 PeiPcdSet16Ex (
1201 IN CONST EFI_GUID *Guid,
1202 IN UINTN ExTokenNumber,
1203 IN UINT16 Value
1204 )
1205 {
1206 return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));
1207 }
1208
1209 /**
1210 Sets an 32-bit value for a given PCD token.
1211
1212 When the PCD service sets a value, it will check to ensure that the
1213 size of the value being set is compatible with the Token's existing definition.
1214 If it is not, an error will be returned.
1215
1216 @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
1217 @param[in] ExTokenNumber The PCD token number.
1218 @param[in] Value The value to set for the PCD token.
1219
1220 @retval EFI_SUCCESS Procedure returned successfully.
1221 @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
1222 being set was incompatible with a call to this function.
1223 Use GetSize() to retrieve the size of the target data.
1224 @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
1225
1226 **/
1227 EFI_STATUS
1228 EFIAPI
1229 PeiPcdSet32Ex (
1230 IN CONST EFI_GUID *Guid,
1231 IN UINTN ExTokenNumber,
1232 IN UINT32 Value
1233 )
1234 {
1235 return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));
1236 }
1237
1238 /**
1239 Sets an 64-bit value for a given PCD token.
1240
1241 When the PCD service sets a value, it will check to ensure that the
1242 size of the value being set is compatible with the Token's existing definition.
1243 If it is not, an error will be returned.
1244
1245 @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
1246 @param[in] ExTokenNumber The PCD token number.
1247 @param[in] Value The value to set for the PCD token.
1248
1249 @retval EFI_SUCCESS Procedure returned successfully.
1250 @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
1251 being set was incompatible with a call to this function.
1252 Use GetSize() to retrieve the size of the target data.
1253 @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
1254
1255 **/
1256 EFI_STATUS
1257 EFIAPI
1258 PeiPcdSet64Ex (
1259 IN CONST EFI_GUID *Guid,
1260 IN UINTN ExTokenNumber,
1261 IN UINT64 Value
1262 )
1263 {
1264 return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));
1265 }
1266
1267 /**
1268 Sets a value of a specified size for a given PCD token.
1269
1270 When the PCD service sets a value, it will check to ensure that the
1271 size of the value being set is compatible with the Token's existing definition.
1272 If it is not, an error will be returned.
1273
1274 @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
1275 @param[in] ExTokenNumber The PCD token number.
1276 @param[in, out] SizeOfBuffer A pointer to the length of the value being set for the PCD token.
1277 On input, if the SizeOfValue is greater than the maximum size supported
1278 for this TokenNumber then the output value of SizeOfValue will reflect
1279 the maximum size supported for this TokenNumber.
1280 @param[in] Value The buffer to set for the PCD token.
1281
1282 @retval EFI_SUCCESS Procedure returned successfully.
1283 @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
1284 being set was incompatible with a call to this function.
1285 Use GetSize() to retrieve the size of the target data.
1286 @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
1287
1288 **/
1289 EFI_STATUS
1290 EFIAPI
1291 PeiPcdSetPtrEx (
1292 IN CONST EFI_GUID *Guid,
1293 IN UINTN ExTokenNumber,
1294 IN OUT UINTN *SizeOfBuffer,
1295 IN VOID *Value
1296 )
1297 {
1298 return ExSetWorker (ExTokenNumber, Guid, Value, SizeOfBuffer, TRUE);
1299 }
1300
1301 /**
1302 Sets an Boolean value for a given PCD token.
1303
1304 When the PCD service sets a value, it will check to ensure that the
1305 size of the value being set is compatible with the Token's existing definition.
1306 If it is not, an error will be returned.
1307
1308 @param [in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
1309 @param [in] ExTokenNumber The PCD token number.
1310 @param [in] Value The value to set for the PCD token.
1311
1312 @retval EFI_SUCCESS Procedure returned successfully.
1313 @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
1314 being set was incompatible with a call to this function.
1315 Use GetSize() to retrieve the size of the target data.
1316 @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
1317
1318 **/
1319 EFI_STATUS
1320 EFIAPI
1321 PeiPcdSetBoolEx (
1322 IN CONST EFI_GUID *Guid,
1323 IN UINTN ExTokenNumber,
1324 IN BOOLEAN Value
1325 )
1326 {
1327 return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));
1328 }
1329
1330 /**
1331 Specifies a function to be called anytime the value of a designated token is changed.
1332
1333 @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
1334 @param[in] ExTokenNumber The PCD token number.
1335 @param[in] CallBackFunction The function prototype called when the value associated with the CallBackToken is set.
1336
1337 @retval EFI_SUCCESS The PCD service has successfully established a call event
1338 for the CallBackToken requested.
1339 @retval EFI_NOT_FOUND The PCD service could not find the referenced token number.
1340
1341 **/
1342 EFI_STATUS
1343 EFIAPI
1344 PeiRegisterCallBackOnSet (
1345 IN CONST EFI_GUID *Guid, OPTIONAL
1346 IN UINTN ExTokenNumber,
1347 IN PCD_PPI_CALLBACK CallBackFunction
1348 )
1349 {
1350 if (!FeaturePcdGet(PcdPeiFullPcdDatabaseEnable)) {
1351 return EFI_UNSUPPORTED;
1352 }
1353
1354 if (CallBackFunction == NULL) {
1355 return EFI_INVALID_PARAMETER;
1356 }
1357
1358 return PeiRegisterCallBackWorker (ExTokenNumber, Guid, CallBackFunction, TRUE);
1359 }
1360
1361 /**
1362 Cancels a previously set callback function for a particular PCD token number.
1363
1364 @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
1365 @param[in] ExTokenNumber The PCD token number.
1366 @param[in] CallBackFunction The function prototype called when the value associated with the CallBackToken is set.
1367
1368 @retval EFI_SUCCESS The PCD service has successfully established a call event
1369 for the CallBackToken requested.
1370 @retval EFI_NOT_FOUND The PCD service could not find the referenced token number.
1371
1372 **/
1373 EFI_STATUS
1374 EFIAPI
1375 PcdUnRegisterCallBackOnSet (
1376 IN CONST EFI_GUID *Guid, OPTIONAL
1377 IN UINTN ExTokenNumber,
1378 IN PCD_PPI_CALLBACK CallBackFunction
1379 )
1380 {
1381 if (!FeaturePcdGet(PcdPeiFullPcdDatabaseEnable)) {
1382 return EFI_UNSUPPORTED;
1383 }
1384
1385 if (CallBackFunction == NULL) {
1386 return EFI_INVALID_PARAMETER;
1387 }
1388
1389 return PeiRegisterCallBackWorker (ExTokenNumber, Guid, CallBackFunction, FALSE);
1390 }
1391
1392 /**
1393 Retrieves the next valid token number in a given namespace.
1394
1395 This is useful since the PCD infrastructure contains a sparse list of token numbers,
1396 and one cannot a priori know what token numbers are valid in the database.
1397
1398 If TokenNumber is 0 and Guid is not NULL, then the first token from the token space specified by Guid is returned.
1399 If TokenNumber is not 0 and Guid is not NULL, then the next token in the token space specified by Guid is returned.
1400 If TokenNumber is 0 and Guid is NULL, then the first token in the default token space is returned.
1401 If TokenNumber is not 0 and Guid is NULL, then the next token in the default token space is returned.
1402 The token numbers in the default token space may not be related to token numbers in token spaces that are named by Guid.
1403 If the next token number can be retrieved, then it is returned in TokenNumber, and EFI_SUCCESS is returned.
1404 If TokenNumber represents the last token number in the token space specified by Guid, then EFI_NOT_FOUND is returned.
1405 If TokenNumber is not present in the token space specified by Guid, then EFI_NOT_FOUND is returned.
1406
1407
1408 @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
1409 This is an optional parameter that may be NULL. If this parameter is NULL, then a request
1410 is being made to retrieve tokens from the default token space.
1411 @param[in, out] TokenNumber A pointer to the PCD token number to use to find the subsequent token number.
1412
1413 @retval EFI_SUCCESS The PCD service has retrieved the next valid token number.
1414 @retval EFI_NOT_FOUND The PCD service could not find data from the requested token number.
1415
1416 **/
1417 EFI_STATUS
1418 EFIAPI
1419 PeiPcdGetNextToken (
1420 IN CONST EFI_GUID *Guid, OPTIONAL
1421 IN OUT UINTN *TokenNumber
1422 )
1423 {
1424 UINTN GuidTableIdx;
1425 PEI_PCD_DATABASE *PeiPcdDb;
1426 EFI_GUID *MatchGuid;
1427 EFI_GUID *GuidTable;
1428 DYNAMICEX_MAPPING *ExMapTable;
1429 UINTN Index;
1430 BOOLEAN Found;
1431 BOOLEAN PeiExMapTableEmpty;
1432 UINTN PeiNexTokenNumber;
1433
1434 if (!FeaturePcdGet (PcdPeiFullPcdDatabaseEnable)) {
1435 return EFI_UNSUPPORTED;
1436 }
1437
1438 PeiPcdDb = GetPcdDatabase ();
1439 PeiNexTokenNumber = PeiPcdDb->LocalTokenCount - PeiPcdDb->ExTokenCount;
1440 GuidTable = (EFI_GUID *)((UINT8 *)PeiPcdDb + PeiPcdDb->GuidTableOffset);
1441
1442 if (PeiPcdDb->ExTokenCount == 0) {
1443 PeiExMapTableEmpty = TRUE;
1444 } else {
1445 PeiExMapTableEmpty = FALSE;
1446 }
1447 if (Guid == NULL) {
1448 if (*TokenNumber > PeiNexTokenNumber) {
1449 return EFI_NOT_FOUND;
1450 }
1451 (*TokenNumber)++;
1452 if (*TokenNumber > PeiNexTokenNumber) {
1453 *TokenNumber = PCD_INVALID_TOKEN_NUMBER;
1454 return EFI_NOT_FOUND;
1455 }
1456 return EFI_SUCCESS;
1457 } else {
1458 if (PeiExMapTableEmpty) {
1459 return EFI_NOT_FOUND;
1460 }
1461
1462 MatchGuid = ScanGuid (GuidTable, PeiPcdDb->GuidTableCount * sizeof(EFI_GUID), Guid);
1463
1464 if (MatchGuid == NULL) {
1465 return EFI_NOT_FOUND;
1466 }
1467
1468 GuidTableIdx = MatchGuid - GuidTable;
1469
1470 ExMapTable = (DYNAMICEX_MAPPING *)((UINT8 *)PeiPcdDb + PeiPcdDb->ExMapTableOffset);
1471
1472 Found = FALSE;
1473 //
1474 // Locate the GUID in ExMapTable first.
1475 //
1476 for (Index = 0; Index < PeiPcdDb->ExTokenCount; Index++) {
1477 if (ExMapTable[Index].ExGuidIndex == GuidTableIdx) {
1478 Found = TRUE;
1479 break;
1480 }
1481 }
1482
1483 if (Found) {
1484 //
1485 // If given token number is PCD_INVALID_TOKEN_NUMBER, then return the first
1486 // token number in found token space.
1487 //
1488 if (*TokenNumber == PCD_INVALID_TOKEN_NUMBER) {
1489 *TokenNumber = ExMapTable[Index].ExTokenNumber;
1490 return EFI_SUCCESS;
1491 }
1492
1493 for ( ; Index < PeiPcdDb->ExTokenCount; Index++) {
1494 if ((ExMapTable[Index].ExTokenNumber == *TokenNumber) && (ExMapTable[Index].ExGuidIndex == GuidTableIdx)) {
1495 break;
1496 }
1497 }
1498
1499 while (Index < PeiPcdDb->ExTokenCount) {
1500 Index++;
1501 if (Index == PeiPcdDb->ExTokenCount) {
1502 //
1503 // Exceed the length of ExMap Table
1504 //
1505 *TokenNumber = PCD_INVALID_TOKEN_NUMBER;
1506 return EFI_NOT_FOUND;
1507 } else if (ExMapTable[Index].ExGuidIndex == GuidTableIdx) {
1508 //
1509 // Found the next match
1510 //
1511 *TokenNumber = ExMapTable[Index].ExTokenNumber;
1512 return EFI_SUCCESS;
1513 }
1514 }
1515 }
1516 }
1517
1518 return EFI_NOT_FOUND;
1519 }
1520
1521 /**
1522 Retrieves the next valid PCD token namespace for a given namespace.
1523
1524 Gets the next valid token namespace for a given namespace. This is useful to traverse the valid
1525 token namespaces on a platform.
1526
1527 @param[in, out] Guid An indirect pointer to EFI_GUID. On input it designates a known token
1528 namespace from which the search will start. On output, it designates the next valid
1529 token namespace on the platform. If *Guid is NULL, then the GUID of the first token
1530 space of the current platform is returned. If the search cannot locate the next valid
1531 token namespace, an error is returned and the value of *Guid is undefined.
1532
1533 @retval EFI_SUCCESS The PCD service retrieved the value requested.
1534 @retval EFI_NOT_FOUND The PCD service could not find the next valid token namespace.
1535
1536 **/
1537 EFI_STATUS
1538 EFIAPI
1539 PeiPcdGetNextTokenSpace (
1540 IN OUT CONST EFI_GUID **Guid
1541 )
1542 {
1543 UINTN GuidTableIdx;
1544 EFI_GUID *MatchGuid;
1545 PEI_PCD_DATABASE *PeiPcdDb;
1546 DYNAMICEX_MAPPING *ExMapTable;
1547 UINTN Index;
1548 UINTN Index2;
1549 BOOLEAN Found;
1550 BOOLEAN PeiExMapTableEmpty;
1551 EFI_GUID *GuidTable;
1552
1553 if (!FeaturePcdGet (PcdPeiFullPcdDatabaseEnable)) {
1554 return EFI_UNSUPPORTED;
1555 }
1556
1557 ASSERT (Guid != NULL);
1558
1559 PeiPcdDb = GetPcdDatabase ();
1560
1561 if (PeiPcdDb->ExTokenCount == 0) {
1562 PeiExMapTableEmpty = TRUE;
1563 } else {
1564 PeiExMapTableEmpty = FALSE;
1565 }
1566
1567 if (PeiExMapTableEmpty) {
1568 return EFI_NOT_FOUND;
1569 }
1570
1571 ExMapTable = (DYNAMICEX_MAPPING *)((UINT8 *)PeiPcdDb + PeiPcdDb->ExMapTableOffset);
1572 GuidTable = (EFI_GUID *)((UINT8 *)PeiPcdDb + PeiPcdDb->GuidTableOffset);
1573
1574 if (*Guid == NULL) {
1575 //
1576 // return the first Token Space Guid.
1577 //
1578 *Guid = GuidTable + ExMapTable[0].ExGuidIndex;
1579 return EFI_SUCCESS;
1580 }
1581
1582 MatchGuid = ScanGuid (GuidTable, PeiPcdDb->GuidTableCount * sizeof(GuidTable[0]), *Guid);
1583
1584 if (MatchGuid == NULL) {
1585 return EFI_NOT_FOUND;
1586 }
1587
1588 GuidTableIdx = MatchGuid - GuidTable;
1589
1590 Found = FALSE;
1591 for (Index = 0; Index < PeiPcdDb->ExTokenCount; Index++) {
1592 if (ExMapTable[Index].ExGuidIndex == GuidTableIdx) {
1593 Found = TRUE;
1594 break;
1595 }
1596 }
1597
1598 if (Found) {
1599 Index++;
1600 for ( ; Index < PeiPcdDb->ExTokenCount; Index++ ) {
1601 if (ExMapTable[Index].ExGuidIndex != GuidTableIdx) {
1602 Found = FALSE;
1603 for (Index2 = 0 ; Index2 < Index; Index2++) {
1604 if (ExMapTable[Index2].ExGuidIndex == ExMapTable[Index].ExGuidIndex) {
1605 //
1606 // This token namespace should have been found and output at preceding getting.
1607 //
1608 Found = TRUE;
1609 break;
1610 }
1611 }
1612 if (!Found) {
1613 *Guid = (EFI_GUID *)((UINT8 *)PeiPcdDb + PeiPcdDb->GuidTableOffset) + ExMapTable[Index].ExGuidIndex;
1614 return EFI_SUCCESS;
1615 }
1616 }
1617 }
1618 *Guid = NULL;
1619 }
1620
1621 return EFI_NOT_FOUND;
1622
1623 }
1624
1625 /**
1626 Get PCD value's size for POINTER type PCD.
1627
1628 The POINTER type PCD's value will be stored into a buffer in specified size.
1629 The max size of this PCD's value is described in PCD's definition in DEC file.
1630
1631 @param LocalTokenNumberTableIdx Index of PCD token number in PCD token table
1632 @param MaxSize Maximum size of PCD's value
1633 @param Database Pcd database in PEI phase.
1634
1635 @return PCD value's size for POINTER type PCD.
1636
1637 **/
1638 UINTN
1639 GetPtrTypeSize (
1640 IN UINTN LocalTokenNumberTableIdx,
1641 OUT UINTN *MaxSize,
1642 IN PEI_PCD_DATABASE *Database
1643 )
1644 {
1645 INTN SizeTableIdx;
1646 UINTN LocalTokenNumber;
1647 SIZE_INFO *SizeTable;
1648
1649 SizeTableIdx = GetSizeTableIndex (LocalTokenNumberTableIdx, Database);
1650
1651 LocalTokenNumber = *((UINT32 *)((UINT8 *)Database + Database->LocalTokenNumberTableOffset) + LocalTokenNumberTableIdx);
1652
1653 ASSERT ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER);
1654
1655 SizeTable = (SIZE_INFO *)((UINT8 *)Database + Database->SizeTableOffset);
1656
1657 *MaxSize = SizeTable[SizeTableIdx];
1658 //
1659 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type
1660 // PCD entry.
1661 //
1662 if ((LocalTokenNumber & PCD_TYPE_VPD) != 0) {
1663 //
1664 // We have only two entry for VPD enabled PCD entry:
1665 // 1) MAX Size.
1666 // 2) Current Size
1667 // We consider current size is equal to MAX size.
1668 //
1669 return *MaxSize;
1670 } else {
1671 //
1672 // We have only two entry for Non-Sku enabled PCD entry:
1673 // 1) MAX SIZE
1674 // 2) Current Size
1675 //
1676 return SizeTable[SizeTableIdx + 1];
1677 }
1678 }
1679
1680 /**
1681 Set PCD value's size for POINTER type PCD.
1682
1683 The POINTER type PCD's value will be stored into a buffer in specified size.
1684 The max size of this PCD's value is described in PCD's definition in DEC file.
1685
1686 @param LocalTokenNumberTableIdx Index of PCD token number in PCD token table
1687 @param CurrentSize Maximum size of PCD's value
1688 @param Database Pcd database in PEI phase.
1689
1690 @retval TRUE Success to set PCD's value size, which is not exceed maximum size
1691 @retval FALSE Fail to set PCD's value size, which maybe exceed maximum size
1692
1693 **/
1694 BOOLEAN
1695 SetPtrTypeSize (
1696 IN UINTN LocalTokenNumberTableIdx,
1697 IN OUT UINTN *CurrentSize,
1698 IN PEI_PCD_DATABASE *Database
1699 )
1700 {
1701 INTN SizeTableIdx;
1702 UINTN LocalTokenNumber;
1703 SIZE_INFO *SizeTable;
1704 UINTN MaxSize;
1705
1706 SizeTableIdx = GetSizeTableIndex (LocalTokenNumberTableIdx, Database);
1707
1708 LocalTokenNumber = *((UINT32 *)((UINT8 *)Database + Database->LocalTokenNumberTableOffset) + LocalTokenNumberTableIdx);
1709
1710 ASSERT ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER);
1711
1712 SizeTable = (SIZE_INFO *)((UINT8 *)Database + Database->SizeTableOffset);
1713
1714 MaxSize = SizeTable[SizeTableIdx];
1715 //
1716 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type
1717 // PCD entry.
1718 //
1719 if ((LocalTokenNumber & PCD_TYPE_VPD) != 0) {
1720 //
1721 // We shouldn't come here as we don't support SET for VPD
1722 //
1723 ASSERT (FALSE);
1724 return FALSE;
1725 } else {
1726 if ((*CurrentSize > MaxSize) ||
1727 (*CurrentSize == MAX_ADDRESS)) {
1728 *CurrentSize = MaxSize;
1729 return FALSE;
1730 }
1731
1732 //
1733 // We have only two entry for Non-Sku enabled PCD entry:
1734 // 1) MAX SIZE
1735 // 2) Current Size
1736 //
1737 SizeTable[SizeTableIdx + 1] = (SIZE_INFO) *CurrentSize;
1738 return TRUE;
1739 }
1740
1741 }