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