]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/PCD/Pei/Service.c
MdePkg and MdeModulePkg Pcd: Implement PCD Driver for External PCD Database and SKU...
[mirror_edk2.git] / MdeModulePkg / Universal / PCD / Pei / Service.c
CommitLineData
80408db0 1/** @file\r
5944a83b
LG
2 The driver internal functions are implmented here.\r
3 They build Pei PCD database, and provide access service to PCD database.\r
80408db0 4\r
419db80b 5Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>\r
e5eed7d3 6This program and the accompanying materials\r
80408db0 7are licensed and made available under the terms and conditions of the BSD License\r
8which accompanies this distribution. The full text of the license may be found at\r
9http://opensource.org/licenses/bsd-license.php\r
10\r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
80408db0 14**/\r
80408db0 15\r
16#include "Service.h"\r
17\r
18/**\r
19 The function registers the CallBackOnSet fucntion\r
20 according to TokenNumber and EFI_GUID space.\r
21\r
fc547e08 22 @param ExTokenNumber The token number.\r
80408db0 23 @param Guid The GUID space.\r
24 @param CallBackFunction The Callback function to be registered.\r
25 @param Register To register or unregister the callback function.\r
26\r
27 @retval EFI_SUCCESS If the Callback function is registered.\r
28 @retval EFI_NOT_FOUND If the PCD Entry is not found according to Token Number and GUID space.\r
29 @retval EFI_OUT_OF_RESOURCES If the callback function can't be registered because there is not free\r
30 slot left in the CallbackFnTable.\r
8ec8bed4 31 @retval EFI_INVALID_PARAMETER If the callback function want to be de-registered can not be found.\r
fc547e08 32**/\r
80408db0 33EFI_STATUS\r
34PeiRegisterCallBackWorker (\r
35 IN UINTN ExTokenNumber,\r
36 IN CONST EFI_GUID *Guid, OPTIONAL\r
37 IN PCD_PPI_CALLBACK CallBackFunction,\r
38 IN BOOLEAN Register\r
39)\r
40{\r
41 EFI_HOB_GUID_TYPE *GuidHob;\r
42 PCD_PPI_CALLBACK *CallbackTable;\r
43 PCD_PPI_CALLBACK Compare;\r
44 PCD_PPI_CALLBACK Assign;\r
45 UINT32 LocalTokenNumber;\r
419db80b
BF
46 UINT32 LocalTokenCount;\r
47 UINTN PeiNexTokenNumber;\r
80408db0 48 UINTN TokenNumber;\r
49 UINTN Idx;\r
419db80b
BF
50 PEI_PCD_DATABASE *PeiPcdDb;\r
51\r
52 PeiPcdDb = GetPcdDatabase();\r
53 LocalTokenCount = PeiPcdDb->LocalTokenCount;\r
54 PeiNexTokenNumber = PeiPcdDb->LocalTokenCount - PeiPcdDb->ExTokenCount;\r
80408db0 55\r
56 if (Guid == NULL) {\r
57 TokenNumber = ExTokenNumber;\r
80408db0 58 //\r
59 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.\r
60 // We have to decrement TokenNumber by 1 to make it usable\r
61 // as the array index.\r
62 //\r
63 TokenNumber--;\r
419db80b 64 ASSERT (TokenNumber + 1 < (PeiNexTokenNumber + 1));\r
80408db0 65 } else {\r
66 TokenNumber = GetExPcdTokenNumber (Guid, ExTokenNumber);\r
86714ccd 67 if (TokenNumber == PCD_INVALID_TOKEN_NUMBER) {\r
68 return EFI_NOT_FOUND;\r
69 }\r
80408db0 70 //\r
71 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.\r
72 // We have to decrement TokenNumber by 1 to make it usable\r
73 // as the array index.\r
74 //\r
75 TokenNumber--;\r
76 // EBC compiler is very choosy. It may report warning about comparison\r
77 // between UINTN and 0 . So we add 1 in each size of the \r
78 // comparison.\r
419db80b 79 ASSERT ((TokenNumber + 1) < (LocalTokenCount + 1));\r
80408db0 80 }\r
81\r
82\r
419db80b 83 LocalTokenNumber = *((UINT32 *)((UINT8 *)PeiPcdDb + PeiPcdDb->LocalTokenNumberTableOffset) + TokenNumber);\r
80408db0 84\r
85 //\r
86 // We don't support SET for HII and VPD type PCD entry in PEI phase.\r
87 // So we will assert if any register callback for such PCD entry.\r
88 //\r
89 ASSERT ((LocalTokenNumber & PCD_TYPE_HII) == 0);\r
90 ASSERT ((LocalTokenNumber & PCD_TYPE_VPD) == 0);\r
91\r
96cb78a1 92 GuidHob = GetFirstGuidHob (&gEfiCallerIdGuid);\r
80408db0 93 ASSERT (GuidHob != NULL);\r
94 \r
95 CallbackTable = GET_GUID_HOB_DATA (GuidHob);\r
188e4e84 96 CallbackTable = CallbackTable + (TokenNumber * PcdGet32 (PcdMaxPeiPcdCallBackNumberPerPcdEntry));\r
80408db0 97\r
98 Compare = Register? NULL: CallBackFunction;\r
99 Assign = Register? CallBackFunction: NULL;\r
100\r
101\r
188e4e84 102 for (Idx = 0; Idx < PcdGet32 (PcdMaxPeiPcdCallBackNumberPerPcdEntry); Idx++) {\r
80408db0 103 if (CallbackTable[Idx] == Compare) {\r
104 CallbackTable[Idx] = Assign;\r
105 return EFI_SUCCESS;\r
106 }\r
107 }\r
108\r
8ec8bed4 109 return Register? EFI_OUT_OF_RESOURCES : EFI_INVALID_PARAMETER;\r
80408db0 110\r
111}\r
112\r
419db80b
BF
113\r
114/**\r
115 Find the Pcd database. \r
116\r
117 @param FileHandle Handle of the file the external PCD database binary located.\r
118\r
119 @retval The base address of external PCD database binary.\r
120 @retval NULL Return NULL if not find.\r
121**/\r
122VOID *\r
123LocateExPcdBinary (\r
124 IN EFI_PEI_FILE_HANDLE FileHandle\r
125 )\r
126{\r
127 EFI_STATUS Status;\r
128 VOID *PcdDb;\r
129\r
130 PcdDb = NULL;\r
131\r
132 ASSERT (FileHandle != NULL);\r
133\r
134 Status = PeiServicesFfsFindSectionData (EFI_SECTION_RAW, FileHandle, &PcdDb);\r
135 ASSERT_EFI_ERROR (Status);\r
136\r
137 //\r
138 // Check the first bytes (Header Signature Guid) and build version.\r
139 //\r
140 if (!CompareGuid (PcdDb, &gPcdDataBaseSignatureGuid) ||\r
141 (((PEI_PCD_DATABASE *) PcdDb)->BuildVersion != PCD_SERVICE_PEIM_VERSION)) {\r
142 ASSERT (FALSE);\r
143 }\r
144 return PcdDb;\r
145}\r
146\r
147\r
80408db0 148/**\r
149 The function builds the PCD database.\r
419db80b
BF
150\r
151 @param FileHandle Handle of the file the external PCD database binary located.\r
152\r
fc547e08 153**/\r
80408db0 154VOID\r
155BuildPcdDatabase (\r
419db80b 156 IN EFI_PEI_FILE_HANDLE FileHandle\r
80408db0 157 )\r
158{\r
419db80b
BF
159 PEI_PCD_DATABASE *Database;\r
160 PEI_PCD_DATABASE *PeiPcdDbBinary;\r
161 VOID *CallbackFnTable;\r
162 UINTN SizeOfCallbackFnTable;\r
163\r
164 //\r
165 // Locate the external PCD database binary for one section of current FFS\r
166 //\r
167 PeiPcdDbBinary = LocateExPcdBinary (FileHandle);\r
80408db0 168\r
419db80b
BF
169 ASSERT(PeiPcdDbBinary != NULL);\r
170\r
171 Database = BuildGuidHob (&gPcdDataBaseHobGuid, PeiPcdDbBinary->Length + PeiPcdDbBinary->UninitDataBaseSize);\r
172\r
173 ZeroMem (Database, PeiPcdDbBinary->Length + PeiPcdDbBinary->UninitDataBaseSize);\r
80408db0 174\r
175 //\r
419db80b 176 // PeiPcdDbBinary is smaller than Database\r
80408db0 177 //\r
419db80b 178 CopyMem (Database, PeiPcdDbBinary, PeiPcdDbBinary->Length);\r
80408db0 179\r
419db80b 180 SizeOfCallbackFnTable = Database->LocalTokenCount * sizeof (PCD_PPI_CALLBACK) * PcdGet32 (PcdMaxPeiPcdCallBackNumberPerPcdEntry);\r
80408db0 181\r
96cb78a1 182 CallbackFnTable = BuildGuidHob (&gEfiCallerIdGuid, SizeOfCallbackFnTable);\r
80408db0 183 \r
184 ZeroMem (CallbackFnTable, SizeOfCallbackFnTable);\r
80408db0 185}\r
186\r
80408db0 187/**\r
188 The function is provided by PCD PEIM and PCD DXE driver to\r
189 do the work of reading a HII variable from variable service.\r
190\r
191 @param VariableGuid The Variable GUID.\r
192 @param VariableName The Variable Name.\r
193 @param VariableData The output data.\r
194 @param VariableSize The size of the variable.\r
195\r
196 @retval EFI_SUCCESS Operation successful.\r
197 @retval EFI_NOT_FOUND Variablel not found.\r
fc547e08 198**/\r
80408db0 199EFI_STATUS\r
200GetHiiVariable (\r
201 IN CONST EFI_GUID *VariableGuid,\r
202 IN UINT16 *VariableName,\r
203 OUT VOID **VariableData,\r
204 OUT UINTN *VariableSize\r
205 )\r
206{\r
207 UINTN Size;\r
208 EFI_STATUS Status;\r
209 VOID *Buffer;\r
97a079ed 210 EFI_PEI_READ_ONLY_VARIABLE2_PPI *VariablePpi;\r
80408db0 211\r
97a079ed 212 Status = PeiServicesLocatePpi (&gEfiPeiReadOnlyVariable2PpiGuid, 0, NULL, (VOID **) &VariablePpi);\r
80408db0 213 ASSERT_EFI_ERROR (Status);\r
214\r
215 Size = 0;\r
97a079ed
A
216 Status = VariablePpi->GetVariable (\r
217 VariablePpi,\r
80408db0 218 VariableName,\r
219 (EFI_GUID *) VariableGuid,\r
220 NULL,\r
221 &Size,\r
222 NULL\r
97a079ed 223 );\r
80408db0 224\r
e5618791 225 if (Status == EFI_BUFFER_TOO_SMALL) {\r
80408db0 226 Status = PeiServicesAllocatePool (Size, &Buffer);\r
227 ASSERT_EFI_ERROR (Status);\r
228\r
97a079ed
A
229 Status = VariablePpi->GetVariable (\r
230 VariablePpi,\r
80408db0 231 (UINT16 *) VariableName,\r
232 (EFI_GUID *) VariableGuid,\r
233 NULL,\r
234 &Size,\r
235 Buffer\r
236 );\r
237 ASSERT_EFI_ERROR (Status);\r
238\r
239 *VariableSize = Size;\r
240 *VariableData = Buffer;\r
241\r
242 return EFI_SUCCESS;\r
e5618791 243 }\r
80408db0 244\r
fc547e08 245 return EFI_NOT_FOUND;\r
80408db0 246}\r
247\r
fc547e08 248/**\r
249 Find the local token number according to system SKU ID.\r
250\r
251 @param LocalTokenNumber PCD token number\r
252 @param Size The size of PCD entry.\r
253\r
254 @return Token number according to system SKU ID.\r
255\r
256**/\r
80408db0 257UINT32\r
258GetSkuEnabledTokenNumber (\r
259 UINT32 LocalTokenNumber,\r
260 UINTN Size\r
261 ) \r
262{\r
263 PEI_PCD_DATABASE *PeiPcdDb;\r
264 SKU_HEAD *SkuHead;\r
265 SKU_ID *SkuIdTable;\r
fc547e08 266 INTN Index;\r
80408db0 267 UINT8 *Value;\r
419db80b 268 BOOLEAN FoundSku;\r
80408db0 269\r
270 PeiPcdDb = GetPcdDatabase ();\r
271\r
272 ASSERT ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0);\r
273\r
274 SkuHead = (SKU_HEAD *) ((UINT8 *)PeiPcdDb + (LocalTokenNumber & PCD_DATABASE_OFFSET_MASK));\r
275 Value = (UINT8 *) ((UINT8 *)PeiPcdDb + (SkuHead->SkuDataStartOffset));\r
276 SkuIdTable = (SKU_ID *) ((UINT8 *)PeiPcdDb + (SkuHead->SkuIdTableOffset));\r
419db80b
BF
277\r
278 //\r
279 // Find the current system's SKU ID entry in SKU ID table.\r
280 //\r
281 FoundSku = FALSE;\r
fc547e08 282 for (Index = 0; Index < SkuIdTable[0]; Index++) {\r
419db80b
BF
283 if (PeiPcdDb->SystemSkuId == SkuIdTable[Index + 1]) {\r
284 FoundSku = TRUE;\r
80408db0 285 break;\r
286 }\r
287 }\r
288\r
419db80b
BF
289 //\r
290 // Find the default SKU ID entry in SKU ID table.\r
291 //\r
292 if(!FoundSku) {\r
293 for (Index = 0; Index < SkuIdTable[0]; Index++) {\r
294 if (0 == SkuIdTable[Index + 1]) {\r
295 break;\r
296 }\r
297 }\r
298 }\r
299 ASSERT (Index < SkuIdTable[0]);\r
300\r
80408db0 301 switch (LocalTokenNumber & PCD_TYPE_ALL_SET) {\r
302 case PCD_TYPE_VPD:\r
fc547e08 303 Value = (UINT8 *) &(((VPD_HEAD *) Value)[Index]);\r
80408db0 304 return (UINT32) ((Value - (UINT8 *) PeiPcdDb) | PCD_TYPE_VPD);\r
305\r
306 case PCD_TYPE_HII:\r
fc547e08 307 Value = (UINT8 *) &(((VARIABLE_HEAD *) Value)[Index]);\r
80408db0 308 return (UINT32) ((Value - (UINT8 *) PeiPcdDb) | PCD_TYPE_HII);\r
419db80b
BF
309\r
310 case PCD_TYPE_HII|PCD_TYPE_STRING:\r
311 Value = (UINT8 *) &(((VARIABLE_HEAD *) Value)[Index]);\r
312 return (UINT32) ((Value - (UINT8 *) PeiPcdDb) | PCD_TYPE_HII | PCD_TYPE_STRING);\r
313\r
80408db0 314 case PCD_TYPE_STRING:\r
fc547e08 315 Value = (UINT8 *) &(((STRING_HEAD *) Value)[Index]);\r
80408db0 316 return (UINT32) ((Value - (UINT8 *) PeiPcdDb) | PCD_TYPE_STRING);\r
317\r
318 case PCD_TYPE_DATA:\r
fc547e08 319 Value += Size * Index;\r
419db80b 320 return (UINT32) ((Value - (UINT8 *) PeiPcdDb) | PCD_TYPE_DATA);\r
80408db0 321\r
322 default:\r
323 ASSERT (FALSE);\r
324 }\r
325\r
326 ASSERT (FALSE);\r
327\r
328 return 0;\r
80408db0 329}\r
330\r
fc547e08 331/**\r
332 Invoke the callback function when dynamic PCD entry was set, if this PCD entry \r
333 has registered callback function.\r
80408db0 334\r
fc547e08 335 @param ExTokenNumber DynamicEx PCD's token number, if this PCD entry is dyanmicEx\r
336 type PCD.\r
337 @param Guid DynamicEx PCD's guid, if this PCD entry is dynamicEx type\r
338 PCD.\r
339 @param TokenNumber PCD token number generated by build tools.\r
340 @param Data Value want to be set for this PCD entry\r
341 @param Size The size of value\r
80408db0 342\r
fc547e08 343**/\r
80408db0 344VOID\r
345InvokeCallbackOnSet (\r
346 UINTN ExTokenNumber,\r
347 CONST EFI_GUID *Guid, OPTIONAL\r
348 UINTN TokenNumber,\r
349 VOID *Data,\r
350 UINTN Size\r
351 )\r
352{\r
353 EFI_HOB_GUID_TYPE *GuidHob;\r
354 PCD_PPI_CALLBACK *CallbackTable;\r
355 UINTN Idx;\r
419db80b
BF
356 PEI_PCD_DATABASE *PeiPcdDb;\r
357 UINT32 LocalTokenCount;\r
80408db0 358\r
359 //\r
360 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.\r
361 // We have to decrement TokenNumber by 1 to make it usable\r
362 // as the array index.\r
363 //\r
364 TokenNumber--;\r
419db80b
BF
365\r
366 PeiPcdDb = GetPcdDatabase ();\r
367 LocalTokenCount = PeiPcdDb->LocalTokenCount;\r
368\r
80408db0 369 if (Guid == NULL) {\r
370 // EBC compiler is very choosy. It may report warning about comparison\r
371 // between UINTN and 0 . So we add 1 in each size of the \r
372 // comparison.\r
419db80b 373 ASSERT (TokenNumber + 1 < (LocalTokenCount + 1));\r
80408db0 374 }\r
375\r
96cb78a1 376 GuidHob = GetFirstGuidHob (&gEfiCallerIdGuid);\r
80408db0 377 ASSERT (GuidHob != NULL);\r
378 \r
379 CallbackTable = GET_GUID_HOB_DATA (GuidHob);\r
380\r
188e4e84 381 CallbackTable += (TokenNumber * PcdGet32 (PcdMaxPeiPcdCallBackNumberPerPcdEntry));\r
80408db0 382\r
188e4e84 383 for (Idx = 0; Idx < PcdGet32 (PcdMaxPeiPcdCallBackNumberPerPcdEntry); Idx++) {\r
80408db0 384 if (CallbackTable[Idx] != NULL) {\r
385 CallbackTable[Idx] (Guid,\r
736c5dd5 386 (Guid == NULL) ? (TokenNumber + 1) : ExTokenNumber,\r
80408db0 387 Data,\r
388 Size\r
389 );\r
390 }\r
391 }\r
80408db0 392}\r
393\r
fc547e08 394/**\r
395 Wrapper function for setting non-pointer type value for a PCD entry.\r
396\r
397 @param TokenNumber Pcd token number autogenerated by build tools.\r
398 @param Data Value want to be set for PCD entry\r
399 @param Size Size of value.\r
80408db0 400\r
fc547e08 401 @return status of SetWorker.\r
80408db0 402\r
fc547e08 403**/\r
80408db0 404EFI_STATUS\r
405SetValueWorker (\r
406 IN UINTN TokenNumber,\r
407 IN VOID *Data,\r
408 IN UINTN Size\r
409 )\r
410{\r
411 return SetWorker (TokenNumber, Data, &Size, FALSE);\r
412}\r
413\r
fc547e08 414/**\r
415 Set value for an PCD entry\r
416\r
417 @param TokenNumber Pcd token number autogenerated by build tools.\r
418 @param Data Value want to be set for PCD entry\r
419 @param Size Size of value.\r
420 @param PtrType If TRUE, the type of PCD entry's value is Pointer.\r
421 If False, the type of PCD entry's value is not Pointer.\r
422\r
423 @retval EFI_INVALID_PARAMETER If this PCD type is VPD, VPD PCD can not be set.\r
424 @retval EFI_INVALID_PARAMETER If Size can not be set to size table.\r
149fb6d6 425 @retval EFI_INVALID_PARAMETER If Size of non-Ptr type PCD does not match the size information in PCD database.\r
fc547e08 426 @retval EFI_NOT_FOUND If value type of PCD entry is intergrate, but not in\r
427 range of UINT8, UINT16, UINT32, UINT64\r
428 @retval EFI_NOT_FOUND Can not find the PCD type according to token number. \r
429**/\r
80408db0 430EFI_STATUS\r
431SetWorker (\r
432 IN UINTN TokenNumber,\r
fc547e08 433 IN VOID *Data,\r
80408db0 434 IN OUT UINTN *Size,\r
435 IN BOOLEAN PtrType\r
436 )\r
437{\r
438 UINT32 LocalTokenNumber;\r
419db80b 439 UINTN PeiNexTokenNumber;\r
80408db0 440 PEI_PCD_DATABASE *PeiPcdDb;\r
6cfc7292 441 STRING_HEAD StringTableIdx;\r
80408db0 442 UINTN Offset;\r
443 VOID *InternalData;\r
444 UINTN MaxSize;\r
419db80b 445 UINT32 LocalTokenCount;\r
80408db0 446\r
f806dd27 447 if (!FeaturePcdGet(PcdPeiFullPcdDatabaseEnable)) {\r
80408db0 448 return EFI_UNSUPPORTED;\r
449 }\r
450 \r
451 //\r
452 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.\r
453 // We have to decrement TokenNumber by 1 to make it usable\r
454 // as the array index.\r
455 //\r
456 TokenNumber--;\r
419db80b
BF
457 PeiPcdDb = GetPcdDatabase ();\r
458 LocalTokenCount = PeiPcdDb->LocalTokenCount;\r
80408db0 459\r
460 // EBC compiler is very choosy. It may report warning about comparison\r
461 // between UINTN and 0 . So we add 1 in each size of the \r
462 // comparison.\r
419db80b 463 ASSERT (TokenNumber + 1 < (LocalTokenCount + 1));\r
80408db0 464\r
419db80b 465 LocalTokenNumber = *((UINT32 *)((UINT8 *)PeiPcdDb + PeiPcdDb->LocalTokenNumberTableOffset) + TokenNumber);\r
80408db0 466\r
8ec8bed4 467 if (PtrType) {\r
64894410
LG
468 //\r
469 // Get MaxSize first, then check new size with max buffer size.\r
470 //\r
471 GetPtrTypeSize (TokenNumber, &MaxSize, PeiPcdDb);\r
472 if (*Size > MaxSize) {\r
cb40609c 473 *Size = MaxSize;\r
8ec8bed4 474 return EFI_INVALID_PARAMETER;\r
475 }\r
476 } else {\r
477 if (*Size != PeiPcdGetSize (TokenNumber + 1)) {\r
478 return EFI_INVALID_PARAMETER;\r
479 }\r
80408db0 480 }\r
481\r
482 //\r
483 // We only invoke the callback function for Dynamic Type PCD Entry.\r
484 // For Dynamic EX PCD entry, we have invoked the callback function for Dynamic EX\r
485 // type PCD entry in ExSetWorker.\r
486 //\r
419db80b
BF
487 PeiNexTokenNumber = PeiPcdDb->LocalTokenCount - PeiPcdDb->ExTokenCount;\r
488 if (TokenNumber + 1 < PeiNexTokenNumber + 1) {\r
80408db0 489 InvokeCallbackOnSet (0, NULL, TokenNumber + 1, Data, *Size);\r
490 }\r
491\r
492 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == PCD_TYPE_SKU_ENABLED) {\r
493 if (PtrType) {\r
64894410 494 GetPtrTypeSize (TokenNumber, &MaxSize, PeiPcdDb);\r
80408db0 495 } else {\r
496 MaxSize = *Size;\r
497 }\r
498 LocalTokenNumber = GetSkuEnabledTokenNumber (LocalTokenNumber & ~PCD_TYPE_SKU_ENABLED, MaxSize);\r
499 }\r
500\r
501 Offset = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK;\r
502 InternalData = (VOID *) ((UINT8 *) PeiPcdDb + Offset);\r
503 \r
504 switch (LocalTokenNumber & PCD_TYPE_ALL_SET) {\r
505 case PCD_TYPE_VPD:\r
506 case PCD_TYPE_HII:\r
6ac15f7c 507 case PCD_TYPE_HII|PCD_TYPE_STRING:\r
80408db0 508 {\r
509 ASSERT (FALSE);\r
510 return EFI_INVALID_PARAMETER;\r
511 }\r
512\r
513 case PCD_TYPE_STRING:\r
514 if (SetPtrTypeSize (TokenNumber, Size, PeiPcdDb)) {\r
6cfc7292 515 StringTableIdx = *((STRING_HEAD *)InternalData);\r
419db80b 516 CopyMem ((UINT8 *)PeiPcdDb + PeiPcdDb->StringTableOffset + StringTableIdx, Data, *Size);\r
80408db0 517 return EFI_SUCCESS;\r
518 } else {\r
519 return EFI_INVALID_PARAMETER;\r
520 }\r
521\r
522 case PCD_TYPE_DATA:\r
523 {\r
524 if (PtrType) {\r
525 if (SetPtrTypeSize (TokenNumber, Size, PeiPcdDb)) {\r
526 CopyMem (InternalData, Data, *Size);\r
527 return EFI_SUCCESS;\r
528 } else {\r
529 return EFI_INVALID_PARAMETER;\r
530 }\r
531 }\r
532\r
533 switch (*Size) {\r
534 case sizeof(UINT8):\r
535 *((UINT8 *) InternalData) = *((UINT8 *) Data);\r
536 return EFI_SUCCESS;\r
537\r
538 case sizeof(UINT16):\r
539 *((UINT16 *) InternalData) = *((UINT16 *) Data);\r
540 return EFI_SUCCESS;\r
541\r
542 case sizeof(UINT32):\r
543 *((UINT32 *) InternalData) = *((UINT32 *) Data);\r
544 return EFI_SUCCESS;\r
545\r
546 case sizeof(UINT64):\r
547 *((UINT64 *) InternalData) = *((UINT64 *) Data);\r
548 return EFI_SUCCESS;\r
549\r
550 default:\r
551 ASSERT (FALSE);\r
552 return EFI_NOT_FOUND;\r
553 }\r
554 }\r
555 \r
556 }\r
557\r
558 ASSERT (FALSE);\r
559 return EFI_NOT_FOUND;\r
560\r
561}\r
562\r
fc547e08 563/**\r
564 Wrapper function for set PCD value for non-Pointer type dynamic-ex PCD.\r
80408db0 565\r
fc547e08 566 @param ExTokenNumber Token number for dynamic-ex PCD.\r
567 @param Guid Token space guid for dynamic-ex PCD.\r
568 @param Data Value want to be set.\r
569 @param SetSize The size of value.\r
80408db0 570\r
fc547e08 571 @return status of ExSetWorker().\r
572\r
573**/\r
80408db0 574EFI_STATUS\r
575ExSetValueWorker (\r
576 IN UINTN ExTokenNumber,\r
577 IN CONST EFI_GUID *Guid,\r
578 IN VOID *Data,\r
579 IN UINTN Size\r
580 )\r
581{\r
582 return ExSetWorker (ExTokenNumber, Guid, Data, &Size, FALSE);\r
583}\r
584\r
fc547e08 585/**\r
419db80b 586 Set value for a dynamic-ex PCD entry.\r
fc547e08 587 \r
588 This routine find the local token number according to dynamic-ex PCD's token \r
589 space guid and token number firstly, and invoke callback function if this PCD\r
590 entry registered callback function. Finally, invoken general SetWorker to set\r
591 PCD value.\r
592 \r
593 @param ExTokenNumber Dynamic-ex PCD token number.\r
594 @param Guid Token space guid for dynamic-ex PCD.\r
595 @param Data PCD value want to be set\r
596 @param SetSize Size of value.\r
597 @param PtrType If TRUE, this PCD entry is pointer type.\r
598 If FALSE, this PCD entry is not pointer type.\r
80408db0 599\r
fc547e08 600 @return status of SetWorker().\r
80408db0 601\r
fc547e08 602**/\r
80408db0 603EFI_STATUS\r
604ExSetWorker (\r
605 IN UINTN ExTokenNumber,\r
606 IN CONST EFI_GUID *Guid,\r
607 IN VOID *Data,\r
608 IN OUT UINTN *Size,\r
609 IN BOOLEAN PtrType\r
610 )\r
611{\r
612 UINTN TokenNumber;\r
613\r
f806dd27 614 if (!FeaturePcdGet(PcdPeiFullPcdDatabaseEnable)) {\r
80408db0 615 return EFI_UNSUPPORTED;\r
616 }\r
617\r
618 TokenNumber = GetExPcdTokenNumber (Guid, ExTokenNumber);\r
86714ccd 619 if (TokenNumber == PCD_INVALID_TOKEN_NUMBER) {\r
620 return EFI_NOT_FOUND;\r
621 }\r
622 \r
80408db0 623 InvokeCallbackOnSet (ExTokenNumber, Guid, TokenNumber, Data, *Size);\r
624\r
625 return SetWorker (TokenNumber, Data, Size, PtrType);\r
626\r
627}\r
628\r
fc547e08 629/**\r
630 Wrapper function for get PCD value for dynamic-ex PCD.\r
80408db0 631\r
fc547e08 632 @param Guid Token space guid for dynamic-ex PCD.\r
633 @param ExTokenNumber Token number for dyanmic-ex PCD.\r
634 @param GetSize The size of dynamic-ex PCD value.\r
80408db0 635\r
fc547e08 636 @return PCD entry in PCD database.\r
80408db0 637\r
fc547e08 638**/\r
80408db0 639VOID *\r
640ExGetWorker (\r
641 IN CONST EFI_GUID *Guid,\r
642 IN UINTN ExTokenNumber,\r
643 IN UINTN GetSize\r
644 )\r
f806dd27 645{ \r
80408db0 646 return GetWorker (GetExPcdTokenNumber (Guid, ExTokenNumber), GetSize);\r
647}\r
648\r
fc547e08 649/**\r
650 Get the PCD entry pointer in PCD database.\r
651 \r
652 This routine will visit PCD database to find the PCD entry according to given\r
653 token number. The given token number is autogened by build tools and it will be \r
654 translated to local token number. Local token number contains PCD's type and \r
655 offset of PCD entry in PCD database.\r
80408db0 656\r
fc547e08 657 @param TokenNumber Token's number, it is autogened by build tools\r
658 @param GetSize The size of token's value\r
80408db0 659\r
fc547e08 660 @return PCD entry pointer in PCD database\r
80408db0 661\r
fc547e08 662**/\r
80408db0 663VOID *\r
664GetWorker (\r
fc547e08 665 IN UINTN TokenNumber,\r
666 IN UINTN GetSize\r
80408db0 667 )\r
668{\r
669 UINT32 Offset;\r
670 EFI_GUID *Guid;\r
671 UINT16 *Name;\r
672 VARIABLE_HEAD *VariableHead;\r
673 EFI_STATUS Status;\r
674 UINTN DataSize;\r
675 VOID *Data;\r
d0965169 676 UINT8 *StringTable;\r
6cfc7292 677 STRING_HEAD StringTableIdx;\r
80408db0 678 PEI_PCD_DATABASE *PeiPcdDb;\r
679 UINT32 LocalTokenNumber;\r
680 UINTN MaxSize;\r
419db80b 681 UINT32 LocalTokenCount;\r
80408db0 682\r
683 //\r
684 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.\r
685 // We have to decrement TokenNumber by 1 to make it usable\r
686 // as the array index.\r
687 //\r
688 TokenNumber--;\r
689\r
419db80b
BF
690 PeiPcdDb = GetPcdDatabase ();\r
691 LocalTokenCount = PeiPcdDb->LocalTokenCount;\r
692\r
80408db0 693 // EBC compiler is very choosy. It may report warning about comparison\r
694 // between UINTN and 0 . So we add 1 in each size of the \r
695 // comparison.\r
419db80b 696 ASSERT (TokenNumber + 1 < (LocalTokenCount + 1));\r
80408db0 697\r
698 ASSERT ((GetSize == PeiPcdGetSize(TokenNumber + 1)) || (GetSize == 0));\r
699\r
419db80b 700 LocalTokenNumber = *((UINT32 *)((UINT8 *)PeiPcdDb + PeiPcdDb->LocalTokenNumberTableOffset) + TokenNumber);\r
80408db0 701\r
702 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == PCD_TYPE_SKU_ENABLED) {\r
703 if (GetSize == 0) {\r
573e0a48 704 GetPtrTypeSize (TokenNumber, &MaxSize, PeiPcdDb);\r
80408db0 705 } else {\r
706 MaxSize = GetSize;\r
707 }\r
708 LocalTokenNumber = GetSkuEnabledTokenNumber (LocalTokenNumber & ~PCD_TYPE_SKU_ENABLED, MaxSize);\r
709 }\r
710\r
711 Offset = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK;\r
419db80b
BF
712 StringTable = (UINT8 *)PeiPcdDb + PeiPcdDb->StringTableOffset;\r
713\r
80408db0 714 switch (LocalTokenNumber & PCD_TYPE_ALL_SET) {\r
715 case PCD_TYPE_VPD:\r
716 {\r
717 VPD_HEAD *VpdHead;\r
718 VpdHead = (VPD_HEAD *) ((UINT8 *)PeiPcdDb + Offset);\r
188e4e84 719 return (VOID *) (UINTN) (PcdGet32 (PcdVpdBaseAddress) + VpdHead->Offset);\r
80408db0 720 }\r
721 \r
6ac15f7c 722 case PCD_TYPE_HII|PCD_TYPE_STRING:\r
80408db0 723 case PCD_TYPE_HII:\r
724 {\r
725 VariableHead = (VARIABLE_HEAD *) ((UINT8 *)PeiPcdDb + Offset);\r
726 \r
419db80b 727 Guid = (EFI_GUID *) ((UINT8 *)PeiPcdDb + PeiPcdDb->GuidTableOffset) + VariableHead->GuidTableIndex;\r
d0965169 728 Name = (UINT16*)&StringTable[VariableHead->StringIndex];\r
80408db0 729\r
730 Status = GetHiiVariable (Guid, Name, &Data, &DataSize);\r
731\r
732 if (Status == EFI_SUCCESS) {\r
733 return (VOID *) ((UINT8 *) Data + VariableHead->Offset);\r
734 } else {\r
735 //\r
736 // Return the default value specified by Platform Integrator \r
737 //\r
6ac15f7c 738 if ((LocalTokenNumber & PCD_TYPE_ALL_SET) == (PCD_TYPE_HII|PCD_TYPE_STRING)) {\r
6cfc7292 739 return (VOID*)&StringTable[*(STRING_HEAD*)((UINT8*)PeiPcdDb + VariableHead->DefaultValueOffset)];\r
6ac15f7c 740 } else {\r
741 return (VOID *) ((UINT8 *) PeiPcdDb + VariableHead->DefaultValueOffset);\r
742 }\r
80408db0 743 }\r
744 }\r
745\r
746 case PCD_TYPE_DATA:\r
747 return (VOID *) ((UINT8 *)PeiPcdDb + Offset);\r
748\r
749 case PCD_TYPE_STRING:\r
6cfc7292 750 StringTableIdx = * (STRING_HEAD*) ((UINT8 *) PeiPcdDb + Offset);\r
80408db0 751 return (VOID *) (&StringTable[StringTableIdx]);\r
752\r
753 default:\r
754 ASSERT (FALSE);\r
755 break;\r
756 \r
757 }\r
758\r
759 ASSERT (FALSE);\r
760 \r
761 return NULL;\r
762 \r
763}\r
764\r
fc547e08 765/**\r
419db80b 766 Get Token Number according to dynamic-ex PCD's {token space guid:token number}\r
fc547e08 767\r
768 A dynamic-ex type PCD, developer must provide pair of token space guid: token number\r
769 in DEC file. PCD database maintain a mapping table that translate pair of {token\r
419db80b 770 space guid: token number} to Token Number.\r
fc547e08 771 \r
772 @param Guid Token space guid for dynamic-ex PCD entry.\r
419db80b 773 @param ExTokenNumber Dynamic-ex PCD token number.\r
80408db0 774\r
419db80b 775 @return Token Number for dynamic-ex PCD.\r
80408db0 776\r
fc547e08 777**/\r
80408db0 778UINTN \r
779GetExPcdTokenNumber (\r
780 IN CONST EFI_GUID *Guid,\r
781 IN UINTN ExTokenNumber\r
782 )\r
783{\r
fc547e08 784 UINT32 Index;\r
80408db0 785 DYNAMICEX_MAPPING *ExMap;\r
786 EFI_GUID *GuidTable;\r
787 EFI_GUID *MatchGuid;\r
788 UINTN MatchGuidIdx;\r
789 PEI_PCD_DATABASE *PeiPcdDb;\r
790\r
791 PeiPcdDb = GetPcdDatabase();\r
80408db0 792\r
419db80b
BF
793 ExMap = (DYNAMICEX_MAPPING *)((UINT8 *)PeiPcdDb + PeiPcdDb->ExMapTableOffset);\r
794 GuidTable = (EFI_GUID *)((UINT8 *)PeiPcdDb + PeiPcdDb->GuidTableOffset);\r
795\r
796 MatchGuid = ScanGuid (GuidTable, PeiPcdDb->GuidTableCount * sizeof(EFI_GUID), Guid);\r
80408db0 797 //\r
798 // We need to ASSERT here. If GUID can't be found in GuidTable, this is a\r
799 // error in the BUILD system.\r
800 //\r
801 ASSERT (MatchGuid != NULL);\r
802 \r
803 MatchGuidIdx = MatchGuid - GuidTable;\r
804 \r
419db80b 805 for (Index = 0; Index < PeiPcdDb->ExTokenCount; Index++) {\r
fc547e08 806 if ((ExTokenNumber == ExMap[Index].ExTokenNumber) && \r
807 (MatchGuidIdx == ExMap[Index].ExGuidIndex)) {\r
419db80b 808 return ExMap[Index].TokenNumber;\r
80408db0 809 }\r
810 }\r
811 \r
86714ccd 812 return PCD_INVALID_TOKEN_NUMBER;\r
80408db0 813}\r
814\r
fc547e08 815/**\r
816 Get PCD database from GUID HOB in PEI phase.\r
80408db0 817\r
fc547e08 818 @return Pointer to PCD database.\r
80408db0 819\r
fc547e08 820**/\r
80408db0 821PEI_PCD_DATABASE *\r
822GetPcdDatabase (\r
823 VOID\r
824 )\r
825{\r
826 EFI_HOB_GUID_TYPE *GuidHob;\r
827\r
828 GuidHob = GetFirstGuidHob (&gPcdDataBaseHobGuid);\r
829 ASSERT (GuidHob != NULL);\r
830 \r
831 return (PEI_PCD_DATABASE *) GET_GUID_HOB_DATA (GuidHob);\r
832}\r
833\r
fc547e08 834/**\r
419db80b 835 Get SKU ID table from PCD database.\r
fc547e08 836\r
837 @param LocalTokenNumberTableIdx Index of local token number in token number table.\r
838 @param Database PCD database.\r
80408db0 839\r
fc547e08 840 @return Pointer to SKU ID array table\r
80408db0 841\r
fc547e08 842**/\r
80408db0 843SKU_ID *\r
844GetSkuIdArray (\r
845 IN UINTN LocalTokenNumberTableIdx,\r
846 IN PEI_PCD_DATABASE *Database\r
847 )\r
848{\r
849 SKU_HEAD *SkuHead;\r
850 UINTN LocalTokenNumber;\r
851\r
419db80b 852 LocalTokenNumber = *((UINT32 *)((UINT8 *)Database + Database->LocalTokenNumberTableOffset) + LocalTokenNumberTableIdx);\r
80408db0 853\r
854 ASSERT ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) != 0);\r
855\r
856 SkuHead = (SKU_HEAD *) ((UINT8 *)Database + (LocalTokenNumber & PCD_DATABASE_OFFSET_MASK));\r
857\r
858 return (SKU_ID *) ((UINT8 *)Database + SkuHead->SkuIdTableOffset);\r
859 \r
860}\r
861\r
fc547e08 862/**\r
863 Get index of PCD entry in size table.\r
864\r
865 @param LocalTokenNumberTableIdx Index of this PCD in local token number table.\r
866 @param Database Pointer to PCD database in PEI phase.\r
80408db0 867\r
fc547e08 868 @return index of PCD entry in size table.\r
80408db0 869\r
fc547e08 870**/\r
80408db0 871UINTN\r
872GetSizeTableIndex (\r
873 IN UINTN LocalTokenNumberTableIdx,\r
874 IN PEI_PCD_DATABASE *Database\r
875 )\r
876{\r
fc547e08 877 UINTN Index;\r
419db80b 878 UINTN SizeTableIdx;\r
80408db0 879 UINTN LocalTokenNumber;\r
880 SKU_ID *SkuIdTable;\r
881 \r
882 SizeTableIdx = 0;\r
883\r
419db80b
BF
884 for (Index = 0; Index < LocalTokenNumberTableIdx; Index++) {\r
885 LocalTokenNumber = *((UINT32 *)((UINT8 *)Database + Database->LocalTokenNumberTableOffset) + Index);\r
80408db0 886\r
887 if ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER) {\r
888 //\r
889 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type \r
890 // PCD entry.\r
891 //\r
fc547e08 892 if ((LocalTokenNumber & PCD_TYPE_VPD) != 0) {\r
80408db0 893 //\r
419db80b 894 // We have only two entry for VPD enabled PCD entry:\r
80408db0 895 // 1) MAX Size.\r
419db80b
BF
896 // 2) Current Size\r
897 // Current size is equal to MAX size.\r
80408db0 898 //\r
419db80b 899 SizeTableIdx += 2;\r
80408db0 900 } else {\r
901 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0) {\r
902 //\r
903 // We have only two entry for Non-Sku enabled PCD entry:\r
904 // 1) MAX SIZE\r
905 // 2) Current Size\r
906 //\r
907 SizeTableIdx += 2;\r
908 } else {\r
909 //\r
910 // We have these entry for SKU enabled PCD entry\r
911 // 1) MAX SIZE\r
912 // 2) Current Size for each SKU_ID (It is equal to MaxSku).\r
913 //\r
fc547e08 914 SkuIdTable = GetSkuIdArray (Index, Database);\r
80408db0 915 SizeTableIdx += (UINTN)*SkuIdTable + 1;\r
916 }\r
917 }\r
918 }\r
919\r
920 }\r
921\r
922 return SizeTableIdx;\r
923}\r