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