]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/PCD/Pei/Service.c
BaseTools: Follow PI1.4a to fix artificial limitation of PCD SkuId range
[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
85d0b97d 5Copyright (c) 2006 - 2015, 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
96d6d004
SZ
18/**\r
19 Get Local Token Number by Token Number.\r
20\r
21 @param[in] Database PCD database.\r
22 @param[in] TokenNumber The PCD token number.\r
23\r
24 @return Local Token Number.\r
25**/\r
26UINT32\r
27GetLocalTokenNumber (\r
28 IN PEI_PCD_DATABASE *Database,\r
29 IN UINTN TokenNumber\r
30 )\r
31{\r
32 UINT32 LocalTokenNumber;\r
33 UINTN Size;\r
34 UINTN MaxSize;\r
35\r
36 //\r
37 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.\r
38 // We have to decrement TokenNumber by 1 to make it usable\r
39 // as the array index.\r
40 //\r
41 TokenNumber--;\r
42\r
43 LocalTokenNumber = *((UINT32 *)((UINT8 *)Database + Database->LocalTokenNumberTableOffset) + TokenNumber);\r
44\r
45 Size = (LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) >> PCD_DATUM_TYPE_SHIFT;\r
46\r
47 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == PCD_TYPE_SKU_ENABLED) {\r
48 if (Size == 0) {\r
49 GetPtrTypeSize (TokenNumber, &MaxSize, Database);\r
50 } else {\r
51 MaxSize = Size;\r
52 }\r
53 LocalTokenNumber = GetSkuEnabledTokenNumber (LocalTokenNumber & ~PCD_TYPE_SKU_ENABLED, MaxSize);\r
54 }\r
55\r
56 return LocalTokenNumber;\r
57}\r
58\r
59/**\r
60 Get PCD type by Local Token Number.\r
61\r
62 @param[in] LocalTokenNumber The PCD local token number.\r
63\r
64 @return PCD type.\r
65**/\r
66EFI_PCD_TYPE\r
67GetPcdType (\r
68 IN UINT32 LocalTokenNumber\r
69 )\r
70{\r
71 switch (LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) {\r
72 case PCD_DATUM_TYPE_POINTER:\r
73 return EFI_PCD_TYPE_PTR;\r
74 case PCD_DATUM_TYPE_UINT8:\r
b5bd21b0 75 if ((LocalTokenNumber & PCD_DATUM_TYPE_UINT8_BOOLEAN) == PCD_DATUM_TYPE_UINT8_BOOLEAN) {\r
96d6d004
SZ
76 return EFI_PCD_TYPE_BOOL;\r
77 } else {\r
78 return EFI_PCD_TYPE_8;\r
79 }\r
80 case PCD_DATUM_TYPE_UINT16:\r
81 return EFI_PCD_TYPE_16;\r
82 case PCD_DATUM_TYPE_UINT32:\r
83 return EFI_PCD_TYPE_32;\r
84 case PCD_DATUM_TYPE_UINT64:\r
85 return EFI_PCD_TYPE_64;\r
86 default:\r
87 ASSERT (FALSE);\r
88 return EFI_PCD_TYPE_8;\r
89 }\r
90}\r
91\r
92/**\r
93 Get PCD name.\r
94\r
95 @param[in] OnlyTokenSpaceName If TRUE, only need to get the TokenSpaceCName.\r
96 If FALSE, need to get the full PCD name.\r
97 @param[in] Database PCD database.\r
98 @param[in] TokenNumber The PCD token number.\r
99\r
100 @return The TokenSpaceCName or full PCD name.\r
101**/\r
102CHAR8 *\r
103GetPcdName (\r
104 IN BOOLEAN OnlyTokenSpaceName,\r
105 IN PEI_PCD_DATABASE *Database,\r
106 IN UINTN TokenNumber\r
107 )\r
108{\r
109 UINT8 *StringTable;\r
e85e284e 110 UINTN NameSize;\r
96d6d004
SZ
111 PCD_NAME_INDEX *PcdNameIndex;\r
112 CHAR8 *TokenSpaceName;\r
113 CHAR8 *PcdName;\r
114 CHAR8 *Name;\r
115\r
85d0b97d
SZ
116 //\r
117 // Return NULL when PCD name table is absent. \r
118 //\r
119 if (Database->PcdNameTableOffset == 0) {\r
120 return NULL;\r
121 }\r
122\r
96d6d004
SZ
123 //\r
124 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.\r
125 // We have to decrement TokenNumber by 1 to make it usable\r
126 // as the array index.\r
127 //\r
128 TokenNumber--;\r
129\r
130 StringTable = (UINT8 *) Database + Database->StringTableOffset;\r
131\r
132 //\r
133 // Get the PCD name index.\r
134 //\r
135 PcdNameIndex = (PCD_NAME_INDEX *)((UINT8 *) Database + Database->PcdNameTableOffset) + TokenNumber;\r
136 TokenSpaceName = (CHAR8 *)&StringTable[PcdNameIndex->TokenSpaceCNameIndex];\r
137 PcdName = (CHAR8 *)&StringTable[PcdNameIndex->PcdCNameIndex];\r
138\r
139 if (OnlyTokenSpaceName) {\r
140 //\r
141 // Only need to get the TokenSpaceCName.\r
142 //\r
143 Name = AllocateCopyPool (AsciiStrSize (TokenSpaceName), TokenSpaceName);\r
144 } else {\r
145 //\r
146 // Need to get the full PCD name.\r
147 //\r
e85e284e
QS
148 NameSize = AsciiStrSize (TokenSpaceName) + AsciiStrSize (PcdName);\r
149 Name = AllocateZeroPool (NameSize);\r
f47fc1cb 150 ASSERT (Name != NULL);\r
96d6d004
SZ
151 //\r
152 // Catenate TokenSpaceCName and PcdCName with a '.' to form the full PCD name.\r
153 //\r
e85e284e 154 AsciiStrCatS (Name, NameSize, TokenSpaceName);\r
96d6d004 155 Name[AsciiStrSize (TokenSpaceName) - sizeof (CHAR8)] = '.';\r
e85e284e 156 AsciiStrCatS (Name, NameSize, PcdName); \r
96d6d004
SZ
157 }\r
158\r
159 return Name;\r
160}\r
161\r
162/**\r
163 Retrieve additional information associated with a PCD token.\r
164\r
165 This includes information such as the type of value the TokenNumber is associated with as well as possible\r
166 human readable name that is associated with the token.\r
167\r
168 @param[in] Database PCD database.\r
169 @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.\r
170 @param[in] TokenNumber The PCD token number.\r
171 @param[out] PcdInfo The returned information associated with the requested TokenNumber.\r
172 The caller is responsible for freeing the buffer that is allocated by callee for PcdInfo->PcdName. \r
173\r
174 @retval EFI_SUCCESS The PCD information was returned successfully\r
175 @retval EFI_NOT_FOUND The PCD service could not find the requested token number.\r
176**/\r
177EFI_STATUS\r
178ExGetPcdInfo (\r
179 IN PEI_PCD_DATABASE *Database,\r
180 IN CONST EFI_GUID *Guid,\r
181 IN UINTN TokenNumber,\r
182 OUT EFI_PCD_INFO *PcdInfo\r
183 )\r
184{\r
185 UINTN GuidTableIdx;\r
186 EFI_GUID *MatchGuid;\r
187 EFI_GUID *GuidTable;\r
188 DYNAMICEX_MAPPING *ExMapTable;\r
189 UINTN Index;\r
190 UINT32 LocalTokenNumber;\r
191\r
192 GuidTable = (EFI_GUID *)((UINT8 *)Database + Database->GuidTableOffset);\r
193 MatchGuid = ScanGuid (GuidTable, Database->GuidTableCount * sizeof(EFI_GUID), Guid);\r
194\r
195 if (MatchGuid == NULL) {\r
196 return EFI_NOT_FOUND;\r
197 }\r
198\r
199 GuidTableIdx = MatchGuid - GuidTable;\r
200\r
201 ExMapTable = (DYNAMICEX_MAPPING *)((UINT8 *)Database + Database->ExMapTableOffset);\r
202\r
203 //\r
204 // Find the PCD by GuidTableIdx and ExTokenNumber in ExMapTable.\r
205 //\r
206 for (Index = 0; Index < Database->ExTokenCount; Index++) {\r
207 if (ExMapTable[Index].ExGuidIndex == GuidTableIdx) {\r
208 if (TokenNumber == PCD_INVALID_TOKEN_NUMBER) {\r
209 //\r
210 // TokenNumber is 0, follow spec to set PcdType to EFI_PCD_TYPE_8,\r
211 // PcdSize to 0 and PcdName to the null-terminated ASCII string\r
212 // associated with the token's namespace Guid.\r
213 //\r
214 PcdInfo->PcdType = EFI_PCD_TYPE_8;\r
215 PcdInfo->PcdSize = 0;\r
216 //\r
217 // Here use one representative in the token space to get the TokenSpaceCName.\r
218 // \r
219 PcdInfo->PcdName = GetPcdName (TRUE, Database, ExMapTable[Index].TokenNumber);\r
220 return EFI_SUCCESS;\r
221 } else if (ExMapTable[Index].ExTokenNumber == TokenNumber) {\r
222 PcdInfo->PcdSize = PeiPcdGetSize (ExMapTable[Index].TokenNumber);\r
223 LocalTokenNumber = GetLocalTokenNumber (Database, ExMapTable[Index].TokenNumber);\r
224 PcdInfo->PcdType = GetPcdType (LocalTokenNumber);\r
225 PcdInfo->PcdName = GetPcdName (FALSE, Database, ExMapTable[Index].TokenNumber);\r
226 return EFI_SUCCESS;\r
227 }\r
228 }\r
229 }\r
230\r
231 return EFI_NOT_FOUND;\r
232}\r
233\r
234/**\r
235 Retrieve additional information associated with a PCD token.\r
236\r
237 This includes information such as the type of value the TokenNumber is associated with as well as possible\r
238 human readable name that is associated with the token.\r
239\r
240 @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.\r
241 @param[in] TokenNumber The PCD token number.\r
242 @param[out] PcdInfo The returned information associated with the requested TokenNumber.\r
243 The caller is responsible for freeing the buffer that is allocated by callee for PcdInfo->PcdName.\r
244\r
245 @retval EFI_SUCCESS The PCD information was returned successfully.\r
246 @retval EFI_NOT_FOUND The PCD service could not find the requested token number.\r
247**/\r
248EFI_STATUS\r
249PeiGetPcdInfo (\r
250 IN CONST EFI_GUID *Guid,\r
251 IN UINTN TokenNumber,\r
252 OUT EFI_PCD_INFO *PcdInfo\r
253 )\r
254{\r
255 PEI_PCD_DATABASE *PeiPcdDb;\r
256 BOOLEAN PeiExMapTableEmpty;\r
257 UINTN PeiNexTokenNumber;\r
258 UINT32 LocalTokenNumber;\r
259\r
96d6d004
SZ
260 ASSERT (PcdInfo != NULL);\r
261\r
262 PeiPcdDb = GetPcdDatabase ();\r
263 PeiNexTokenNumber = PeiPcdDb->LocalTokenCount - PeiPcdDb->ExTokenCount;\r
264\r
265 if (PeiPcdDb->ExTokenCount == 0) {\r
266 PeiExMapTableEmpty = TRUE;\r
267 } else {\r
268 PeiExMapTableEmpty = FALSE;\r
269 }\r
270\r
271 if (Guid == NULL) {\r
272 if (TokenNumber > PeiNexTokenNumber) {\r
273 return EFI_NOT_FOUND;\r
274 } else if (TokenNumber == PCD_INVALID_TOKEN_NUMBER) {\r
275 //\r
276 // TokenNumber is 0, follow spec to set PcdType to EFI_PCD_TYPE_8,\r
277 // PcdSize to 0 and PcdName to NULL for default Token Space.\r
278 //\r
279 PcdInfo->PcdType = EFI_PCD_TYPE_8;\r
280 PcdInfo->PcdSize = 0;\r
281 PcdInfo->PcdName = NULL;\r
282 } else {\r
283 PcdInfo->PcdSize = PeiPcdGetSize (TokenNumber);\r
284 LocalTokenNumber = GetLocalTokenNumber (PeiPcdDb, TokenNumber);\r
285 PcdInfo->PcdType = GetPcdType (LocalTokenNumber);\r
286 PcdInfo->PcdName = GetPcdName (FALSE, PeiPcdDb, TokenNumber);\r
287 }\r
288 return EFI_SUCCESS;\r
289 } else {\r
290 if (PeiExMapTableEmpty) {\r
291 return EFI_NOT_FOUND;\r
292 }\r
293 return ExGetPcdInfo (\r
294 PeiPcdDb,\r
295 Guid,\r
296 TokenNumber,\r
297 PcdInfo\r
298 );\r
299 }\r
300}\r
301\r
80408db0 302/**\r
303 The function registers the CallBackOnSet fucntion\r
304 according to TokenNumber and EFI_GUID space.\r
305\r
fc547e08 306 @param ExTokenNumber The token number.\r
80408db0 307 @param Guid The GUID space.\r
308 @param CallBackFunction The Callback function to be registered.\r
309 @param Register To register or unregister the callback function.\r
310\r
311 @retval EFI_SUCCESS If the Callback function is registered.\r
312 @retval EFI_NOT_FOUND If the PCD Entry is not found according to Token Number and GUID space.\r
313 @retval EFI_OUT_OF_RESOURCES If the callback function can't be registered because there is not free\r
314 slot left in the CallbackFnTable.\r
8ec8bed4 315 @retval EFI_INVALID_PARAMETER If the callback function want to be de-registered can not be found.\r
fc547e08 316**/\r
80408db0 317EFI_STATUS\r
318PeiRegisterCallBackWorker (\r
319 IN UINTN ExTokenNumber,\r
320 IN CONST EFI_GUID *Guid, OPTIONAL\r
321 IN PCD_PPI_CALLBACK CallBackFunction,\r
322 IN BOOLEAN Register\r
323)\r
324{\r
325 EFI_HOB_GUID_TYPE *GuidHob;\r
326 PCD_PPI_CALLBACK *CallbackTable;\r
327 PCD_PPI_CALLBACK Compare;\r
328 PCD_PPI_CALLBACK Assign;\r
329 UINT32 LocalTokenNumber;\r
419db80b
BF
330 UINT32 LocalTokenCount;\r
331 UINTN PeiNexTokenNumber;\r
80408db0 332 UINTN TokenNumber;\r
333 UINTN Idx;\r
419db80b
BF
334 PEI_PCD_DATABASE *PeiPcdDb;\r
335\r
336 PeiPcdDb = GetPcdDatabase();\r
337 LocalTokenCount = PeiPcdDb->LocalTokenCount;\r
338 PeiNexTokenNumber = PeiPcdDb->LocalTokenCount - PeiPcdDb->ExTokenCount;\r
80408db0 339\r
340 if (Guid == NULL) {\r
341 TokenNumber = ExTokenNumber;\r
80408db0 342 //\r
343 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.\r
344 // We have to decrement TokenNumber by 1 to make it usable\r
345 // as the array index.\r
346 //\r
347 TokenNumber--;\r
419db80b 348 ASSERT (TokenNumber + 1 < (PeiNexTokenNumber + 1));\r
80408db0 349 } else {\r
350 TokenNumber = GetExPcdTokenNumber (Guid, ExTokenNumber);\r
86714ccd 351 if (TokenNumber == PCD_INVALID_TOKEN_NUMBER) {\r
352 return EFI_NOT_FOUND;\r
353 }\r
80408db0 354 //\r
355 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.\r
356 // We have to decrement TokenNumber by 1 to make it usable\r
357 // as the array index.\r
358 //\r
359 TokenNumber--;\r
360 // EBC compiler is very choosy. It may report warning about comparison\r
361 // between UINTN and 0 . So we add 1 in each size of the \r
362 // comparison.\r
419db80b 363 ASSERT ((TokenNumber + 1) < (LocalTokenCount + 1));\r
80408db0 364 }\r
365\r
366\r
419db80b 367 LocalTokenNumber = *((UINT32 *)((UINT8 *)PeiPcdDb + PeiPcdDb->LocalTokenNumberTableOffset) + TokenNumber);\r
80408db0 368\r
369 //\r
370 // We don't support SET for HII and VPD type PCD entry in PEI phase.\r
371 // So we will assert if any register callback for such PCD entry.\r
372 //\r
373 ASSERT ((LocalTokenNumber & PCD_TYPE_HII) == 0);\r
374 ASSERT ((LocalTokenNumber & PCD_TYPE_VPD) == 0);\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
188e4e84 380 CallbackTable = CallbackTable + (TokenNumber * PcdGet32 (PcdMaxPeiPcdCallBackNumberPerPcdEntry));\r
80408db0 381\r
382 Compare = Register? NULL: CallBackFunction;\r
383 Assign = Register? CallBackFunction: NULL;\r
384\r
385\r
188e4e84 386 for (Idx = 0; Idx < PcdGet32 (PcdMaxPeiPcdCallBackNumberPerPcdEntry); Idx++) {\r
80408db0 387 if (CallbackTable[Idx] == Compare) {\r
388 CallbackTable[Idx] = Assign;\r
389 return EFI_SUCCESS;\r
390 }\r
391 }\r
392\r
8ec8bed4 393 return Register? EFI_OUT_OF_RESOURCES : EFI_INVALID_PARAMETER;\r
80408db0 394\r
395}\r
396\r
419db80b
BF
397\r
398/**\r
399 Find the Pcd database. \r
400\r
401 @param FileHandle Handle of the file the external PCD database binary located.\r
402\r
403 @retval The base address of external PCD database binary.\r
404 @retval NULL Return NULL if not find.\r
405**/\r
406VOID *\r
407LocateExPcdBinary (\r
408 IN EFI_PEI_FILE_HANDLE FileHandle\r
409 )\r
410{\r
411 EFI_STATUS Status;\r
412 VOID *PcdDb;\r
413\r
414 PcdDb = NULL;\r
415\r
416 ASSERT (FileHandle != NULL);\r
417\r
418 Status = PeiServicesFfsFindSectionData (EFI_SECTION_RAW, FileHandle, &PcdDb);\r
419 ASSERT_EFI_ERROR (Status);\r
420\r
421 //\r
422 // Check the first bytes (Header Signature Guid) and build version.\r
423 //\r
424 if (!CompareGuid (PcdDb, &gPcdDataBaseSignatureGuid) ||\r
425 (((PEI_PCD_DATABASE *) PcdDb)->BuildVersion != PCD_SERVICE_PEIM_VERSION)) {\r
426 ASSERT (FALSE);\r
427 }\r
428 return PcdDb;\r
429}\r
430\r
431\r
80408db0 432/**\r
433 The function builds the PCD database.\r
419db80b
BF
434\r
435 @param FileHandle Handle of the file the external PCD database binary located.\r
436\r
96d6d004 437 @return Pointer to PCD database.\r
fc547e08 438**/\r
96d6d004 439PEI_PCD_DATABASE *\r
80408db0 440BuildPcdDatabase (\r
419db80b 441 IN EFI_PEI_FILE_HANDLE FileHandle\r
80408db0 442 )\r
443{\r
419db80b
BF
444 PEI_PCD_DATABASE *Database;\r
445 PEI_PCD_DATABASE *PeiPcdDbBinary;\r
446 VOID *CallbackFnTable;\r
447 UINTN SizeOfCallbackFnTable;\r
448\r
449 //\r
450 // Locate the external PCD database binary for one section of current FFS\r
451 //\r
452 PeiPcdDbBinary = LocateExPcdBinary (FileHandle);\r
80408db0 453\r
419db80b
BF
454 ASSERT(PeiPcdDbBinary != NULL);\r
455\r
456 Database = BuildGuidHob (&gPcdDataBaseHobGuid, PeiPcdDbBinary->Length + PeiPcdDbBinary->UninitDataBaseSize);\r
457\r
458 ZeroMem (Database, PeiPcdDbBinary->Length + PeiPcdDbBinary->UninitDataBaseSize);\r
80408db0 459\r
460 //\r
419db80b 461 // PeiPcdDbBinary is smaller than Database\r
80408db0 462 //\r
419db80b 463 CopyMem (Database, PeiPcdDbBinary, PeiPcdDbBinary->Length);\r
80408db0 464\r
419db80b 465 SizeOfCallbackFnTable = Database->LocalTokenCount * sizeof (PCD_PPI_CALLBACK) * PcdGet32 (PcdMaxPeiPcdCallBackNumberPerPcdEntry);\r
80408db0 466\r
96cb78a1 467 CallbackFnTable = BuildGuidHob (&gEfiCallerIdGuid, SizeOfCallbackFnTable);\r
80408db0 468 \r
469 ZeroMem (CallbackFnTable, SizeOfCallbackFnTable);\r
96d6d004
SZ
470\r
471 return Database;\r
80408db0 472}\r
473\r
80408db0 474/**\r
475 The function is provided by PCD PEIM and PCD DXE driver to\r
476 do the work of reading a HII variable from variable service.\r
477\r
478 @param VariableGuid The Variable GUID.\r
479 @param VariableName The Variable Name.\r
480 @param VariableData The output data.\r
481 @param VariableSize The size of the variable.\r
482\r
483 @retval EFI_SUCCESS Operation successful.\r
484 @retval EFI_NOT_FOUND Variablel not found.\r
fc547e08 485**/\r
80408db0 486EFI_STATUS\r
487GetHiiVariable (\r
488 IN CONST EFI_GUID *VariableGuid,\r
489 IN UINT16 *VariableName,\r
490 OUT VOID **VariableData,\r
491 OUT UINTN *VariableSize\r
492 )\r
493{\r
494 UINTN Size;\r
495 EFI_STATUS Status;\r
496 VOID *Buffer;\r
97a079ed 497 EFI_PEI_READ_ONLY_VARIABLE2_PPI *VariablePpi;\r
80408db0 498\r
97a079ed 499 Status = PeiServicesLocatePpi (&gEfiPeiReadOnlyVariable2PpiGuid, 0, NULL, (VOID **) &VariablePpi);\r
80408db0 500 ASSERT_EFI_ERROR (Status);\r
501\r
502 Size = 0;\r
97a079ed
A
503 Status = VariablePpi->GetVariable (\r
504 VariablePpi,\r
80408db0 505 VariableName,\r
506 (EFI_GUID *) VariableGuid,\r
507 NULL,\r
508 &Size,\r
509 NULL\r
97a079ed 510 );\r
80408db0 511\r
e5618791 512 if (Status == EFI_BUFFER_TOO_SMALL) {\r
80408db0 513 Status = PeiServicesAllocatePool (Size, &Buffer);\r
514 ASSERT_EFI_ERROR (Status);\r
515\r
97a079ed
A
516 Status = VariablePpi->GetVariable (\r
517 VariablePpi,\r
80408db0 518 (UINT16 *) VariableName,\r
519 (EFI_GUID *) VariableGuid,\r
520 NULL,\r
521 &Size,\r
522 Buffer\r
523 );\r
524 ASSERT_EFI_ERROR (Status);\r
525\r
526 *VariableSize = Size;\r
527 *VariableData = Buffer;\r
528\r
529 return EFI_SUCCESS;\r
e5618791 530 }\r
80408db0 531\r
fc547e08 532 return EFI_NOT_FOUND;\r
80408db0 533}\r
534\r
fc547e08 535/**\r
536 Find the local token number according to system SKU ID.\r
537\r
538 @param LocalTokenNumber PCD token number\r
539 @param Size The size of PCD entry.\r
540\r
541 @return Token number according to system SKU ID.\r
542\r
543**/\r
80408db0 544UINT32\r
545GetSkuEnabledTokenNumber (\r
546 UINT32 LocalTokenNumber,\r
547 UINTN Size\r
548 ) \r
549{\r
550 PEI_PCD_DATABASE *PeiPcdDb;\r
551 SKU_HEAD *SkuHead;\r
552 SKU_ID *SkuIdTable;\r
fc547e08 553 INTN Index;\r
80408db0 554 UINT8 *Value;\r
419db80b 555 BOOLEAN FoundSku;\r
80408db0 556\r
557 PeiPcdDb = GetPcdDatabase ();\r
558\r
559 ASSERT ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0);\r
560\r
561 SkuHead = (SKU_HEAD *) ((UINT8 *)PeiPcdDb + (LocalTokenNumber & PCD_DATABASE_OFFSET_MASK));\r
562 Value = (UINT8 *) ((UINT8 *)PeiPcdDb + (SkuHead->SkuDataStartOffset));\r
563 SkuIdTable = (SKU_ID *) ((UINT8 *)PeiPcdDb + (SkuHead->SkuIdTableOffset));\r
419db80b
BF
564\r
565 //\r
566 // Find the current system's SKU ID entry in SKU ID table.\r
567 //\r
568 FoundSku = FALSE;\r
fc547e08 569 for (Index = 0; Index < SkuIdTable[0]; Index++) {\r
419db80b
BF
570 if (PeiPcdDb->SystemSkuId == SkuIdTable[Index + 1]) {\r
571 FoundSku = TRUE;\r
80408db0 572 break;\r
573 }\r
574 }\r
575\r
419db80b
BF
576 //\r
577 // Find the default SKU ID entry in SKU ID table.\r
578 //\r
579 if(!FoundSku) {\r
580 for (Index = 0; Index < SkuIdTable[0]; Index++) {\r
581 if (0 == SkuIdTable[Index + 1]) {\r
582 break;\r
583 }\r
584 }\r
585 }\r
586 ASSERT (Index < SkuIdTable[0]);\r
587\r
80408db0 588 switch (LocalTokenNumber & PCD_TYPE_ALL_SET) {\r
589 case PCD_TYPE_VPD:\r
fc547e08 590 Value = (UINT8 *) &(((VPD_HEAD *) Value)[Index]);\r
80408db0 591 return (UINT32) ((Value - (UINT8 *) PeiPcdDb) | PCD_TYPE_VPD);\r
592\r
593 case PCD_TYPE_HII:\r
fc547e08 594 Value = (UINT8 *) &(((VARIABLE_HEAD *) Value)[Index]);\r
80408db0 595 return (UINT32) ((Value - (UINT8 *) PeiPcdDb) | PCD_TYPE_HII);\r
419db80b
BF
596\r
597 case PCD_TYPE_HII|PCD_TYPE_STRING:\r
598 Value = (UINT8 *) &(((VARIABLE_HEAD *) Value)[Index]);\r
599 return (UINT32) ((Value - (UINT8 *) PeiPcdDb) | PCD_TYPE_HII | PCD_TYPE_STRING);\r
600\r
80408db0 601 case PCD_TYPE_STRING:\r
fc547e08 602 Value = (UINT8 *) &(((STRING_HEAD *) Value)[Index]);\r
80408db0 603 return (UINT32) ((Value - (UINT8 *) PeiPcdDb) | PCD_TYPE_STRING);\r
604\r
605 case PCD_TYPE_DATA:\r
fc547e08 606 Value += Size * Index;\r
419db80b 607 return (UINT32) ((Value - (UINT8 *) PeiPcdDb) | PCD_TYPE_DATA);\r
80408db0 608\r
609 default:\r
610 ASSERT (FALSE);\r
611 }\r
612\r
613 ASSERT (FALSE);\r
614\r
615 return 0;\r
80408db0 616}\r
617\r
fc547e08 618/**\r
619 Invoke the callback function when dynamic PCD entry was set, if this PCD entry \r
620 has registered callback function.\r
80408db0 621\r
fc547e08 622 @param ExTokenNumber DynamicEx PCD's token number, if this PCD entry is dyanmicEx\r
623 type PCD.\r
624 @param Guid DynamicEx PCD's guid, if this PCD entry is dynamicEx type\r
625 PCD.\r
626 @param TokenNumber PCD token number generated by build tools.\r
627 @param Data Value want to be set for this PCD entry\r
628 @param Size The size of value\r
80408db0 629\r
fc547e08 630**/\r
80408db0 631VOID\r
632InvokeCallbackOnSet (\r
633 UINTN ExTokenNumber,\r
634 CONST EFI_GUID *Guid, OPTIONAL\r
635 UINTN TokenNumber,\r
636 VOID *Data,\r
637 UINTN Size\r
638 )\r
639{\r
640 EFI_HOB_GUID_TYPE *GuidHob;\r
641 PCD_PPI_CALLBACK *CallbackTable;\r
642 UINTN Idx;\r
419db80b
BF
643 PEI_PCD_DATABASE *PeiPcdDb;\r
644 UINT32 LocalTokenCount;\r
80408db0 645\r
646 //\r
647 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.\r
648 // We have to decrement TokenNumber by 1 to make it usable\r
649 // as the array index.\r
650 //\r
651 TokenNumber--;\r
419db80b
BF
652\r
653 PeiPcdDb = GetPcdDatabase ();\r
654 LocalTokenCount = PeiPcdDb->LocalTokenCount;\r
655\r
80408db0 656 if (Guid == NULL) {\r
657 // EBC compiler is very choosy. It may report warning about comparison\r
658 // between UINTN and 0 . So we add 1 in each size of the \r
659 // comparison.\r
419db80b 660 ASSERT (TokenNumber + 1 < (LocalTokenCount + 1));\r
80408db0 661 }\r
662\r
96cb78a1 663 GuidHob = GetFirstGuidHob (&gEfiCallerIdGuid);\r
80408db0 664 ASSERT (GuidHob != NULL);\r
665 \r
666 CallbackTable = GET_GUID_HOB_DATA (GuidHob);\r
667\r
188e4e84 668 CallbackTable += (TokenNumber * PcdGet32 (PcdMaxPeiPcdCallBackNumberPerPcdEntry));\r
80408db0 669\r
188e4e84 670 for (Idx = 0; Idx < PcdGet32 (PcdMaxPeiPcdCallBackNumberPerPcdEntry); Idx++) {\r
80408db0 671 if (CallbackTable[Idx] != NULL) {\r
672 CallbackTable[Idx] (Guid,\r
736c5dd5 673 (Guid == NULL) ? (TokenNumber + 1) : ExTokenNumber,\r
80408db0 674 Data,\r
675 Size\r
676 );\r
677 }\r
678 }\r
80408db0 679}\r
680\r
fc547e08 681/**\r
682 Wrapper function for setting non-pointer type value for a PCD entry.\r
683\r
684 @param TokenNumber Pcd token number autogenerated by build tools.\r
685 @param Data Value want to be set for PCD entry\r
686 @param Size Size of value.\r
80408db0 687\r
fc547e08 688 @return status of SetWorker.\r
80408db0 689\r
fc547e08 690**/\r
80408db0 691EFI_STATUS\r
692SetValueWorker (\r
693 IN UINTN TokenNumber,\r
694 IN VOID *Data,\r
695 IN UINTN Size\r
696 )\r
697{\r
698 return SetWorker (TokenNumber, Data, &Size, FALSE);\r
699}\r
700\r
fc547e08 701/**\r
702 Set value for an PCD entry\r
703\r
704 @param TokenNumber Pcd token number autogenerated by build tools.\r
705 @param Data Value want to be set for PCD entry\r
706 @param Size Size of value.\r
707 @param PtrType If TRUE, the type of PCD entry's value is Pointer.\r
708 If False, the type of PCD entry's value is not Pointer.\r
709\r
710 @retval EFI_INVALID_PARAMETER If this PCD type is VPD, VPD PCD can not be set.\r
711 @retval EFI_INVALID_PARAMETER If Size can not be set to size table.\r
149fb6d6 712 @retval EFI_INVALID_PARAMETER If Size of non-Ptr type PCD does not match the size information in PCD database.\r
fc547e08 713 @retval EFI_NOT_FOUND If value type of PCD entry is intergrate, but not in\r
714 range of UINT8, UINT16, UINT32, UINT64\r
715 @retval EFI_NOT_FOUND Can not find the PCD type according to token number. \r
716**/\r
80408db0 717EFI_STATUS\r
718SetWorker (\r
719 IN UINTN TokenNumber,\r
fc547e08 720 IN VOID *Data,\r
80408db0 721 IN OUT UINTN *Size,\r
722 IN BOOLEAN PtrType\r
723 )\r
724{\r
725 UINT32 LocalTokenNumber;\r
419db80b 726 UINTN PeiNexTokenNumber;\r
80408db0 727 PEI_PCD_DATABASE *PeiPcdDb;\r
6cfc7292 728 STRING_HEAD StringTableIdx;\r
80408db0 729 UINTN Offset;\r
730 VOID *InternalData;\r
731 UINTN MaxSize;\r
419db80b 732 UINT32 LocalTokenCount;\r
80408db0 733\r
f806dd27 734 if (!FeaturePcdGet(PcdPeiFullPcdDatabaseEnable)) {\r
80408db0 735 return EFI_UNSUPPORTED;\r
736 }\r
737 \r
738 //\r
739 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.\r
740 // We have to decrement TokenNumber by 1 to make it usable\r
741 // as the array index.\r
742 //\r
743 TokenNumber--;\r
419db80b
BF
744 PeiPcdDb = GetPcdDatabase ();\r
745 LocalTokenCount = PeiPcdDb->LocalTokenCount;\r
80408db0 746\r
747 // EBC compiler is very choosy. It may report warning about comparison\r
748 // between UINTN and 0 . So we add 1 in each size of the \r
749 // comparison.\r
419db80b 750 ASSERT (TokenNumber + 1 < (LocalTokenCount + 1));\r
80408db0 751\r
8ec8bed4 752 if (PtrType) {\r
64894410
LG
753 //\r
754 // Get MaxSize first, then check new size with max buffer size.\r
755 //\r
756 GetPtrTypeSize (TokenNumber, &MaxSize, PeiPcdDb);\r
757 if (*Size > MaxSize) {\r
cb40609c 758 *Size = MaxSize;\r
8ec8bed4 759 return EFI_INVALID_PARAMETER;\r
760 }\r
761 } else {\r
762 if (*Size != PeiPcdGetSize (TokenNumber + 1)) {\r
763 return EFI_INVALID_PARAMETER;\r
764 }\r
80408db0 765 }\r
766\r
767 //\r
768 // We only invoke the callback function for Dynamic Type PCD Entry.\r
769 // For Dynamic EX PCD entry, we have invoked the callback function for Dynamic EX\r
770 // type PCD entry in ExSetWorker.\r
771 //\r
419db80b
BF
772 PeiNexTokenNumber = PeiPcdDb->LocalTokenCount - PeiPcdDb->ExTokenCount;\r
773 if (TokenNumber + 1 < PeiNexTokenNumber + 1) {\r
80408db0 774 InvokeCallbackOnSet (0, NULL, TokenNumber + 1, Data, *Size);\r
775 }\r
776\r
96d6d004 777 LocalTokenNumber = GetLocalTokenNumber (PeiPcdDb, TokenNumber + 1);\r
80408db0 778\r
779 Offset = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK;\r
780 InternalData = (VOID *) ((UINT8 *) PeiPcdDb + Offset);\r
781 \r
782 switch (LocalTokenNumber & PCD_TYPE_ALL_SET) {\r
783 case PCD_TYPE_VPD:\r
784 case PCD_TYPE_HII:\r
6ac15f7c 785 case PCD_TYPE_HII|PCD_TYPE_STRING:\r
80408db0 786 {\r
787 ASSERT (FALSE);\r
788 return EFI_INVALID_PARAMETER;\r
789 }\r
790\r
791 case PCD_TYPE_STRING:\r
792 if (SetPtrTypeSize (TokenNumber, Size, PeiPcdDb)) {\r
6cfc7292 793 StringTableIdx = *((STRING_HEAD *)InternalData);\r
419db80b 794 CopyMem ((UINT8 *)PeiPcdDb + PeiPcdDb->StringTableOffset + StringTableIdx, Data, *Size);\r
80408db0 795 return EFI_SUCCESS;\r
796 } else {\r
797 return EFI_INVALID_PARAMETER;\r
798 }\r
799\r
800 case PCD_TYPE_DATA:\r
801 {\r
802 if (PtrType) {\r
803 if (SetPtrTypeSize (TokenNumber, Size, PeiPcdDb)) {\r
804 CopyMem (InternalData, Data, *Size);\r
805 return EFI_SUCCESS;\r
806 } else {\r
807 return EFI_INVALID_PARAMETER;\r
808 }\r
809 }\r
810\r
811 switch (*Size) {\r
812 case sizeof(UINT8):\r
813 *((UINT8 *) InternalData) = *((UINT8 *) Data);\r
814 return EFI_SUCCESS;\r
815\r
816 case sizeof(UINT16):\r
817 *((UINT16 *) InternalData) = *((UINT16 *) Data);\r
818 return EFI_SUCCESS;\r
819\r
820 case sizeof(UINT32):\r
821 *((UINT32 *) InternalData) = *((UINT32 *) Data);\r
822 return EFI_SUCCESS;\r
823\r
824 case sizeof(UINT64):\r
825 *((UINT64 *) InternalData) = *((UINT64 *) Data);\r
826 return EFI_SUCCESS;\r
827\r
828 default:\r
829 ASSERT (FALSE);\r
830 return EFI_NOT_FOUND;\r
831 }\r
832 }\r
833 \r
834 }\r
835\r
836 ASSERT (FALSE);\r
837 return EFI_NOT_FOUND;\r
838\r
839}\r
840\r
fc547e08 841/**\r
842 Wrapper function for set PCD value for non-Pointer type dynamic-ex PCD.\r
80408db0 843\r
fc547e08 844 @param ExTokenNumber Token number for dynamic-ex PCD.\r
845 @param Guid Token space guid for dynamic-ex PCD.\r
846 @param Data Value want to be set.\r
847 @param SetSize The size of value.\r
80408db0 848\r
fc547e08 849 @return status of ExSetWorker().\r
850\r
851**/\r
80408db0 852EFI_STATUS\r
853ExSetValueWorker (\r
854 IN UINTN ExTokenNumber,\r
855 IN CONST EFI_GUID *Guid,\r
856 IN VOID *Data,\r
857 IN UINTN Size\r
858 )\r
859{\r
860 return ExSetWorker (ExTokenNumber, Guid, Data, &Size, FALSE);\r
861}\r
862\r
fc547e08 863/**\r
419db80b 864 Set value for a dynamic-ex PCD entry.\r
fc547e08 865 \r
866 This routine find the local token number according to dynamic-ex PCD's token \r
867 space guid and token number firstly, and invoke callback function if this PCD\r
868 entry registered callback function. Finally, invoken general SetWorker to set\r
869 PCD value.\r
870 \r
871 @param ExTokenNumber Dynamic-ex PCD token number.\r
872 @param Guid Token space guid for dynamic-ex PCD.\r
873 @param Data PCD value want to be set\r
874 @param SetSize Size of value.\r
875 @param PtrType If TRUE, this PCD entry is pointer type.\r
876 If FALSE, this PCD entry is not pointer type.\r
80408db0 877\r
fc547e08 878 @return status of SetWorker().\r
80408db0 879\r
fc547e08 880**/\r
80408db0 881EFI_STATUS\r
882ExSetWorker (\r
883 IN UINTN ExTokenNumber,\r
884 IN CONST EFI_GUID *Guid,\r
885 IN VOID *Data,\r
886 IN OUT UINTN *Size,\r
887 IN BOOLEAN PtrType\r
888 )\r
889{\r
890 UINTN TokenNumber;\r
891\r
f806dd27 892 if (!FeaturePcdGet(PcdPeiFullPcdDatabaseEnable)) {\r
80408db0 893 return EFI_UNSUPPORTED;\r
894 }\r
895\r
896 TokenNumber = GetExPcdTokenNumber (Guid, ExTokenNumber);\r
86714ccd 897 if (TokenNumber == PCD_INVALID_TOKEN_NUMBER) {\r
898 return EFI_NOT_FOUND;\r
899 }\r
900 \r
80408db0 901 InvokeCallbackOnSet (ExTokenNumber, Guid, TokenNumber, Data, *Size);\r
902\r
903 return SetWorker (TokenNumber, Data, Size, PtrType);\r
904\r
905}\r
906\r
fc547e08 907/**\r
908 Wrapper function for get PCD value for dynamic-ex PCD.\r
80408db0 909\r
fc547e08 910 @param Guid Token space guid for dynamic-ex PCD.\r
911 @param ExTokenNumber Token number for dyanmic-ex PCD.\r
912 @param GetSize The size of dynamic-ex PCD value.\r
80408db0 913\r
fc547e08 914 @return PCD entry in PCD database.\r
80408db0 915\r
fc547e08 916**/\r
80408db0 917VOID *\r
918ExGetWorker (\r
919 IN CONST EFI_GUID *Guid,\r
920 IN UINTN ExTokenNumber,\r
921 IN UINTN GetSize\r
922 )\r
f806dd27 923{ \r
80408db0 924 return GetWorker (GetExPcdTokenNumber (Guid, ExTokenNumber), GetSize);\r
925}\r
926\r
fc547e08 927/**\r
928 Get the PCD entry pointer in PCD database.\r
929 \r
930 This routine will visit PCD database to find the PCD entry according to given\r
931 token number. The given token number is autogened by build tools and it will be \r
932 translated to local token number. Local token number contains PCD's type and \r
933 offset of PCD entry in PCD database.\r
80408db0 934\r
fc547e08 935 @param TokenNumber Token's number, it is autogened by build tools\r
936 @param GetSize The size of token's value\r
80408db0 937\r
fc547e08 938 @return PCD entry pointer in PCD database\r
80408db0 939\r
fc547e08 940**/\r
80408db0 941VOID *\r
942GetWorker (\r
fc547e08 943 IN UINTN TokenNumber,\r
944 IN UINTN GetSize\r
80408db0 945 )\r
946{\r
947 UINT32 Offset;\r
948 EFI_GUID *Guid;\r
949 UINT16 *Name;\r
950 VARIABLE_HEAD *VariableHead;\r
951 EFI_STATUS Status;\r
952 UINTN DataSize;\r
953 VOID *Data;\r
d0965169 954 UINT8 *StringTable;\r
6cfc7292 955 STRING_HEAD StringTableIdx;\r
80408db0 956 PEI_PCD_DATABASE *PeiPcdDb;\r
957 UINT32 LocalTokenNumber;\r
419db80b 958 UINT32 LocalTokenCount;\r
553e8669 959 UINT8 *VaraiableDefaultBuffer;\r
80408db0 960\r
961 //\r
962 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.\r
963 // We have to decrement TokenNumber by 1 to make it usable\r
964 // as the array index.\r
965 //\r
966 TokenNumber--;\r
967\r
419db80b
BF
968 PeiPcdDb = GetPcdDatabase ();\r
969 LocalTokenCount = PeiPcdDb->LocalTokenCount;\r
970\r
80408db0 971 // EBC compiler is very choosy. It may report warning about comparison\r
972 // between UINTN and 0 . So we add 1 in each size of the \r
973 // comparison.\r
419db80b 974 ASSERT (TokenNumber + 1 < (LocalTokenCount + 1));\r
80408db0 975\r
976 ASSERT ((GetSize == PeiPcdGetSize(TokenNumber + 1)) || (GetSize == 0));\r
977\r
96d6d004 978 LocalTokenNumber = GetLocalTokenNumber (PeiPcdDb, TokenNumber + 1);\r
80408db0 979\r
980 Offset = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK;\r
419db80b
BF
981 StringTable = (UINT8 *)PeiPcdDb + PeiPcdDb->StringTableOffset;\r
982\r
80408db0 983 switch (LocalTokenNumber & PCD_TYPE_ALL_SET) {\r
984 case PCD_TYPE_VPD:\r
985 {\r
986 VPD_HEAD *VpdHead;\r
987 VpdHead = (VPD_HEAD *) ((UINT8 *)PeiPcdDb + Offset);\r
188e4e84 988 return (VOID *) (UINTN) (PcdGet32 (PcdVpdBaseAddress) + VpdHead->Offset);\r
80408db0 989 }\r
990 \r
6ac15f7c 991 case PCD_TYPE_HII|PCD_TYPE_STRING:\r
80408db0 992 case PCD_TYPE_HII:\r
993 {\r
994 VariableHead = (VARIABLE_HEAD *) ((UINT8 *)PeiPcdDb + Offset);\r
995 \r
419db80b 996 Guid = (EFI_GUID *) ((UINT8 *)PeiPcdDb + PeiPcdDb->GuidTableOffset) + VariableHead->GuidTableIndex;\r
d0965169 997 Name = (UINT16*)&StringTable[VariableHead->StringIndex];\r
80408db0 998\r
553e8669 999 if ((LocalTokenNumber & PCD_TYPE_ALL_SET) == (PCD_TYPE_HII|PCD_TYPE_STRING)) {\r
80408db0 1000 //\r
553e8669
SZ
1001 // If a HII type PCD's datum type is VOID*, the DefaultValueOffset is the index of \r
1002 // string array in string table.\r
80408db0 1003 //\r
553e8669
SZ
1004 VaraiableDefaultBuffer = (UINT8 *) &StringTable[*(STRING_HEAD*)((UINT8*) PeiPcdDb + VariableHead->DefaultValueOffset)]; \r
1005 } else {\r
1006 VaraiableDefaultBuffer = (UINT8 *) PeiPcdDb + VariableHead->DefaultValueOffset;\r
1007 }\r
1008 Status = GetHiiVariable (Guid, Name, &Data, &DataSize);\r
1009 if ((Status == EFI_SUCCESS) && (DataSize >= (VariableHead->Offset + GetSize))) {\r
1010 if (GetSize == 0) {\r
1011 //\r
1012 // It is a pointer type. So get the MaxSize reserved for\r
1013 // this PCD entry.\r
1014 //\r
1015 GetPtrTypeSize (TokenNumber, &GetSize, PeiPcdDb);\r
1016 if (GetSize > (DataSize - VariableHead->Offset)) {\r
1017 //\r
1018 // Use actual valid size.\r
1019 //\r
1020 GetSize = DataSize - VariableHead->Offset;\r
1021 }\r
6ac15f7c 1022 }\r
553e8669
SZ
1023 //\r
1024 // If the operation is successful, we copy the data\r
1025 // to the default value buffer in the PCD Database.\r
1026 //\r
1027 CopyMem (VaraiableDefaultBuffer, (UINT8 *) Data + VariableHead->Offset, GetSize);\r
80408db0 1028 }\r
553e8669 1029 return (VOID *) VaraiableDefaultBuffer;\r
80408db0 1030 }\r
1031\r
1032 case PCD_TYPE_DATA:\r
1033 return (VOID *) ((UINT8 *)PeiPcdDb + Offset);\r
1034\r
1035 case PCD_TYPE_STRING:\r
6cfc7292 1036 StringTableIdx = * (STRING_HEAD*) ((UINT8 *) PeiPcdDb + Offset);\r
80408db0 1037 return (VOID *) (&StringTable[StringTableIdx]);\r
1038\r
1039 default:\r
1040 ASSERT (FALSE);\r
1041 break;\r
1042 \r
1043 }\r
1044\r
1045 ASSERT (FALSE);\r
1046 \r
1047 return NULL;\r
1048 \r
1049}\r
1050\r
fc547e08 1051/**\r
419db80b 1052 Get Token Number according to dynamic-ex PCD's {token space guid:token number}\r
fc547e08 1053\r
1054 A dynamic-ex type PCD, developer must provide pair of token space guid: token number\r
1055 in DEC file. PCD database maintain a mapping table that translate pair of {token\r
419db80b 1056 space guid: token number} to Token Number.\r
fc547e08 1057 \r
1058 @param Guid Token space guid for dynamic-ex PCD entry.\r
419db80b 1059 @param ExTokenNumber Dynamic-ex PCD token number.\r
80408db0 1060\r
419db80b 1061 @return Token Number for dynamic-ex PCD.\r
80408db0 1062\r
fc547e08 1063**/\r
80408db0 1064UINTN \r
1065GetExPcdTokenNumber (\r
1066 IN CONST EFI_GUID *Guid,\r
1067 IN UINTN ExTokenNumber\r
1068 )\r
1069{\r
fc547e08 1070 UINT32 Index;\r
80408db0 1071 DYNAMICEX_MAPPING *ExMap;\r
1072 EFI_GUID *GuidTable;\r
1073 EFI_GUID *MatchGuid;\r
1074 UINTN MatchGuidIdx;\r
1075 PEI_PCD_DATABASE *PeiPcdDb;\r
1076\r
1077 PeiPcdDb = GetPcdDatabase();\r
80408db0 1078\r
419db80b
BF
1079 ExMap = (DYNAMICEX_MAPPING *)((UINT8 *)PeiPcdDb + PeiPcdDb->ExMapTableOffset);\r
1080 GuidTable = (EFI_GUID *)((UINT8 *)PeiPcdDb + PeiPcdDb->GuidTableOffset);\r
1081\r
1082 MatchGuid = ScanGuid (GuidTable, PeiPcdDb->GuidTableCount * sizeof(EFI_GUID), Guid);\r
80408db0 1083 //\r
1084 // We need to ASSERT here. If GUID can't be found in GuidTable, this is a\r
1085 // error in the BUILD system.\r
1086 //\r
1087 ASSERT (MatchGuid != NULL);\r
1088 \r
1089 MatchGuidIdx = MatchGuid - GuidTable;\r
1090 \r
419db80b 1091 for (Index = 0; Index < PeiPcdDb->ExTokenCount; Index++) {\r
fc547e08 1092 if ((ExTokenNumber == ExMap[Index].ExTokenNumber) && \r
1093 (MatchGuidIdx == ExMap[Index].ExGuidIndex)) {\r
419db80b 1094 return ExMap[Index].TokenNumber;\r
80408db0 1095 }\r
1096 }\r
1097 \r
86714ccd 1098 return PCD_INVALID_TOKEN_NUMBER;\r
80408db0 1099}\r
1100\r
fc547e08 1101/**\r
1102 Get PCD database from GUID HOB in PEI phase.\r
80408db0 1103\r
fc547e08 1104 @return Pointer to PCD database.\r
80408db0 1105\r
fc547e08 1106**/\r
80408db0 1107PEI_PCD_DATABASE *\r
1108GetPcdDatabase (\r
1109 VOID\r
1110 )\r
1111{\r
1112 EFI_HOB_GUID_TYPE *GuidHob;\r
1113\r
1114 GuidHob = GetFirstGuidHob (&gPcdDataBaseHobGuid);\r
1115 ASSERT (GuidHob != NULL);\r
1116 \r
1117 return (PEI_PCD_DATABASE *) GET_GUID_HOB_DATA (GuidHob);\r
1118}\r
1119\r
fc547e08 1120/**\r
419db80b 1121 Get SKU ID table from PCD database.\r
fc547e08 1122\r
1123 @param LocalTokenNumberTableIdx Index of local token number in token number table.\r
1124 @param Database PCD database.\r
80408db0 1125\r
fc547e08 1126 @return Pointer to SKU ID array table\r
80408db0 1127\r
fc547e08 1128**/\r
80408db0 1129SKU_ID *\r
1130GetSkuIdArray (\r
1131 IN UINTN LocalTokenNumberTableIdx,\r
1132 IN PEI_PCD_DATABASE *Database\r
1133 )\r
1134{\r
1135 SKU_HEAD *SkuHead;\r
1136 UINTN LocalTokenNumber;\r
1137\r
419db80b 1138 LocalTokenNumber = *((UINT32 *)((UINT8 *)Database + Database->LocalTokenNumberTableOffset) + LocalTokenNumberTableIdx);\r
80408db0 1139\r
1140 ASSERT ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) != 0);\r
1141\r
1142 SkuHead = (SKU_HEAD *) ((UINT8 *)Database + (LocalTokenNumber & PCD_DATABASE_OFFSET_MASK));\r
1143\r
1144 return (SKU_ID *) ((UINT8 *)Database + SkuHead->SkuIdTableOffset);\r
1145 \r
1146}\r
1147\r
fc547e08 1148/**\r
1149 Get index of PCD entry in size table.\r
1150\r
1151 @param LocalTokenNumberTableIdx Index of this PCD in local token number table.\r
1152 @param Database Pointer to PCD database in PEI phase.\r
80408db0 1153\r
fc547e08 1154 @return index of PCD entry in size table.\r
80408db0 1155\r
fc547e08 1156**/\r
80408db0 1157UINTN\r
1158GetSizeTableIndex (\r
1159 IN UINTN LocalTokenNumberTableIdx,\r
1160 IN PEI_PCD_DATABASE *Database\r
1161 )\r
1162{\r
fc547e08 1163 UINTN Index;\r
419db80b 1164 UINTN SizeTableIdx;\r
80408db0 1165 UINTN LocalTokenNumber;\r
1166 SKU_ID *SkuIdTable;\r
1167 \r
1168 SizeTableIdx = 0;\r
1169\r
419db80b
BF
1170 for (Index = 0; Index < LocalTokenNumberTableIdx; Index++) {\r
1171 LocalTokenNumber = *((UINT32 *)((UINT8 *)Database + Database->LocalTokenNumberTableOffset) + Index);\r
80408db0 1172\r
1173 if ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER) {\r
1174 //\r
1175 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type \r
1176 // PCD entry.\r
1177 //\r
fc547e08 1178 if ((LocalTokenNumber & PCD_TYPE_VPD) != 0) {\r
80408db0 1179 //\r
419db80b 1180 // We have only two entry for VPD enabled PCD entry:\r
80408db0 1181 // 1) MAX Size.\r
419db80b
BF
1182 // 2) Current Size\r
1183 // Current size is equal to MAX size.\r
80408db0 1184 //\r
419db80b 1185 SizeTableIdx += 2;\r
80408db0 1186 } else {\r
1187 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0) {\r
1188 //\r
1189 // We have only two entry for Non-Sku enabled PCD entry:\r
1190 // 1) MAX SIZE\r
1191 // 2) Current Size\r
1192 //\r
1193 SizeTableIdx += 2;\r
1194 } else {\r
1195 //\r
1196 // We have these entry for SKU enabled PCD entry\r
1197 // 1) MAX SIZE\r
1198 // 2) Current Size for each SKU_ID (It is equal to MaxSku).\r
1199 //\r
fc547e08 1200 SkuIdTable = GetSkuIdArray (Index, Database);\r
80408db0 1201 SizeTableIdx += (UINTN)*SkuIdTable + 1;\r
1202 }\r
1203 }\r
1204 }\r
1205\r
1206 }\r
1207\r
1208 return SizeTableIdx;\r
1209}\r