]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/PCD/Pei/Service.c
Fix GCC build bug and add a debug library to dump load and unload commands into the...
[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
86714ccd 5Copyright (c) 2006 - 2009, 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
90 CallbackTable = CallbackTable + (TokenNumber * FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry));\r
91\r
92 Compare = Register? NULL: CallBackFunction;\r
93 Assign = Register? CallBackFunction: NULL;\r
94\r
95\r
96 for (Idx = 0; Idx < FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry); Idx++) {\r
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
129 SizeOfCallbackFnTable = PEI_LOCAL_TOKEN_NUMBER * sizeof (PCD_PPI_CALLBACK) * FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry);\r
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
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
f806dd27 366 if (!FeaturePcdGet(PcdPeiFullPcdDatabaseEnable)) {\r
80408db0 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
f806dd27 520 if (!FeaturePcdGet(PcdPeiFullPcdDatabaseEnable)) {\r
80408db0 521 return EFI_UNSUPPORTED;\r
522 }\r
523\r
524 TokenNumber = GetExPcdTokenNumber (Guid, ExTokenNumber);\r
86714ccd 525 if (TokenNumber == PCD_INVALID_TOKEN_NUMBER) {\r
526 return EFI_NOT_FOUND;\r
527 }\r
528 \r
80408db0 529 InvokeCallbackOnSet (ExTokenNumber, Guid, TokenNumber, Data, *Size);\r
530\r
531 return SetWorker (TokenNumber, Data, Size, PtrType);\r
532\r
533}\r
534\r
fc547e08 535/**\r
536 Wrapper function for get PCD value for dynamic-ex PCD.\r
80408db0 537\r
fc547e08 538 @param Guid Token space guid for dynamic-ex PCD.\r
539 @param ExTokenNumber Token number for dyanmic-ex PCD.\r
540 @param GetSize The size of dynamic-ex PCD value.\r
80408db0 541\r
fc547e08 542 @return PCD entry in PCD database.\r
80408db0 543\r
fc547e08 544**/\r
80408db0 545VOID *\r
546ExGetWorker (\r
547 IN CONST EFI_GUID *Guid,\r
548 IN UINTN ExTokenNumber,\r
549 IN UINTN GetSize\r
550 )\r
f806dd27 551{ \r
80408db0 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
d0965169 582 UINT8 *StringTable;\r
80408db0 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
d0965169 631 Name = (UINT16*)&StringTable[VariableHead->StringIndex];\r
80408db0 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
2ef9435a 649 StringTableIdx = * (UINT16*) ((UINT8 *) PeiPcdDb + Offset);\r
80408db0 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
86714ccd 711 return PCD_INVALID_TOKEN_NUMBER;\r
80408db0 712}\r
713\r
fc547e08 714/**\r
715 Get PCD database from GUID HOB in PEI phase.\r
80408db0 716\r
fc547e08 717 @return Pointer to PCD database.\r
80408db0 718\r
fc547e08 719**/\r
80408db0 720PEI_PCD_DATABASE *\r
721GetPcdDatabase (\r
722 VOID\r
723 )\r
724{\r
725 EFI_HOB_GUID_TYPE *GuidHob;\r
726\r
727 GuidHob = GetFirstGuidHob (&gPcdDataBaseHobGuid);\r
728 ASSERT (GuidHob != NULL);\r
729 \r
730 return (PEI_PCD_DATABASE *) GET_GUID_HOB_DATA (GuidHob);\r
731}\r
732\r
fc547e08 733/**\r
734 Get SKU ID tabble from PCD database.\r
735\r
736 @param LocalTokenNumberTableIdx Index of local token number in token number table.\r
737 @param Database PCD database.\r
80408db0 738\r
fc547e08 739 @return Pointer to SKU ID array table\r
80408db0 740\r
fc547e08 741**/\r
80408db0 742SKU_ID *\r
743GetSkuIdArray (\r
744 IN UINTN LocalTokenNumberTableIdx,\r
745 IN PEI_PCD_DATABASE *Database\r
746 )\r
747{\r
748 SKU_HEAD *SkuHead;\r
749 UINTN LocalTokenNumber;\r
750\r
751 LocalTokenNumber = Database->Init.LocalTokenNumberTable[LocalTokenNumberTableIdx];\r
752\r
753 ASSERT ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) != 0);\r
754\r
755 SkuHead = (SKU_HEAD *) ((UINT8 *)Database + (LocalTokenNumber & PCD_DATABASE_OFFSET_MASK));\r
756\r
757 return (SKU_ID *) ((UINT8 *)Database + SkuHead->SkuIdTableOffset);\r
758 \r
759}\r
760\r
fc547e08 761/**\r
762 Get index of PCD entry in size table.\r
763\r
764 @param LocalTokenNumberTableIdx Index of this PCD in local token number table.\r
765 @param Database Pointer to PCD database in PEI phase.\r
80408db0 766\r
fc547e08 767 @return index of PCD entry in size table.\r
80408db0 768\r
fc547e08 769**/\r
80408db0 770UINTN\r
771GetSizeTableIndex (\r
772 IN UINTN LocalTokenNumberTableIdx,\r
773 IN PEI_PCD_DATABASE *Database\r
774 )\r
775{\r
fc547e08 776 UINTN Index;\r
80408db0 777 UINTN SizeTableIdx;\r
778 UINTN LocalTokenNumber;\r
779 SKU_ID *SkuIdTable;\r
780 \r
781 SizeTableIdx = 0;\r
782\r
fc547e08 783 for (Index=0; Index<LocalTokenNumberTableIdx; Index++) {\r
784 LocalTokenNumber = Database->Init.LocalTokenNumberTable[Index];\r
80408db0 785\r
786 if ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER) {\r
787 //\r
788 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type \r
789 // PCD entry.\r
790 //\r
fc547e08 791 if ((LocalTokenNumber & PCD_TYPE_VPD) != 0) {\r
80408db0 792 //\r
793 // We have only one entry for VPD enabled PCD entry:\r
794 // 1) MAX Size.\r
795 // We consider current size is equal to MAX size.\r
796 //\r
797 SizeTableIdx++;\r
798 } else {\r
799 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0) {\r
800 //\r
801 // We have only two entry for Non-Sku enabled PCD entry:\r
802 // 1) MAX SIZE\r
803 // 2) Current Size\r
804 //\r
805 SizeTableIdx += 2;\r
806 } else {\r
807 //\r
808 // We have these entry for SKU enabled PCD entry\r
809 // 1) MAX SIZE\r
810 // 2) Current Size for each SKU_ID (It is equal to MaxSku).\r
811 //\r
fc547e08 812 SkuIdTable = GetSkuIdArray (Index, Database);\r
80408db0 813 SizeTableIdx += (UINTN)*SkuIdTable + 1;\r
814 }\r
815 }\r
816 }\r
817\r
818 }\r
819\r
820 return SizeTableIdx;\r
821}\r