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