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