]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/PCD/Pei/Service.c
Code scrub for PCD PEIM.
[mirror_edk2.git] / MdeModulePkg / Universal / PCD / Pei / Service.c
CommitLineData
80408db0 1/** @file\r
2Private functions used by PCD PEIM.\r
3\r
4Copyright (c) 2006, Intel Corporation\r
5All rights reserved. This program and the accompanying materials\r
6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13\r
14Module Name: Service.c\r
15\r
16**/\r
80408db0 17\r
18#include "Service.h"\r
19\r
20/**\r
21 The function registers the CallBackOnSet fucntion\r
22 according to TokenNumber and EFI_GUID space.\r
23\r
fc547e08 24 @param ExTokenNumber The token number.\r
80408db0 25 @param Guid The GUID space.\r
26 @param CallBackFunction The Callback function to be registered.\r
27 @param Register To register or unregister the callback function.\r
28\r
29 @retval EFI_SUCCESS If the Callback function is registered.\r
30 @retval EFI_NOT_FOUND If the PCD Entry is not found according to Token Number and GUID space.\r
31 @retval EFI_OUT_OF_RESOURCES If the callback function can't be registered because there is not free\r
32 slot left in the CallbackFnTable.\r
fc547e08 33**/\r
80408db0 34EFI_STATUS\r
35PeiRegisterCallBackWorker (\r
36 IN UINTN ExTokenNumber,\r
37 IN CONST EFI_GUID *Guid, OPTIONAL\r
38 IN PCD_PPI_CALLBACK CallBackFunction,\r
39 IN BOOLEAN Register\r
40)\r
41{\r
42 EFI_HOB_GUID_TYPE *GuidHob;\r
43 PCD_PPI_CALLBACK *CallbackTable;\r
44 PCD_PPI_CALLBACK Compare;\r
45 PCD_PPI_CALLBACK Assign;\r
46 UINT32 LocalTokenNumber;\r
47 UINTN TokenNumber;\r
48 UINTN Idx;\r
49\r
50 if (Guid == NULL) {\r
51 TokenNumber = ExTokenNumber;\r
52\r
53 //\r
54 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.\r
55 // We have to decrement TokenNumber by 1 to make it usable\r
56 // as the array index.\r
57 //\r
58 TokenNumber--;\r
59 ASSERT (TokenNumber + 1 < PEI_NEX_TOKEN_NUMBER + 1);\r
60 } else {\r
61 TokenNumber = GetExPcdTokenNumber (Guid, ExTokenNumber);\r
62\r
63 //\r
64 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.\r
65 // We have to decrement TokenNumber by 1 to make it usable\r
66 // as the array index.\r
67 //\r
68 TokenNumber--;\r
69 // EBC compiler is very choosy. It may report warning about comparison\r
70 // between UINTN and 0 . So we add 1 in each size of the \r
71 // comparison.\r
72 ASSERT (TokenNumber + 1 < PEI_LOCAL_TOKEN_NUMBER + 1);\r
73 }\r
74\r
75\r
76 LocalTokenNumber = GetPcdDatabase()->Init.LocalTokenNumberTable[TokenNumber];\r
77\r
78 //\r
79 // We don't support SET for HII and VPD type PCD entry in PEI phase.\r
80 // So we will assert if any register callback for such PCD entry.\r
81 //\r
82 ASSERT ((LocalTokenNumber & PCD_TYPE_HII) == 0);\r
83 ASSERT ((LocalTokenNumber & PCD_TYPE_VPD) == 0);\r
84\r
85 GuidHob = GetFirstGuidHob (&gPcdPeiCallbackFnTableHobGuid);\r
86 ASSERT (GuidHob != NULL);\r
87 \r
88 CallbackTable = GET_GUID_HOB_DATA (GuidHob);\r
89 CallbackTable = CallbackTable + (TokenNumber * FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry));\r
90\r
91 Compare = Register? NULL: CallBackFunction;\r
92 Assign = Register? CallBackFunction: NULL;\r
93\r
94\r
95 for (Idx = 0; Idx < FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry); Idx++) {\r
96 if (CallbackTable[Idx] == Compare) {\r
97 CallbackTable[Idx] = Assign;\r
98 return EFI_SUCCESS;\r
99 }\r
100 }\r
101\r
102 return Register? EFI_OUT_OF_RESOURCES : EFI_NOT_FOUND;\r
103\r
104}\r
105\r
80408db0 106/**\r
107 The function builds the PCD database.\r
fc547e08 108**/\r
80408db0 109VOID\r
110BuildPcdDatabase (\r
111 VOID\r
112 )\r
113{\r
114 PEI_PCD_DATABASE *Database;\r
115 VOID *CallbackFnTable;\r
116 UINTN SizeOfCallbackFnTable;\r
117 \r
118 Database = BuildGuidHob (&gPcdDataBaseHobGuid, sizeof (PEI_PCD_DATABASE));\r
119\r
120 ZeroMem (Database, sizeof (PEI_PCD_DATABASE));\r
121\r
122 //\r
123 // gPEIPcdDbInit is smaller than PEI_PCD_DATABASE\r
124 //\r
125 \r
126 CopyMem (&Database->Init, &gPEIPcdDbInit, sizeof (gPEIPcdDbInit));\r
127\r
128 SizeOfCallbackFnTable = PEI_LOCAL_TOKEN_NUMBER * sizeof (PCD_PPI_CALLBACK) * FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry);\r
129\r
130 CallbackFnTable = BuildGuidHob (&gPcdPeiCallbackFnTableHobGuid, SizeOfCallbackFnTable);\r
131 \r
132 ZeroMem (CallbackFnTable, SizeOfCallbackFnTable);\r
80408db0 133}\r
134\r
80408db0 135/**\r
136 The function is provided by PCD PEIM and PCD DXE driver to\r
137 do the work of reading a HII variable from variable service.\r
138\r
139 @param VariableGuid The Variable GUID.\r
140 @param VariableName The Variable Name.\r
141 @param VariableData The output data.\r
142 @param VariableSize The size of the variable.\r
143\r
144 @retval EFI_SUCCESS Operation successful.\r
145 @retval EFI_NOT_FOUND Variablel not found.\r
fc547e08 146**/\r
80408db0 147EFI_STATUS\r
148GetHiiVariable (\r
149 IN CONST EFI_GUID *VariableGuid,\r
150 IN UINT16 *VariableName,\r
151 OUT VOID **VariableData,\r
152 OUT UINTN *VariableSize\r
153 )\r
154{\r
155 UINTN Size;\r
156 EFI_STATUS Status;\r
157 VOID *Buffer;\r
97a079ed 158 EFI_PEI_READ_ONLY_VARIABLE2_PPI *VariablePpi;\r
80408db0 159\r
97a079ed 160 Status = PeiServicesLocatePpi (&gEfiPeiReadOnlyVariable2PpiGuid, 0, NULL, (VOID **) &VariablePpi);\r
80408db0 161 ASSERT_EFI_ERROR (Status);\r
162\r
163 Size = 0;\r
97a079ed
A
164 Status = VariablePpi->GetVariable (\r
165 VariablePpi,\r
80408db0 166 VariableName,\r
167 (EFI_GUID *) VariableGuid,\r
168 NULL,\r
169 &Size,\r
170 NULL\r
97a079ed 171 );\r
80408db0 172 if (Status == EFI_BUFFER_TOO_SMALL) {\r
173\r
174\r
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
fc547e08 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
298 GuidHob = GetFirstGuidHob (&gPcdPeiCallbackFnTableHobGuid);\r
299 ASSERT (GuidHob != NULL);\r
300 \r
301 CallbackTable = GET_GUID_HOB_DATA (GuidHob);\r
302\r
303 CallbackTable += (TokenNumber * FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry));\r
304\r
305 for (Idx = 0; Idx < FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry); Idx++) {\r
306 if (CallbackTable[Idx] != NULL) {\r
307 CallbackTable[Idx] (Guid,\r
308 (Guid == NULL)? TokenNumber: ExTokenNumber,\r
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
347 @retval EFI_NOT_FOUND If value type of PCD entry is intergrate, but not in\r
348 range of UINT8, UINT16, UINT32, UINT64\r
349 @retval EFI_NOT_FOUND Can not find the PCD type according to token number. \r
350**/\r
80408db0 351EFI_STATUS\r
352SetWorker (\r
353 IN UINTN TokenNumber,\r
fc547e08 354 IN VOID *Data,\r
80408db0 355 IN OUT UINTN *Size,\r
356 IN BOOLEAN PtrType\r
357 )\r
358{\r
359 UINT32 LocalTokenNumber;\r
360 PEI_PCD_DATABASE *PeiPcdDb;\r
361 UINT16 StringTableIdx;\r
362 UINTN Offset;\r
363 VOID *InternalData;\r
364 UINTN MaxSize;\r
365\r
366 if (!FeaturePcdGet(PcdPeiPcdDatabaseSetEnabled)) {\r
367 return EFI_UNSUPPORTED;\r
368 }\r
369 \r
370 //\r
371 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.\r
372 // We have to decrement TokenNumber by 1 to make it usable\r
373 // as the array index.\r
374 //\r
375 TokenNumber--;\r
376\r
377 // EBC compiler is very choosy. It may report warning about comparison\r
378 // between UINTN and 0 . So we add 1 in each size of the \r
379 // comparison.\r
380 ASSERT (TokenNumber + 1 < PEI_LOCAL_TOKEN_NUMBER + 1);\r
381 \r
382 PeiPcdDb = GetPcdDatabase ();\r
383\r
384 LocalTokenNumber = PeiPcdDb->Init.LocalTokenNumberTable[TokenNumber];\r
385\r
386 if (!PtrType) {\r
387 ASSERT (PeiPcdGetSize(TokenNumber + 1) == *Size);\r
388 }\r
389\r
390 //\r
391 // We only invoke the callback function for Dynamic Type PCD Entry.\r
392 // For Dynamic EX PCD entry, we have invoked the callback function for Dynamic EX\r
393 // type PCD entry in ExSetWorker.\r
394 //\r
395 if (TokenNumber + 1 < PEI_NEX_TOKEN_NUMBER + 1) {\r
396 InvokeCallbackOnSet (0, NULL, TokenNumber + 1, Data, *Size);\r
397 }\r
398\r
399 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == PCD_TYPE_SKU_ENABLED) {\r
400 if (PtrType) {\r
401 MaxSize = GetPtrTypeSize (TokenNumber, &MaxSize, PeiPcdDb);\r
402 } else {\r
403 MaxSize = *Size;\r
404 }\r
405 LocalTokenNumber = GetSkuEnabledTokenNumber (LocalTokenNumber & ~PCD_TYPE_SKU_ENABLED, MaxSize);\r
406 }\r
407\r
408 Offset = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK;\r
409 InternalData = (VOID *) ((UINT8 *) PeiPcdDb + Offset);\r
410 \r
411 switch (LocalTokenNumber & PCD_TYPE_ALL_SET) {\r
412 case PCD_TYPE_VPD:\r
413 case PCD_TYPE_HII:\r
414 {\r
415 ASSERT (FALSE);\r
416 return EFI_INVALID_PARAMETER;\r
417 }\r
418\r
419 case PCD_TYPE_STRING:\r
420 if (SetPtrTypeSize (TokenNumber, Size, PeiPcdDb)) {\r
421 StringTableIdx = *((UINT16 *)InternalData);\r
422 CopyMem (&PeiPcdDb->Init.StringTable[StringTableIdx], Data, *Size);\r
423 return EFI_SUCCESS;\r
424 } else {\r
425 return EFI_INVALID_PARAMETER;\r
426 }\r
427\r
428 case PCD_TYPE_DATA:\r
429 {\r
430 if (PtrType) {\r
431 if (SetPtrTypeSize (TokenNumber, Size, PeiPcdDb)) {\r
432 CopyMem (InternalData, Data, *Size);\r
433 return EFI_SUCCESS;\r
434 } else {\r
435 return EFI_INVALID_PARAMETER;\r
436 }\r
437 }\r
438\r
439 switch (*Size) {\r
440 case sizeof(UINT8):\r
441 *((UINT8 *) InternalData) = *((UINT8 *) Data);\r
442 return EFI_SUCCESS;\r
443\r
444 case sizeof(UINT16):\r
445 *((UINT16 *) InternalData) = *((UINT16 *) Data);\r
446 return EFI_SUCCESS;\r
447\r
448 case sizeof(UINT32):\r
449 *((UINT32 *) InternalData) = *((UINT32 *) Data);\r
450 return EFI_SUCCESS;\r
451\r
452 case sizeof(UINT64):\r
453 *((UINT64 *) InternalData) = *((UINT64 *) Data);\r
454 return EFI_SUCCESS;\r
455\r
456 default:\r
457 ASSERT (FALSE);\r
458 return EFI_NOT_FOUND;\r
459 }\r
460 }\r
461 \r
462 }\r
463\r
464 ASSERT (FALSE);\r
465 return EFI_NOT_FOUND;\r
466\r
467}\r
468\r
fc547e08 469/**\r
470 Wrapper function for set PCD value for non-Pointer type dynamic-ex PCD.\r
80408db0 471\r
fc547e08 472 @param ExTokenNumber Token number for dynamic-ex PCD.\r
473 @param Guid Token space guid for dynamic-ex PCD.\r
474 @param Data Value want to be set.\r
475 @param SetSize The size of value.\r
80408db0 476\r
fc547e08 477 @return status of ExSetWorker().\r
478\r
479**/\r
80408db0 480EFI_STATUS\r
481ExSetValueWorker (\r
482 IN UINTN ExTokenNumber,\r
483 IN CONST EFI_GUID *Guid,\r
484 IN VOID *Data,\r
485 IN UINTN Size\r
486 )\r
487{\r
488 return ExSetWorker (ExTokenNumber, Guid, Data, &Size, FALSE);\r
489}\r
490\r
fc547e08 491/**\r
492 Set value for a dynamic PCD entry.\r
493 \r
494 This routine find the local token number according to dynamic-ex PCD's token \r
495 space guid and token number firstly, and invoke callback function if this PCD\r
496 entry registered callback function. Finally, invoken general SetWorker to set\r
497 PCD value.\r
498 \r
499 @param ExTokenNumber Dynamic-ex PCD token number.\r
500 @param Guid Token space guid for dynamic-ex PCD.\r
501 @param Data PCD value want to be set\r
502 @param SetSize Size of value.\r
503 @param PtrType If TRUE, this PCD entry is pointer type.\r
504 If FALSE, this PCD entry is not pointer type.\r
80408db0 505\r
fc547e08 506 @return status of SetWorker().\r
80408db0 507\r
fc547e08 508**/\r
80408db0 509EFI_STATUS\r
510ExSetWorker (\r
511 IN UINTN ExTokenNumber,\r
512 IN CONST EFI_GUID *Guid,\r
513 IN VOID *Data,\r
514 IN OUT UINTN *Size,\r
515 IN BOOLEAN PtrType\r
516 )\r
517{\r
518 UINTN TokenNumber;\r
519\r
520 if (!FeaturePcdGet(PcdPeiPcdDatabaseSetEnabled)) {\r
521 return EFI_UNSUPPORTED;\r
522 }\r
523\r
524 TokenNumber = GetExPcdTokenNumber (Guid, ExTokenNumber);\r
525\r
526 InvokeCallbackOnSet (ExTokenNumber, Guid, TokenNumber, Data, *Size);\r
527\r
528 return SetWorker (TokenNumber, Data, Size, PtrType);\r
529\r
530}\r
531\r
fc547e08 532/**\r
533 Wrapper function for get PCD value for dynamic-ex PCD.\r
80408db0 534\r
fc547e08 535 @param Guid Token space guid for dynamic-ex PCD.\r
536 @param ExTokenNumber Token number for dyanmic-ex PCD.\r
537 @param GetSize The size of dynamic-ex PCD value.\r
80408db0 538\r
fc547e08 539 @return PCD entry in PCD database.\r
80408db0 540\r
fc547e08 541**/\r
80408db0 542VOID *\r
543ExGetWorker (\r
544 IN CONST EFI_GUID *Guid,\r
545 IN UINTN ExTokenNumber,\r
546 IN UINTN GetSize\r
547 )\r
548{\r
549 if (!FeaturePcdGet (PcdPeiPcdDatabaseExEnabled)) {\r
550 ASSERT (FALSE);\r
551 return 0;\r
552 }\r
553 \r
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
584 UINT16 *StringTable;\r
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
625 return (VOID *) (UINTN) (FixedPcdGet32(PcdVpdBaseAddress) + VpdHead->Offset);\r
626 }\r
627 \r
628 case PCD_TYPE_HII:\r
629 {\r
630 VariableHead = (VARIABLE_HEAD *) ((UINT8 *)PeiPcdDb + Offset);\r
631 \r
632 Guid = &(PeiPcdDb->Init.GuidTable[VariableHead->GuidTableIndex]);\r
633 Name = &StringTable[VariableHead->StringIndex];\r
634\r
635 Status = GetHiiVariable (Guid, Name, &Data, &DataSize);\r
636\r
637 if (Status == EFI_SUCCESS) {\r
638 return (VOID *) ((UINT8 *) Data + VariableHead->Offset);\r
639 } else {\r
640 //\r
641 // Return the default value specified by Platform Integrator \r
642 //\r
643 return (VOID *) ((UINT8 *) PeiPcdDb + VariableHead->DefaultValueOffset);\r
644 }\r
645 }\r
646\r
647 case PCD_TYPE_DATA:\r
648 return (VOID *) ((UINT8 *)PeiPcdDb + Offset);\r
649\r
650 case PCD_TYPE_STRING:\r
651 StringTableIdx = (UINT16) *((UINT8 *) PeiPcdDb + Offset);\r
652 return (VOID *) (&StringTable[StringTableIdx]);\r
653\r
654 default:\r
655 ASSERT (FALSE);\r
656 break;\r
657 \r
658 }\r
659\r
660 ASSERT (FALSE);\r
661 \r
662 return NULL;\r
663 \r
664}\r
665\r
fc547e08 666/**\r
667 Get local token number according to dynamic-ex PCD's {token space guid:token number}\r
668\r
669 A dynamic-ex type PCD, developer must provide pair of token space guid: token number\r
670 in DEC file. PCD database maintain a mapping table that translate pair of {token\r
671 space guid: token number} to local token number.\r
672 \r
673 @param Guid Token space guid for dynamic-ex PCD entry.\r
674 @param ExTokenNumber EDES_TODO: Add parameter description\r
80408db0 675\r
fc547e08 676 @return local token number for dynamic-ex PCD.\r
80408db0 677\r
fc547e08 678**/\r
80408db0 679UINTN \r
680GetExPcdTokenNumber (\r
681 IN CONST EFI_GUID *Guid,\r
682 IN UINTN ExTokenNumber\r
683 )\r
684{\r
fc547e08 685 UINT32 Index;\r
80408db0 686 DYNAMICEX_MAPPING *ExMap;\r
687 EFI_GUID *GuidTable;\r
688 EFI_GUID *MatchGuid;\r
689 UINTN MatchGuidIdx;\r
690 PEI_PCD_DATABASE *PeiPcdDb;\r
691\r
692 PeiPcdDb = GetPcdDatabase();\r
693 \r
694 ExMap = PeiPcdDb->Init.ExMapTable;\r
695 GuidTable = PeiPcdDb->Init.GuidTable;\r
696\r
697 MatchGuid = ScanGuid (GuidTable, sizeof(PeiPcdDb->Init.GuidTable), Guid);\r
698 //\r
699 // We need to ASSERT here. If GUID can't be found in GuidTable, this is a\r
700 // error in the BUILD system.\r
701 //\r
702 ASSERT (MatchGuid != NULL);\r
703 \r
704 MatchGuidIdx = MatchGuid - GuidTable;\r
705 \r
fc547e08 706 for (Index = 0; Index < PEI_EXMAPPING_TABLE_SIZE; Index++) {\r
707 if ((ExTokenNumber == ExMap[Index].ExTokenNumber) && \r
708 (MatchGuidIdx == ExMap[Index].ExGuidIndex)) {\r
709 return ExMap[Index].LocalTokenNumber;\r
80408db0 710 }\r
711 }\r
712 \r
713 ASSERT (FALSE);\r
714 \r
715 return 0;\r
716}\r
717\r
fc547e08 718/**\r
719 Get PCD database from GUID HOB in PEI phase.\r
80408db0 720\r
fc547e08 721 @return Pointer to PCD database.\r
80408db0 722\r
fc547e08 723**/\r
80408db0 724PEI_PCD_DATABASE *\r
725GetPcdDatabase (\r
726 VOID\r
727 )\r
728{\r
729 EFI_HOB_GUID_TYPE *GuidHob;\r
730\r
731 GuidHob = GetFirstGuidHob (&gPcdDataBaseHobGuid);\r
732 ASSERT (GuidHob != NULL);\r
733 \r
734 return (PEI_PCD_DATABASE *) GET_GUID_HOB_DATA (GuidHob);\r
735}\r
736\r
fc547e08 737/**\r
738 Get SKU ID tabble from PCD database.\r
739\r
740 @param LocalTokenNumberTableIdx Index of local token number in token number table.\r
741 @param Database PCD database.\r
80408db0 742\r
fc547e08 743 @return Pointer to SKU ID array table\r
80408db0 744\r
fc547e08 745**/\r
80408db0 746SKU_ID *\r
747GetSkuIdArray (\r
748 IN UINTN LocalTokenNumberTableIdx,\r
749 IN PEI_PCD_DATABASE *Database\r
750 )\r
751{\r
752 SKU_HEAD *SkuHead;\r
753 UINTN LocalTokenNumber;\r
754\r
755 LocalTokenNumber = Database->Init.LocalTokenNumberTable[LocalTokenNumberTableIdx];\r
756\r
757 ASSERT ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) != 0);\r
758\r
759 SkuHead = (SKU_HEAD *) ((UINT8 *)Database + (LocalTokenNumber & PCD_DATABASE_OFFSET_MASK));\r
760\r
761 return (SKU_ID *) ((UINT8 *)Database + SkuHead->SkuIdTableOffset);\r
762 \r
763}\r
764\r
fc547e08 765/**\r
766 Get index of PCD entry in size table.\r
767\r
768 @param LocalTokenNumberTableIdx Index of this PCD in local token number table.\r
769 @param Database Pointer to PCD database in PEI phase.\r
80408db0 770\r
fc547e08 771 @return index of PCD entry in size table.\r
80408db0 772\r
fc547e08 773**/\r
80408db0 774UINTN\r
775GetSizeTableIndex (\r
776 IN UINTN LocalTokenNumberTableIdx,\r
777 IN PEI_PCD_DATABASE *Database\r
778 )\r
779{\r
fc547e08 780 UINTN Index;\r
80408db0 781 UINTN SizeTableIdx;\r
782 UINTN LocalTokenNumber;\r
783 SKU_ID *SkuIdTable;\r
784 \r
785 SizeTableIdx = 0;\r
786\r
fc547e08 787 for (Index=0; Index<LocalTokenNumberTableIdx; Index++) {\r
788 LocalTokenNumber = Database->Init.LocalTokenNumberTable[Index];\r
80408db0 789\r
790 if ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER) {\r
791 //\r
792 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type \r
793 // PCD entry.\r
794 //\r
fc547e08 795 if ((LocalTokenNumber & PCD_TYPE_VPD) != 0) {\r
80408db0 796 //\r
797 // We have only one entry for VPD enabled PCD entry:\r
798 // 1) MAX Size.\r
799 // We consider current size is equal to MAX size.\r
800 //\r
801 SizeTableIdx++;\r
802 } else {\r
803 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0) {\r
804 //\r
805 // We have only two entry for Non-Sku enabled PCD entry:\r
806 // 1) MAX SIZE\r
807 // 2) Current Size\r
808 //\r
809 SizeTableIdx += 2;\r
810 } else {\r
811 //\r
812 // We have these entry for SKU enabled PCD entry\r
813 // 1) MAX SIZE\r
814 // 2) Current Size for each SKU_ID (It is equal to MaxSku).\r
815 //\r
fc547e08 816 SkuIdTable = GetSkuIdArray (Index, Database);\r
80408db0 817 SizeTableIdx += (UINTN)*SkuIdTable + 1;\r
818 }\r
819 }\r
820 }\r
821\r
822 }\r
823\r
824 return SizeTableIdx;\r
825}\r