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