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