]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/PCD/Dxe/Service.c
Update HiiDataBase to make sure that the installed StringPackages contains the same...
[mirror_edk2.git] / MdeModulePkg / Universal / PCD / Dxe / Service.c
CommitLineData
80408db0 1/** @file\r
2ab6330e 2 Help functions used by PCD DXE driver.\r
80408db0 3\r
149fb6d6 4Copyright (c) 2006 - 2010, Intel Corporation\r
80408db0 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
80408db0 13**/\r
80408db0 14\r
15#include "Service.h"\r
16\r
b07a5b68 17PCD_DATABASE *mPcdDatabase;\r
80408db0 18\r
b07a5b68 19LIST_ENTRY *mCallbackFnTable;\r
80408db0 20\r
2ab6330e 21/**\r
22 Get the PCD entry pointer in PCD database.\r
23 \r
24 This routine will visit PCD database to find the PCD entry according to given\r
25 token number. The given token number is autogened by build tools and it will be \r
26 translated to local token number. Local token number contains PCD's type and \r
27 offset of PCD entry in PCD database.\r
28\r
29 @param TokenNumber Token's number, it is autogened by build tools\r
30 @param GetSize The size of token's value\r
31\r
32 @return PCD entry pointer in PCD database\r
33\r
34**/\r
80408db0 35VOID *\r
36GetWorker (\r
2ab6330e 37 IN UINTN TokenNumber,\r
38 IN UINTN GetSize\r
80408db0 39 )\r
40{\r
41 UINT32 *LocalTokenNumberTable;\r
42 EFI_GUID *GuidTable;\r
d0965169 43 UINT8 *StringTable;\r
80408db0 44 EFI_GUID *Guid;\r
45 UINT16 *Name;\r
46 VARIABLE_HEAD *VariableHead;\r
47 UINT8 *VaraiableDefaultBuffer;\r
48 UINT8 *Data;\r
49 VPD_HEAD *VpdHead;\r
50 UINT8 *PcdDb;\r
51 VOID *RetPtr;\r
52 UINTN MaxSize;\r
53 UINTN TmpTokenNumber;\r
54 UINTN DataSize;\r
55 EFI_STATUS Status;\r
56 UINT32 LocalTokenNumber;\r
57 UINT32 Offset;\r
58 UINT16 StringTableIdx; \r
59 BOOLEAN IsPeiDb;\r
60\r
61 //\r
62 // Aquire lock to prevent reentrance from TPL_CALLBACK level\r
63 //\r
64 EfiAcquireLock (&mPcdDatabaseLock);\r
65\r
66 RetPtr = NULL;\r
67 //\r
68 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.\r
69 // We have to decrement TokenNumber by 1 to make it usable\r
70 // as the array index.\r
71 //\r
72 TokenNumber--;\r
73\r
74 TmpTokenNumber = TokenNumber;\r
75 \r
76 //\r
77 // PCD_TOTAL_TOKEN_NUMBER is a auto-generated constant.\r
78 // It could be zero. EBC compiler is very choosy. It may\r
79 // report warning. So we add 1 in each size of the \r
80 // comparison.\r
81 //\r
82 ASSERT (TokenNumber + 1 < PCD_TOTAL_TOKEN_NUMBER + 1);\r
83\r
84 ASSERT ((GetSize == DxePcdGetSize (TokenNumber + 1)) || (GetSize == 0));\r
85\r
86 // EBC compiler is very choosy. It may report warning about comparison\r
87 // between UINTN and 0 . So we add 1 in each size of the \r
88 // comparison.\r
89 IsPeiDb = (BOOLEAN) ((TokenNumber + 1 < PEI_LOCAL_TOKEN_NUMBER + 1) ? TRUE : FALSE);\r
90\r
91 LocalTokenNumberTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.LocalTokenNumberTable : \r
92 mPcdDatabase->DxeDb.Init.LocalTokenNumberTable;\r
93\r
94 TokenNumber = IsPeiDb ? TokenNumber :\r
95 TokenNumber - PEI_LOCAL_TOKEN_NUMBER;\r
96\r
97 LocalTokenNumber = LocalTokenNumberTable[TokenNumber];\r
98 \r
99 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == PCD_TYPE_SKU_ENABLED) {\r
100 if (GetSize == 0) {\r
101 GetPtrTypeSize (TmpTokenNumber, &MaxSize);\r
102 } else {\r
103 MaxSize = GetSize;\r
104 }\r
105 LocalTokenNumber = GetSkuEnabledTokenNumber (LocalTokenNumber & ~PCD_TYPE_SKU_ENABLED, MaxSize, IsPeiDb);\r
106 }\r
107\r
108 PcdDb = IsPeiDb ? ((UINT8 *) &mPcdDatabase->PeiDb) : ((UINT8 *) &mPcdDatabase->DxeDb);\r
309e3122 109 \r
110 if (IsPeiDb) {\r
d0965169 111 StringTable = (UINT8 *) (&mPcdDatabase->PeiDb.Init.StringTable[0]);\r
309e3122 112 } else {\r
d0965169 113 StringTable = (UINT8 *) (&mPcdDatabase->DxeDb.Init.StringTable[0]);\r
309e3122 114 }\r
115 \r
80408db0 116 \r
117 Offset = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK;\r
118 \r
119 switch (LocalTokenNumber & PCD_TYPE_ALL_SET) {\r
120 case PCD_TYPE_VPD:\r
121 VpdHead = (VPD_HEAD *) ((UINT8 *) PcdDb + Offset);\r
188e4e84 122 RetPtr = (VOID *) (UINTN) (PcdGet32 (PcdVpdBaseAddress) + VpdHead->Offset);\r
80408db0 123 break;\r
124 \r
125 case PCD_TYPE_HII:\r
309e3122 126 if (IsPeiDb) {\r
127 GuidTable = (EFI_GUID *) (&mPcdDatabase->PeiDb.Init.GuidTable[0]);\r
128 } else {\r
129 GuidTable = (EFI_GUID *) (&mPcdDatabase->DxeDb.Init.GuidTable[0]);\r
130 }\r
80408db0 131 \r
132 VariableHead = (VARIABLE_HEAD *) (PcdDb + Offset);\r
133 \r
1fef733c 134 Guid = GuidTable + VariableHead->GuidTableIndex;\r
d0965169 135 Name = (UINT16*)(StringTable + VariableHead->StringIndex);\r
80408db0 136 VaraiableDefaultBuffer = (UINT8 *) PcdDb + VariableHead->DefaultValueOffset;\r
137\r
138 Status = GetHiiVariable (Guid, Name, &Data, &DataSize);\r
139 if (Status == EFI_SUCCESS) {\r
140 if (GetSize == 0) {\r
141 //\r
142 // It is a pointer type. So get the MaxSize reserved for\r
143 // this PCD entry.\r
144 //\r
145 GetPtrTypeSize (TmpTokenNumber, &GetSize);\r
146 }\r
147 CopyMem (VaraiableDefaultBuffer, Data + VariableHead->Offset, GetSize);\r
148 FreePool (Data);\r
149 }\r
150 //\r
151 // If the operation is successful, we copy the data\r
152 // to the default value buffer in the PCD Database.\r
153 // So that we can free the Data allocated in GetHiiVariable.\r
154 //\r
155 //\r
156 // If the operation is not successful, \r
157 // Return 1) either the default value specified by Platform Integrator \r
158 // 2) Or the value Set by a PCD set operation.\r
159 //\r
160 RetPtr = (VOID *) VaraiableDefaultBuffer;\r
161 break;\r
162\r
163 case PCD_TYPE_STRING:\r
2ef9435a 164 StringTableIdx = *(UINT16*)((UINT8 *) PcdDb + Offset);\r
1fef733c 165 RetPtr = (VOID *) (StringTable + StringTableIdx);\r
80408db0 166 break;\r
167\r
168 case PCD_TYPE_DATA:\r
169 RetPtr = (VOID *) ((UINT8 *) PcdDb + Offset);\r
170 break;\r
171\r
172 default:\r
173 ASSERT (FALSE);\r
174 break;\r
175 \r
176 }\r
177\r
178 EfiReleaseLock (&mPcdDatabaseLock);\r
179 \r
180 return RetPtr;\r
181 \r
182}\r
183\r
2ab6330e 184/**\r
185 Register the callback function for a PCD entry.\r
186\r
187 This routine will register a callback function to a PCD entry by given token number\r
188 and token space guid.\r
189 \r
190 @param TokenNumber PCD token's number, it is autogened by build tools.\r
191 @param Guid PCD token space's guid, \r
192 if not NULL, this PCD is dynamicEx type PCD.\r
193 @param CallBackFunction Callback function pointer\r
80408db0 194\r
2ab6330e 195 @return EFI_SUCCESS Always success for registering callback function.\r
80408db0 196\r
2ab6330e 197**/\r
80408db0 198EFI_STATUS\r
199DxeRegisterCallBackWorker (\r
200 IN UINTN TokenNumber,\r
2ab6330e 201 IN CONST EFI_GUID *Guid, OPTIONAL\r
80408db0 202 IN PCD_PROTOCOL_CALLBACK CallBackFunction\r
203)\r
204{\r
205 CALLBACK_FN_ENTRY *FnTableEntry;\r
206 LIST_ENTRY *ListHead;\r
207 LIST_ENTRY *ListNode;\r
208\r
209 if (Guid != NULL) {\r
210 TokenNumber = GetExPcdTokenNumber (Guid, (UINT32) TokenNumber);\r
211 }\r
212\r
213 //\r
214 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.\r
215 // We have to decrement TokenNumber by 1 to make it usable\r
b07a5b68 216 // as the array index of mCallbackFnTable[].\r
80408db0 217 //\r
b07a5b68 218 ListHead = &mCallbackFnTable[TokenNumber - 1];\r
80408db0 219 ListNode = GetFirstNode (ListHead);\r
220\r
221 while (ListNode != ListHead) {\r
222 FnTableEntry = CR_FNENTRY_FROM_LISTNODE(ListNode, CALLBACK_FN_ENTRY, Node);\r
223\r
224 if (FnTableEntry->CallbackFn == CallBackFunction) {\r
225 //\r
226 // We only allow a Callback function to be register once\r
227 // for a TokenNumber. So just return EFI_SUCCESS\r
228 //\r
229 return EFI_SUCCESS;\r
230 }\r
231 ListNode = GetNextNode (ListHead, ListNode);\r
232 }\r
233\r
234 FnTableEntry = AllocatePool (sizeof(CALLBACK_FN_ENTRY));\r
235 ASSERT (FnTableEntry != NULL);\r
236\r
237 FnTableEntry->CallbackFn = CallBackFunction;\r
238 InsertTailList (ListHead, &FnTableEntry->Node);\r
239 \r
240 return EFI_SUCCESS;\r
241}\r
242\r
2ab6330e 243/**\r
244 UnRegister the callback function for a PCD entry.\r
80408db0 245\r
2ab6330e 246 This routine will unregister a callback function to a PCD entry by given token number\r
247 and token space guid.\r
80408db0 248\r
2ab6330e 249 @param TokenNumber PCD token's number, it is autogened by build tools.\r
250 @param Guid PCD token space's guid.\r
251 if not NULL, this PCD is dynamicEx type PCD.\r
252 @param CallBackFunction Callback function pointer\r
80408db0 253\r
2ab6330e 254 @retval EFI_SUCCESS Callback function is success to be unregister.\r
255 @retval EFI_INVALID_PARAMETER Can not find the PCD entry by given token number.\r
256**/\r
80408db0 257EFI_STATUS\r
258DxeUnRegisterCallBackWorker (\r
259 IN UINTN TokenNumber,\r
2ab6330e 260 IN CONST EFI_GUID *Guid, OPTIONAL\r
80408db0 261 IN PCD_PROTOCOL_CALLBACK CallBackFunction\r
262)\r
263{\r
264 CALLBACK_FN_ENTRY *FnTableEntry;\r
265 LIST_ENTRY *ListHead;\r
266 LIST_ENTRY *ListNode;\r
267\r
268 if (Guid != NULL) {\r
269 TokenNumber = GetExPcdTokenNumber (Guid, (UINT32) TokenNumber);\r
270 }\r
271\r
272 //\r
273 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.\r
274 // We have to decrement TokenNumber by 1 to make it usable\r
b07a5b68 275 // as the array index of mCallbackFnTable[].\r
80408db0 276 //\r
b07a5b68 277 ListHead = &mCallbackFnTable[TokenNumber - 1];\r
80408db0 278 ListNode = GetFirstNode (ListHead);\r
279\r
280 while (ListNode != ListHead) {\r
281 FnTableEntry = CR_FNENTRY_FROM_LISTNODE(ListNode, CALLBACK_FN_ENTRY, Node);\r
282\r
283 if (FnTableEntry->CallbackFn == CallBackFunction) {\r
284 //\r
285 // We only allow a Callback function to be register once\r
286 // for a TokenNumber. So we can safely remove the Node from\r
287 // the Link List and return EFI_SUCCESS.\r
288 //\r
289 RemoveEntryList (ListNode);\r
290 FreePool (FnTableEntry);\r
291 \r
292 return EFI_SUCCESS;\r
293 }\r
294 ListNode = GetNextNode (ListHead, ListNode);\r
295 }\r
296\r
297 return EFI_INVALID_PARAMETER;\r
298}\r
299\r
2ab6330e 300/**\r
301 Get next token number in given token space.\r
302 \r
303 This routine is used for dynamicEx type PCD. It will firstly scan token space\r
304 table to get token space according to given token space guid. Then scan given \r
305 token number in found token space, if found, then return next token number in \r
306 this token space.\r
307\r
308 @param Guid Token space guid. Next token number will be scaned in \r
309 this token space.\r
310 @param TokenNumber Token number. \r
311 If PCD_INVALID_TOKEN_NUMBER, return first token number in \r
312 token space table.\r
313 If not PCD_INVALID_TOKEN_NUMBER, return next token number\r
314 in token space table.\r
315 @param GuidTable Token space guid table. It will be used for scan token space\r
316 by given token space guid.\r
317 @param SizeOfGuidTable The size of guid table.\r
318 @param ExMapTable DynamicEx token number mapping table.\r
319 @param SizeOfExMapTable The size of dynamicEx token number mapping table.\r
320\r
321 @retval EFI_NOT_FOUND Can not given token space or token number.\r
322 @retval EFI_SUCCESS Success to get next token number.\r
80408db0 323\r
2ab6330e 324**/\r
80408db0 325EFI_STATUS\r
326ExGetNextTokeNumber (\r
327 IN CONST EFI_GUID *Guid,\r
328 IN OUT UINTN *TokenNumber,\r
329 IN EFI_GUID *GuidTable,\r
330 IN UINTN SizeOfGuidTable,\r
331 IN DYNAMICEX_MAPPING *ExMapTable,\r
332 IN UINTN SizeOfExMapTable\r
333 )\r
334{\r
335 EFI_GUID *MatchGuid;\r
2ab6330e 336 UINTN Index;\r
80408db0 337 UINTN GuidTableIdx;\r
338 BOOLEAN Found;\r
339\r
2ab6330e 340 //\r
341 // Scan token space guid \r
342 // \r
80408db0 343 MatchGuid = ScanGuid (GuidTable, SizeOfGuidTable, Guid);\r
344 if (MatchGuid == NULL) {\r
345 return EFI_NOT_FOUND;\r
346 }\r
347\r
2ab6330e 348 //\r
349 // Find the token space table in dynamicEx mapping table.\r
350 //\r
80408db0 351 Found = FALSE;\r
352 GuidTableIdx = MatchGuid - GuidTable;\r
2ab6330e 353 for (Index = 0; Index < SizeOfExMapTable; Index++) {\r
354 if (ExMapTable[Index].ExGuidIndex == GuidTableIdx) {\r
80408db0 355 Found = TRUE;\r
356 break;\r
357 }\r
358 }\r
359\r
360 if (Found) {\r
2ab6330e 361 //\r
362 // If given token number is PCD_INVALID_TOKEN_NUMBER, then return the first\r
363 // token number in found token space.\r
364 //\r
80408db0 365 if (*TokenNumber == PCD_INVALID_TOKEN_NUMBER) {\r
2ab6330e 366 *TokenNumber = ExMapTable[Index].ExTokenNumber;\r
80408db0 367 return EFI_SUCCESS;\r
368 }\r
369\r
2ab6330e 370 for ( ; Index < SizeOfExMapTable; Index++) {\r
371 if (ExMapTable[Index].ExTokenNumber == *TokenNumber) {\r
372 Index ++;\r
373 if (Index == SizeOfExMapTable) {\r
80408db0 374 //\r
375 // Exceed the length of ExMap Table\r
376 //\r
377 *TokenNumber = PCD_INVALID_TOKEN_NUMBER;\r
378 return EFI_SUCCESS;\r
2ab6330e 379 } else if (ExMapTable[Index].ExGuidIndex == GuidTableIdx) {\r
80408db0 380 //\r
381 // Found the next match\r
382 //\r
2ab6330e 383 *TokenNumber = ExMapTable[Index].ExTokenNumber;\r
80408db0 384 return EFI_SUCCESS;\r
385 } else {\r
386 //\r
387 // Guid has been changed. It is the next Token Space Guid.\r
388 // We should flag no more TokenNumber.\r
389 //\r
390 *TokenNumber = PCD_INVALID_TOKEN_NUMBER;\r
391 return EFI_SUCCESS;\r
392 }\r
393 }\r
394 }\r
395 }\r
396 \r
397 return EFI_NOT_FOUND;\r
398}\r
80408db0 399\r
400\r
2ab6330e 401/**\r
402 Initialize the PCD database in DXE phase.\r
403 \r
404 PCD database in DXE phase also contains PCD database in PEI phase which is copied\r
405 from GUID Hob.\r
80408db0 406\r
2ab6330e 407**/\r
80408db0 408VOID\r
409BuildPcdDxeDataBase (\r
410 VOID\r
411 )\r
412{\r
413 PEI_PCD_DATABASE *PeiDatabase;\r
414 EFI_HOB_GUID_TYPE *GuidHob;\r
2ab6330e 415 UINTN Index;\r
80408db0 416\r
417 mPcdDatabase = AllocateZeroPool (sizeof(PCD_DATABASE));\r
418 ASSERT (mPcdDatabase != NULL);\r
419\r
420 GuidHob = GetFirstGuidHob (&gPcdDataBaseHobGuid);\r
421 if (GuidHob != NULL) {\r
422\r
423 //\r
424 // We will copy over the PEI phase's PCD Database.\r
425 // \r
426 // If no PEIMs use dynamic Pcd Entry, the Pcd Service PEIM\r
427 // should not be included at all. So the GuidHob could\r
428 // be NULL. If it is NULL, we just copy over the DXE Default\r
429 // Value to PCD Database.\r
430 //\r
431 \r
432 PeiDatabase = (PEI_PCD_DATABASE *) GET_GUID_HOB_DATA (GuidHob);\r
433 //\r
434 // Copy PCD Entries refereneced in PEI phase to PCD DATABASE\r
435 //\r
436 CopyMem (&mPcdDatabase->PeiDb, PeiDatabase, sizeof (PEI_PCD_DATABASE));\r
437 }\r
438\r
439 //\r
440 // Copy PCD Entries with default value to PCD DATABASE\r
441 //\r
442 CopyMem (&mPcdDatabase->DxeDb.Init, &gDXEPcdDbInit, sizeof(DXE_PCD_DATABASE_INIT));\r
443\r
444\r
445 //\r
446 // Initialized the Callback Function Table\r
447 //\r
448\r
449 mCallbackFnTable = AllocateZeroPool (PCD_TOTAL_TOKEN_NUMBER * sizeof (LIST_ENTRY));\r
3fd8027e 450 ASSERT(mCallbackFnTable != NULL);\r
80408db0 451 \r
452 // EBC compiler is very choosy. It may report warning about comparison\r
453 // between UINTN and 0 . So we add 1 in each size of the \r
454 // comparison.\r
2ab6330e 455 for (Index = 0; Index + 1 < PCD_TOTAL_TOKEN_NUMBER + 1; Index++) {\r
456 InitializeListHead (&mCallbackFnTable[Index]);\r
80408db0 457 }\r
80408db0 458}\r
459\r
2ab6330e 460/**\r
461 Get Variable which contains HII type PCD entry.\r
80408db0 462\r
2ab6330e 463 @param VariableGuid Variable's guid\r
464 @param VariableName Variable's unicode name string\r
465 @param VariableData Variable's data pointer, \r
466 @param VariableSize Variable's size.\r
80408db0 467\r
2ab6330e 468 @return the status of gRT->GetVariable\r
469**/\r
80408db0 470EFI_STATUS\r
471GetHiiVariable (\r
472 IN EFI_GUID *VariableGuid,\r
473 IN UINT16 *VariableName,\r
474 OUT UINT8 **VariableData,\r
475 OUT UINTN *VariableSize\r
476 )\r
477{\r
478 UINTN Size;\r
479 EFI_STATUS Status;\r
480 UINT8 *Buffer;\r
481\r
482 Size = 0;\r
483 Buffer = NULL;\r
484 \r
2ab6330e 485 //\r
486 // Firstly get the real size of HII variable\r
487 //\r
80408db0 488 Status = gRT->GetVariable (\r
489 (UINT16 *)VariableName,\r
490 VariableGuid,\r
491 NULL,\r
492 &Size,\r
493 Buffer\r
494 );\r
495 \r
2ab6330e 496 //\r
497 // Allocate buffer to hold whole variable data according to variable size.\r
498 //\r
80408db0 499 if (Status == EFI_BUFFER_TOO_SMALL) {\r
500 Buffer = (UINT8 *) AllocatePool (Size);\r
501\r
502 ASSERT (Buffer != NULL);\r
503\r
504 Status = gRT->GetVariable (\r
505 VariableName,\r
506 VariableGuid,\r
507 NULL,\r
508 &Size,\r
509 Buffer\r
510 );\r
511\r
512 ASSERT (Status == EFI_SUCCESS);\r
513 *VariableData = Buffer;\r
514 *VariableSize = Size;\r
515 }\r
516\r
517 return Status;\r
518}\r
519\r
2ab6330e 520/**\r
521 Find the local token number according to system SKU ID.\r
522\r
523 @param LocalTokenNumber PCD token number\r
524 @param Size The size of PCD entry.\r
525 @param IsPeiDb If TRUE, the PCD entry is initialized in PEI phase.\r
526 If False, the PCD entry is initialized in DXE phase.\r
527\r
528 @return Token number according to system SKU ID.\r
80408db0 529\r
2ab6330e 530**/\r
80408db0 531UINT32\r
532GetSkuEnabledTokenNumber (\r
533 UINT32 LocalTokenNumber,\r
534 UINTN Size,\r
535 BOOLEAN IsPeiDb\r
536 ) \r
537{\r
538 SKU_HEAD *SkuHead;\r
539 SKU_ID *SkuIdTable;\r
2ab6330e 540 INTN Index;\r
80408db0 541 UINT8 *Value;\r
542 SKU_ID *PhaseSkuIdTable;\r
543 UINT8 *PcdDb;\r
544\r
545 ASSERT ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0);\r
546\r
547 PcdDb = IsPeiDb ? (UINT8 *) &mPcdDatabase->PeiDb : (UINT8 *) &mPcdDatabase->DxeDb;\r
548\r
549 SkuHead = (SKU_HEAD *) (PcdDb + (LocalTokenNumber & PCD_DATABASE_OFFSET_MASK));\r
550 Value = (UINT8 *) (PcdDb + SkuHead->SkuDataStartOffset); \r
551\r
552 PhaseSkuIdTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.SkuIdTable :\r
553 mPcdDatabase->DxeDb.Init.SkuIdTable;\r
554 \r
555 SkuIdTable = &PhaseSkuIdTable[SkuHead->SkuIdTableOffset];\r
556 \r
2ab6330e 557 //\r
558 // Find the current system's SKU ID entry in SKU ID table.\r
559 //\r
560 for (Index = 0; Index < SkuIdTable[0]; Index++) {\r
561 if (mPcdDatabase->PeiDb.Init.SystemSkuId == SkuIdTable[Index + 1]) {\r
80408db0 562 break;\r
563 }\r
564 }\r
2ab6330e 565 ASSERT (Index < SkuIdTable[0]);\r
80408db0 566\r
567 switch (LocalTokenNumber & PCD_TYPE_ALL_SET) {\r
568 case PCD_TYPE_VPD:\r
2ab6330e 569 Value = (UINT8 *) &(((VPD_HEAD *) Value)[Index]);\r
80408db0 570 return (UINT32) ((Value - PcdDb) | PCD_TYPE_VPD);\r
571\r
572 case PCD_TYPE_HII:\r
2ab6330e 573 Value = (UINT8 *) &(((VARIABLE_HEAD *) Value)[Index]);\r
80408db0 574 return (UINT32) ((Value - PcdDb) | PCD_TYPE_HII);\r
575\r
576 case PCD_TYPE_STRING:\r
2ab6330e 577 Value = (UINT8 *) &(((STRING_HEAD *) Value)[Index]);\r
80408db0 578 return (UINT32) ((Value - PcdDb) | PCD_TYPE_STRING);\r
579 \r
580 case PCD_TYPE_DATA:\r
2ab6330e 581 Value += Size * Index;\r
80408db0 582 return (UINT32) (Value - PcdDb);\r
583\r
584 default:\r
585 ASSERT (FALSE);\r
586 }\r
587\r
588 ASSERT (FALSE);\r
589\r
590 return 0;\r
591 \r
592}\r
593\r
2ab6330e 594/**\r
595 Invoke the callback function when dynamic PCD entry was set, if this PCD entry \r
596 has registered callback function.\r
80408db0 597\r
2ab6330e 598 @param ExTokenNumber DynamicEx PCD's token number, if this PCD entry is dyanmicEx\r
599 type PCD.\r
600 @param Guid DynamicEx PCD's guid, if this PCD entry is dynamicEx type\r
601 PCD.\r
602 @param TokenNumber PCD token number generated by build tools.\r
603 @param Data Value want to be set for this PCD entry\r
604 @param Size The size of value\r
80408db0 605\r
2ab6330e 606**/\r
80408db0 607VOID\r
608InvokeCallbackOnSet (\r
609 UINT32 ExTokenNumber,\r
610 CONST EFI_GUID *Guid, OPTIONAL\r
611 UINTN TokenNumber,\r
612 VOID *Data,\r
613 UINTN Size\r
614 )\r
615{\r
616 CALLBACK_FN_ENTRY *FnTableEntry;\r
617 LIST_ENTRY *ListHead;\r
618 LIST_ENTRY *ListNode;\r
619\r
620 //\r
621 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.\r
622 // We have to decrement TokenNumber by 1 to make it usable\r
b07a5b68 623 // as the array index of mCallbackFnTable[].\r
80408db0 624 //\r
b07a5b68 625 ListHead = &mCallbackFnTable[TokenNumber - 1];\r
80408db0 626 ListNode = GetFirstNode (ListHead);\r
627\r
628 while (ListNode != ListHead) {\r
b07a5b68 629 FnTableEntry = CR_FNENTRY_FROM_LISTNODE (ListNode, CALLBACK_FN_ENTRY, Node);\r
80408db0 630\r
631 FnTableEntry->CallbackFn(Guid, \r
632 (Guid == NULL) ? TokenNumber : ExTokenNumber,\r
633 Data,\r
634 Size);\r
635 \r
636 ListNode = GetNextNode (ListHead, ListNode);\r
637 }\r
638 \r
639 return;\r
640}\r
641\r
642\r
2ab6330e 643/**\r
644 Wrapper function for setting non-pointer type value for a PCD entry.\r
645\r
646 @param TokenNumber Pcd token number autogenerated by build tools.\r
647 @param Data Value want to be set for PCD entry\r
648 @param Size Size of value.\r
649\r
650 @return status of SetWorker.\r
651\r
652**/\r
80408db0 653EFI_STATUS\r
654SetValueWorker (\r
655 IN UINTN TokenNumber,\r
656 IN VOID *Data,\r
657 IN UINTN Size\r
658 )\r
659{\r
660 return SetWorker (TokenNumber, Data, &Size, FALSE);\r
661}\r
662\r
663\r
2ab6330e 664/**\r
665 Set value for an PCD entry\r
666\r
667 @param TokenNumber Pcd token number autogenerated by build tools.\r
668 @param Data Value want to be set for PCD entry\r
669 @param Size Size of value.\r
670 @param PtrType If TRUE, the type of PCD entry's value is Pointer.\r
671 If False, the type of PCD entry's value is not Pointer.\r
672\r
673 @retval EFI_INVALID_PARAMETER If this PCD type is VPD, VPD PCD can not be set.\r
674 @retval EFI_INVALID_PARAMETER If Size can not be set to size table.\r
149fb6d6 675 @retval EFI_INVALID_PARAMETER If Size of non-Ptr type PCD does not match the size information in PCD database. \r
2ab6330e 676 @retval EFI_NOT_FOUND If value type of PCD entry is intergrate, but not in\r
677 range of UINT8, UINT16, UINT32, UINT64\r
678 @retval EFI_NOT_FOUND Can not find the PCD type according to token number. \r
679**/\r
80408db0 680EFI_STATUS\r
681SetWorker (\r
682 IN UINTN TokenNumber,\r
683 IN VOID *Data,\r
684 IN OUT UINTN *Size,\r
685 IN BOOLEAN PtrType\r
686 )\r
687{\r
688 UINT32 *LocalTokenNumberTable;\r
689 BOOLEAN IsPeiDb;\r
690 UINT32 LocalTokenNumber;\r
691 EFI_GUID *GuidTable;\r
d0965169 692 UINT8 *StringTable;\r
80408db0 693 EFI_GUID *Guid;\r
694 UINT16 *Name;\r
695 UINTN VariableOffset;\r
696 VOID *InternalData;\r
697 VARIABLE_HEAD *VariableHead;\r
698 UINTN Offset;\r
699 UINT8 *PcdDb;\r
700 EFI_STATUS Status;\r
701 UINTN MaxSize;\r
702 UINTN TmpTokenNumber;\r
703\r
80408db0 704 //\r
705 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.\r
706 // We have to decrement TokenNumber by 1 to make it usable\r
707 // as the array index.\r
708 //\r
709 TokenNumber--;\r
710\r
711 TmpTokenNumber = TokenNumber;\r
712 \r
2ab6330e 713 //\r
80408db0 714 // EBC compiler is very choosy. It may report warning about comparison\r
715 // between UINTN and 0 . So we add 1 in each size of the \r
716 // comparison.\r
2ab6330e 717 //\r
80408db0 718 ASSERT (TokenNumber + 1 < PCD_TOTAL_TOKEN_NUMBER + 1);\r
719\r
149fb6d6 720 if ((!PtrType) && (*Size != DxePcdGetSize (TokenNumber + 1))) {\r
721 return EFI_INVALID_PARAMETER;\r
80408db0 722 }\r
b07a5b68 723\r
2ab6330e 724 //\r
80408db0 725 // EBC compiler is very choosy. It may report warning about comparison\r
726 // between UINTN and 0 . So we add 1 in each size of the \r
727 // comparison.\r
2ab6330e 728 //\r
b07a5b68 729 if ((TokenNumber + 1 < PEI_NEX_TOKEN_NUMBER + 1) ||\r
730 (TokenNumber + 1 >= PEI_LOCAL_TOKEN_NUMBER + 1 || TokenNumber + 1 < (PEI_LOCAL_TOKEN_NUMBER + DXE_NEX_TOKEN_NUMBER + 1))) {\r
731 InvokeCallbackOnSet (0, NULL, TokenNumber + 1, Data, *Size);\r
732 }\r
80408db0 733\r
b07a5b68 734 //\r
735 // Aquire lock to prevent reentrance from TPL_CALLBACK level\r
736 //\r
737 EfiAcquireLock (&mPcdDatabaseLock);\r
80408db0 738\r
2ab6330e 739 //\r
80408db0 740 // EBC compiler is very choosy. It may report warning about comparison\r
741 // between UINTN and 0 . So we add 1 in each size of the \r
742 // comparison.\r
2ab6330e 743 //\r
b07a5b68 744 IsPeiDb = (BOOLEAN) ((TokenNumber + 1 < PEI_LOCAL_TOKEN_NUMBER + 1) ? TRUE : FALSE);\r
745\r
746 LocalTokenNumberTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.LocalTokenNumberTable : \r
747 mPcdDatabase->DxeDb.Init.LocalTokenNumberTable;\r
80408db0 748\r
749 TokenNumber = IsPeiDb ? TokenNumber\r
750 : TokenNumber - PEI_LOCAL_TOKEN_NUMBER;\r
751\r
752 LocalTokenNumber = LocalTokenNumberTable[TokenNumber];\r
753 \r
754 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == PCD_TYPE_SKU_ENABLED) {\r
755 if (PtrType) {\r
756 GetPtrTypeSize (TmpTokenNumber, &MaxSize);\r
757 } else {\r
758 MaxSize = *Size;\r
759 }\r
760 LocalTokenNumber = GetSkuEnabledTokenNumber (LocalTokenNumber & ~PCD_TYPE_SKU_ENABLED, MaxSize, IsPeiDb);\r
761 }\r
762\r
763 Offset = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK;\r
764\r
765 PcdDb = IsPeiDb ? ((UINT8 *) &mPcdDatabase->PeiDb) : ((UINT8 *) &mPcdDatabase->DxeDb);\r
766\r
309e3122 767 if (IsPeiDb) {\r
d0965169 768 StringTable = (UINT8 *) (&mPcdDatabase->PeiDb.Init.StringTable[0]);\r
309e3122 769 } else {\r
d0965169 770 StringTable = (UINT8 *) (&mPcdDatabase->DxeDb.Init.StringTable[0]);\r
309e3122 771 }\r
772\r
80408db0 773 \r
774 InternalData = PcdDb + Offset;\r
775\r
776 switch (LocalTokenNumber & PCD_TYPE_ALL_SET) {\r
777 case PCD_TYPE_VPD:\r
778 ASSERT (FALSE);\r
779 Status = EFI_INVALID_PARAMETER;\r
780 break;\r
781 \r
782 case PCD_TYPE_STRING:\r
783 if (SetPtrTypeSize (TmpTokenNumber, Size)) {\r
7076244e 784 CopyMem (StringTable + *((UINT16 *)InternalData), Data, *Size);\r
80408db0 785 Status = EFI_SUCCESS;\r
786 } else {\r
787 Status = EFI_INVALID_PARAMETER;\r
788 }\r
789 break;\r
790\r
791 case PCD_TYPE_HII:\r
792 if (PtrType) {\r
793 if (!SetPtrTypeSize (TmpTokenNumber, Size)) {\r
794 Status = EFI_INVALID_PARAMETER;\r
795 break;\r
796 }\r
797 }\r
798 \r
309e3122 799 if (IsPeiDb) {\r
800 GuidTable = (EFI_GUID *) (&mPcdDatabase->PeiDb.Init.GuidTable[0]);\r
801 } else {\r
802 GuidTable = (EFI_GUID *) (&mPcdDatabase->DxeDb.Init.GuidTable[0]);\r
803 }\r
80408db0 804 \r
805 VariableHead = (VARIABLE_HEAD *) (PcdDb + Offset);\r
806 \r
1fef733c 807 Guid = GuidTable + VariableHead->GuidTableIndex;\r
d0965169 808 Name = (UINT16*) (StringTable + VariableHead->StringIndex);\r
80408db0 809 VariableOffset = VariableHead->Offset;\r
810\r
811 Status = SetHiiVariable (Guid, Name, Data, *Size, VariableOffset);\r
812\r
813 if (EFI_NOT_FOUND == Status) {\r
814 CopyMem (PcdDb + VariableHead->DefaultValueOffset, Data, *Size);\r
815 Status = EFI_SUCCESS;\r
816 } \r
817 break;\r
818 \r
819 case PCD_TYPE_DATA:\r
820 if (PtrType) {\r
821 if (SetPtrTypeSize (TmpTokenNumber, Size)) {\r
822 CopyMem (InternalData, Data, *Size);\r
823 Status = EFI_SUCCESS;\r
824 } else {\r
825 Status = EFI_INVALID_PARAMETER;\r
826 }\r
827 break;\r
828 }\r
829\r
830 Status = EFI_SUCCESS;\r
831 switch (*Size) {\r
832 case sizeof(UINT8):\r
833 *((UINT8 *) InternalData) = *((UINT8 *) Data);\r
834 break;\r
835\r
836 case sizeof(UINT16):\r
837 *((UINT16 *) InternalData) = *((UINT16 *) Data);\r
838 break;\r
839\r
840 case sizeof(UINT32):\r
841 *((UINT32 *) InternalData) = *((UINT32 *) Data);\r
842 break;\r
843\r
844 case sizeof(UINT64):\r
845 *((UINT64 *) InternalData) = *((UINT64 *) Data);\r
846 break;\r
847\r
848 default:\r
849 ASSERT (FALSE);\r
850 Status = EFI_NOT_FOUND;\r
851 break;\r
852 }\r
853 break;\r
854\r
855 default:\r
856 ASSERT (FALSE);\r
857 Status = EFI_NOT_FOUND;\r
858 break;\r
859 }\r
860\r
861 EfiReleaseLock (&mPcdDatabaseLock);\r
862 \r
863 return Status;\r
864}\r
865\r
2ab6330e 866/**\r
867 Wrapper function for get PCD value for dynamic-ex PCD.\r
80408db0 868\r
2ab6330e 869 @param Guid Token space guid for dynamic-ex PCD.\r
3fd8027e 870 @param ExTokenNumber Token number for dynamic-ex PCD.\r
2ab6330e 871 @param GetSize The size of dynamic-ex PCD value.\r
80408db0 872\r
2ab6330e 873 @return PCD entry in PCD database.\r
80408db0 874\r
2ab6330e 875**/\r
80408db0 876VOID *\r
877ExGetWorker (\r
878 IN CONST EFI_GUID *Guid,\r
879 IN UINTN ExTokenNumber,\r
880 IN UINTN GetSize\r
881 ) \r
882{\r
883 return GetWorker(GetExPcdTokenNumber (Guid, (UINT32) ExTokenNumber), GetSize);\r
884}\r
885\r
2ab6330e 886/**\r
887 Wrapper function for set PCD value for non-Pointer type dynamic-ex PCD.\r
80408db0 888\r
2ab6330e 889 @param ExTokenNumber Token number for dynamic-ex PCD.\r
890 @param Guid Token space guid for dynamic-ex PCD.\r
891 @param Data Value want to be set.\r
892 @param SetSize The size of value.\r
80408db0 893\r
2ab6330e 894 @return status of ExSetWorker().\r
80408db0 895\r
2ab6330e 896**/\r
80408db0 897EFI_STATUS\r
898ExSetValueWorker (\r
899 IN UINTN ExTokenNumber,\r
900 IN CONST EFI_GUID *Guid,\r
901 IN VOID *Data,\r
902 IN UINTN SetSize\r
903 )\r
904{\r
905 return ExSetWorker (ExTokenNumber, Guid, Data, &SetSize, FALSE);\r
906}\r
907\r
2ab6330e 908/**\r
909 Set value for a dynamic PCD entry.\r
910 \r
911 This routine find the local token number according to dynamic-ex PCD's token \r
912 space guid and token number firstly, and invoke callback function if this PCD\r
913 entry registered callback function. Finally, invoken general SetWorker to set\r
914 PCD value.\r
915 \r
916 @param ExTokenNumber Dynamic-ex PCD token number.\r
917 @param Guid Token space guid for dynamic-ex PCD.\r
918 @param Data PCD value want to be set\r
919 @param SetSize Size of value.\r
920 @param PtrType If TRUE, this PCD entry is pointer type.\r
921 If FALSE, this PCD entry is not pointer type.\r
922\r
923 @return status of SetWorker().\r
80408db0 924\r
2ab6330e 925**/\r
80408db0 926EFI_STATUS\r
927ExSetWorker (\r
928 IN UINTN ExTokenNumber,\r
929 IN CONST EFI_GUID *Guid,\r
930 IN VOID *Data,\r
931 IN OUT UINTN *SetSize,\r
932 IN BOOLEAN PtrType\r
933 )\r
934{\r
935 UINTN TokenNumber;\r
936 \r
937 TokenNumber = GetExPcdTokenNumber (Guid, (UINT32) ExTokenNumber);\r
938\r
939 InvokeCallbackOnSet ((UINT32) ExTokenNumber, Guid, TokenNumber, Data, *SetSize);\r
940\r
941 return SetWorker (TokenNumber, Data, SetSize, PtrType);\r
942\r
943}\r
944\r
2ab6330e 945/**\r
946 Set value for HII-type PCD.\r
80408db0 947\r
2ab6330e 948 A HII-type PCD's value is stored in a variable. Setting/Getting the value of \r
949 HII-type PCD is to visit this variable.\r
950 \r
951 @param VariableGuid Guid of variable which stored value of a HII-type PCD.\r
952 @param VariableName Unicode name of variable which stored value of a HII-type PCD.\r
953 @param Data Value want to be set.\r
954 @param DataSize Size of value\r
955 @param Offset Value offset of HII-type PCD in variable.\r
80408db0 956\r
2ab6330e 957 @return status of GetVariable()/SetVariable().\r
80408db0 958\r
2ab6330e 959**/\r
80408db0 960EFI_STATUS\r
961SetHiiVariable (\r
962 IN EFI_GUID *VariableGuid,\r
963 IN UINT16 *VariableName,\r
964 IN CONST VOID *Data,\r
965 IN UINTN DataSize,\r
966 IN UINTN Offset\r
967 )\r
968{\r
969 UINTN Size;\r
970 VOID *Buffer;\r
971 EFI_STATUS Status;\r
972 UINT32 Attribute;\r
b13151ff 973 UINTN SetSize;\r
80408db0 974\r
975 Size = 0;\r
b13151ff 976 SetSize = 0;\r
80408db0 977\r
746be876 978 //\r
979 // Try to get original variable size information.\r
980 //\r
80408db0 981 Status = gRT->GetVariable (\r
982 (UINT16 *)VariableName,\r
983 VariableGuid,\r
984 NULL,\r
985 &Size,\r
986 NULL\r
987 );\r
b13151ff 988 \r
80408db0 989 if (Status == EFI_BUFFER_TOO_SMALL) {\r
746be876 990 //\r
991 // Patch new PCD's value to offset in given HII variable.\r
992 //\r
b13151ff
LG
993 if (Size >= (DataSize + Offset)) {\r
994 SetSize = Size;\r
995 } else {\r
996 SetSize = DataSize + Offset;\r
997 }\r
998 Buffer = AllocatePool (SetSize);\r
80408db0 999 ASSERT (Buffer != NULL);\r
1000\r
1001 Status = gRT->GetVariable (\r
1002 VariableName,\r
1003 VariableGuid,\r
1004 &Attribute,\r
1005 &Size,\r
1006 Buffer\r
1007 );\r
1008 \r
1009 ASSERT_EFI_ERROR (Status);\r
1010\r
1011 CopyMem ((UINT8 *)Buffer + Offset, Data, DataSize);\r
1012\r
1013 Status = gRT->SetVariable (\r
1014 VariableName,\r
1015 VariableGuid,\r
1016 Attribute,\r
b13151ff 1017 SetSize,\r
80408db0 1018 Buffer\r
1019 );\r
1020\r
1021 FreePool (Buffer);\r
1022 return Status;\r
746be876 1023 } else if (Status == EFI_NOT_FOUND) {\r
1024 //\r
1025 // If variable does not exist, a new variable need to be created.\r
1026 //\r
1027 \r
1028 Size = Offset + DataSize;\r
1029 \r
1030 Buffer = AllocateZeroPool (Size);\r
1031 ASSERT (Buffer != NULL);\r
1032 \r
1033 CopyMem ((UINT8 *)Buffer + Offset, Data, DataSize);\r
1034 \r
1035 Status = gRT->SetVariable (\r
1036 VariableName,\r
1037 VariableGuid,\r
1038 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
1039 Size,\r
1040 Buffer\r
1041 );\r
1042\r
1043 FreePool (Buffer);\r
1044 return Status; \r
1045 }\r
80408db0 1046 \r
1047 //\r
746be876 1048 // If we drop to here, the value is failed to be written in to variable area\r
1049 // So, we will save the data in the PCD Database's volatile area.\r
80408db0 1050 //\r
1051 return Status;\r
1052}\r
1053\r
2ab6330e 1054/**\r
1055 Get local token number according to dynamic-ex PCD's {token space guid:token number}\r
80408db0 1056\r
2ab6330e 1057 A dynamic-ex type PCD, developer must provide pair of token space guid: token number\r
1058 in DEC file. PCD database maintain a mapping table that translate pair of {token\r
1059 space guid: token number} to local token number.\r
1060 \r
1061 @param Guid Token space guid for dynamic-ex PCD entry.\r
b9982883 1062 @param ExTokenNumber Dynamic-ex PCD token number.\r
80408db0 1063\r
2ab6330e 1064 @return local token number for dynamic-ex PCD.\r
80408db0 1065\r
2ab6330e 1066**/\r
80408db0 1067UINTN \r
1068GetExPcdTokenNumber (\r
1069 IN CONST EFI_GUID *Guid,\r
1070 IN UINT32 ExTokenNumber\r
1071 )\r
1072{\r
2ab6330e 1073 UINT32 Index;\r
80408db0 1074 DYNAMICEX_MAPPING *ExMap;\r
1075 EFI_GUID *GuidTable;\r
1076 EFI_GUID *MatchGuid;\r
1077 UINTN MatchGuidIdx;\r
1078\r
1079 if (!PEI_DATABASE_EMPTY) {\r
1080 ExMap = mPcdDatabase->PeiDb.Init.ExMapTable;\r
1081 GuidTable = mPcdDatabase->PeiDb.Init.GuidTable;\r
1082 \r
1083 MatchGuid = ScanGuid (GuidTable, sizeof(mPcdDatabase->PeiDb.Init.GuidTable), Guid);\r
1084 \r
1085 if (MatchGuid != NULL) {\r
1086\r
1087 MatchGuidIdx = MatchGuid - GuidTable;\r
1088 \r
2ab6330e 1089 for (Index = 0; Index < PEI_EXMAPPING_TABLE_SIZE; Index++) {\r
1090 if ((ExTokenNumber == ExMap[Index].ExTokenNumber) &&\r
1091 (MatchGuidIdx == ExMap[Index].ExGuidIndex)) {\r
1092 return ExMap[Index].LocalTokenNumber;\r
80408db0 1093 }\r
1094 }\r
1095 }\r
1096 }\r
1097 \r
1098 ExMap = mPcdDatabase->DxeDb.Init.ExMapTable;\r
1099 GuidTable = mPcdDatabase->DxeDb.Init.GuidTable;\r
1100\r
1101 MatchGuid = ScanGuid (GuidTable, sizeof(mPcdDatabase->DxeDb.Init.GuidTable), Guid);\r
1102 //\r
1103 // We need to ASSERT here. If GUID can't be found in GuidTable, this is a\r
1104 // error in the BUILD system.\r
1105 //\r
1106 ASSERT (MatchGuid != NULL);\r
1107\r
1108 MatchGuidIdx = MatchGuid - GuidTable;\r
1109 \r
2ab6330e 1110 for (Index = 0; Index < DXE_EXMAPPING_TABLE_SIZE; Index++) {\r
1111 if ((ExTokenNumber == ExMap[Index].ExTokenNumber) &&\r
1112 (MatchGuidIdx == ExMap[Index].ExGuidIndex)) {\r
1113 return ExMap[Index].LocalTokenNumber;\r
80408db0 1114 }\r
1115 }\r
1116\r
1117 ASSERT (FALSE);\r
1118\r
1119 return 0;\r
1120}\r
1121\r
2ab6330e 1122/**\r
3fd8027e 1123 Get SKU ID table from PCD database.\r
2ab6330e 1124\r
1125 @param LocalTokenNumberTableIdx Index of local token number in token number table.\r
1126 @param IsPeiPcd If TRUE, \r
80408db0 1127\r
2ab6330e 1128 @return Pointer to SKU ID array table\r
1129\r
1130**/\r
80408db0 1131SKU_ID *\r
1132GetSkuIdArray (\r
1133 IN UINTN LocalTokenNumberTableIdx,\r
1134 IN BOOLEAN IsPeiPcd\r
1135 )\r
1136{\r
1137 SKU_HEAD *SkuHead;\r
1138 UINTN LocalTokenNumber;\r
1139 UINT8 *Database;\r
1140\r
1141 if (IsPeiPcd) {\r
1142 LocalTokenNumber = mPcdDatabase->PeiDb.Init.LocalTokenNumberTable[LocalTokenNumberTableIdx];\r
1143 Database = (UINT8 *) &mPcdDatabase->PeiDb;\r
1144 } else {\r
1145 LocalTokenNumber = mPcdDatabase->DxeDb.Init.LocalTokenNumberTable[LocalTokenNumberTableIdx - PEI_LOCAL_TOKEN_NUMBER];\r
1146 Database = (UINT8 *) &mPcdDatabase->DxeDb;\r
1147 }\r
1148\r
1149 ASSERT ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) != 0);\r
1150\r
1151 SkuHead = (SKU_HEAD *) ((UINT8 *)Database + (LocalTokenNumber & PCD_DATABASE_OFFSET_MASK));\r
1152\r
1153 return (SKU_ID *) (Database + SkuHead->SkuIdTableOffset);\r
1154 \r
1155}\r
1156\r
2ab6330e 1157/**\r
3d53ba8b 1158 Wrapper function of getting index of PCD entry in size table.\r
1159 \r
2ab6330e 1160 @param LocalTokenNumberTableIdx Index of this PCD in local token number table.\r
2ab6330e 1161 @param IsPeiDb If TRUE, the pcd entry is initialized in PEI phase,\r
1162 If FALSE, the pcd entry is initialized in DXE phase.\r
1163\r
1164 @return index of PCD entry in size table.\r
2ab6330e 1165**/\r
80408db0 1166UINTN\r
3d53ba8b 1167GetSizeTableIndex (\r
1168 IN UINTN LocalTokenNumberTableIdx,\r
1169 IN BOOLEAN IsPeiDb\r
80408db0 1170 )\r
1171{\r
3d53ba8b 1172 UINT32 *LocalTokenNumberTable;\r
1173 UINTN LocalTokenNumber;\r
1174 UINTN Index;\r
1175 UINTN SizeTableIdx;\r
1176 SKU_ID *SkuIdTable;\r
80408db0 1177 \r
3d53ba8b 1178 if (IsPeiDb) {\r
1179 LocalTokenNumberTable = mPcdDatabase->PeiDb.Init.LocalTokenNumberTable;\r
1180 } else {\r
1181 LocalTokenNumberTable = mPcdDatabase->DxeDb.Init.LocalTokenNumberTable;\r
1182 }\r
1183\r
80408db0 1184 SizeTableIdx = 0;\r
1185\r
3d53ba8b 1186 for (Index = 0; Index < LocalTokenNumberTableIdx; Index ++) {\r
2ab6330e 1187 LocalTokenNumber = LocalTokenNumberTable[Index];\r
80408db0 1188\r
1189 if ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER) {\r
1190 //\r
1191 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type \r
1192 // PCD entry.\r
1193 //\r
2ab6330e 1194 if ((LocalTokenNumber & PCD_TYPE_VPD) != 0) {\r
80408db0 1195 //\r
1196 // We have only one entry for VPD enabled PCD entry:\r
1197 // 1) MAX Size.\r
1198 // We consider current size is equal to MAX size.\r
1199 //\r
1200 SizeTableIdx++;\r
1201 } else {\r
1202 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0) {\r
1203 //\r
1204 // We have only two entry for Non-Sku enabled PCD entry:\r
1205 // 1) MAX SIZE\r
1206 // 2) Current Size\r
1207 //\r
1208 SizeTableIdx += 2;\r
1209 } else {\r
1210 //\r
1211 // We have these entry for SKU enabled PCD entry\r
1212 // 1) MAX SIZE\r
1213 // 2) Current Size for each SKU_ID (It is equal to MaxSku).\r
1214 //\r
2ab6330e 1215 SkuIdTable = GetSkuIdArray (Index, IsPeiDb);\r
80408db0 1216 SizeTableIdx += (UINTN)*SkuIdTable + 1;\r
1217 }\r
1218 }\r
1219 }\r
1220\r
1221 }\r
1222\r
3d53ba8b 1223 return SizeTableIdx; \r
80408db0 1224}\r
1225\r
2ab6330e 1226/**\r
1227 Get size of POINTER type PCD value.\r
1228\r
1229 @param LocalTokenNumberTableIdx Index of local token number in local token number table.\r
1230 @param MaxSize Maxmium size of POINTER type PCD value.\r
80408db0 1231\r
2ab6330e 1232 @return size of POINTER type PCD value.\r
80408db0 1233\r
2ab6330e 1234**/\r
80408db0 1235UINTN\r
1236GetPtrTypeSize (\r
1237 IN UINTN LocalTokenNumberTableIdx,\r
1238 OUT UINTN *MaxSize\r
1239 )\r
1240{\r
1241 INTN SizeTableIdx;\r
1242 UINTN LocalTokenNumber;\r
1243 SKU_ID *SkuIdTable;\r
1244 SIZE_INFO *SizeTable;\r
2ab6330e 1245 UINTN Index;\r
80408db0 1246 BOOLEAN IsPeiDb;\r
1247 UINT32 *LocalTokenNumberTable;\r
1248\r
1249 // EBC compiler is very choosy. It may report warning about comparison\r
1250 // between UINTN and 0 . So we add 1 in each size of the \r
1251 // comparison.\r
1252 IsPeiDb = (BOOLEAN) (LocalTokenNumberTableIdx + 1 < PEI_LOCAL_TOKEN_NUMBER + 1);\r
1253\r
1254\r
1255 if (IsPeiDb) {\r
1256 LocalTokenNumberTable = mPcdDatabase->PeiDb.Init.LocalTokenNumberTable;\r
1257 SizeTable = mPcdDatabase->PeiDb.Init.SizeTable;\r
1258 } else {\r
1259 LocalTokenNumberTableIdx -= PEI_LOCAL_TOKEN_NUMBER;\r
1260 LocalTokenNumberTable = mPcdDatabase->DxeDb.Init.LocalTokenNumberTable;\r
1261 SizeTable = mPcdDatabase->DxeDb.Init.SizeTable;\r
1262 }\r
1263\r
1264 LocalTokenNumber = LocalTokenNumberTable[LocalTokenNumberTableIdx];\r
1265\r
1266 ASSERT ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER);\r
1267 \r
1268 SizeTableIdx = GetSizeTableIndex (LocalTokenNumberTableIdx, IsPeiDb);\r
1269\r
1270 *MaxSize = SizeTable[SizeTableIdx];\r
1271 //\r
1272 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type \r
1273 // PCD entry.\r
1274 //\r
2ab6330e 1275 if ((LocalTokenNumber & PCD_TYPE_VPD) != 0) {\r
80408db0 1276 //\r
1277 // We have only one entry for VPD enabled PCD entry:\r
1278 // 1) MAX Size.\r
1279 // We consider current size is equal to MAX size.\r
1280 //\r
1281 return *MaxSize;\r
1282 } else {\r
1283 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0) {\r
1284 //\r
1285 // We have only two entry for Non-Sku enabled PCD entry:\r
1286 // 1) MAX SIZE\r
1287 // 2) Current Size\r
1288 //\r
1289 return SizeTable[SizeTableIdx + 1];\r
1290 } else {\r
1291 //\r
1292 // We have these entry for SKU enabled PCD entry\r
1293 // 1) MAX SIZE\r
1294 // 2) Current Size for each SKU_ID (It is equal to MaxSku).\r
1295 //\r
1296 SkuIdTable = GetSkuIdArray (LocalTokenNumberTableIdx, IsPeiDb);\r
2ab6330e 1297 for (Index = 0; Index < SkuIdTable[0]; Index++) {\r
1298 if (SkuIdTable[1 + Index] == mPcdDatabase->PeiDb.Init.SystemSkuId) {\r
1299 return SizeTable[SizeTableIdx + 1 + Index];\r
80408db0 1300 }\r
1301 }\r
1302 return SizeTable[SizeTableIdx + 1];\r
1303 }\r
1304 }\r
1305}\r
1306\r
2ab6330e 1307/**\r
3fd8027e 1308 Set size of POINTER type PCD value. The size should not exceed the maximum size\r
2ab6330e 1309 of this PCD value.\r
80408db0 1310\r
2ab6330e 1311 @param LocalTokenNumberTableIdx Index of local token number in local token number table.\r
1312 @param CurrentSize Size of POINTER type PCD value.\r
80408db0 1313\r
2ab6330e 1314 @retval TRUE Success to set size of PCD value.\r
1315 @retval FALSE Fail to set size of PCD value.\r
1316**/\r
80408db0 1317BOOLEAN\r
1318SetPtrTypeSize (\r
1319 IN UINTN LocalTokenNumberTableIdx,\r
1320 IN OUT UINTN *CurrentSize\r
1321 )\r
1322{\r
1323 INTN SizeTableIdx;\r
1324 UINTN LocalTokenNumber;\r
1325 SKU_ID *SkuIdTable;\r
1326 SIZE_INFO *SizeTable;\r
2ab6330e 1327 UINTN Index;\r
80408db0 1328 UINTN MaxSize;\r
1329 BOOLEAN IsPeiDb;\r
1330 UINT32 *LocalTokenNumberTable;\r
1331\r
2ab6330e 1332 //\r
80408db0 1333 // EBC compiler is very choosy. It may report warning about comparison\r
1334 // between UINTN and 0 . So we add 1 in each size of the \r
1335 // comparison.\r
2ab6330e 1336 //\r
80408db0 1337 IsPeiDb = (BOOLEAN) (LocalTokenNumberTableIdx + 1 < PEI_LOCAL_TOKEN_NUMBER + 1);\r
1338\r
1339 if (IsPeiDb) {\r
1340 LocalTokenNumberTable = mPcdDatabase->PeiDb.Init.LocalTokenNumberTable;\r
1341 SizeTable = mPcdDatabase->PeiDb.Init.SizeTable;\r
1342 } else {\r
1343 LocalTokenNumberTableIdx -= PEI_LOCAL_TOKEN_NUMBER;\r
1344 LocalTokenNumberTable = mPcdDatabase->DxeDb.Init.LocalTokenNumberTable;\r
1345 SizeTable = mPcdDatabase->DxeDb.Init.SizeTable;\r
1346 }\r
1347\r
1348 LocalTokenNumber = LocalTokenNumberTable[LocalTokenNumberTableIdx];\r
1349\r
1350 ASSERT ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER);\r
1351 \r
1352 SizeTableIdx = GetSizeTableIndex (LocalTokenNumberTableIdx, IsPeiDb);\r
1353\r
1354 MaxSize = SizeTable[SizeTableIdx];\r
1355 //\r
1356 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type \r
1357 // PCD entry.\r
1358 //\r
2ab6330e 1359 if ((LocalTokenNumber & PCD_TYPE_VPD) != 0) {\r
80408db0 1360 //\r
1361 // We shouldn't come here as we don't support SET for VPD\r
1362 //\r
1363 ASSERT (FALSE);\r
1364 return FALSE;\r
1365 } else {\r
1366 if ((*CurrentSize > MaxSize) ||\r
1367 (*CurrentSize == MAX_ADDRESS)) {\r
1368 *CurrentSize = MaxSize;\r
1369 return FALSE;\r
1370 } \r
1371 \r
1372 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0) {\r
1373 //\r
1374 // We have only two entry for Non-Sku enabled PCD entry:\r
1375 // 1) MAX SIZE\r
1376 // 2) Current Size\r
1377 //\r
1378 SizeTable[SizeTableIdx + 1] = (SIZE_INFO) *CurrentSize;\r
1379 return TRUE;\r
1380 } else {\r
1381 //\r
1382 // We have these entry for SKU enabled PCD entry\r
1383 // 1) MAX SIZE\r
1384 // 2) Current Size for each SKU_ID (It is equal to MaxSku).\r
1385 //\r
1386 SkuIdTable = GetSkuIdArray (LocalTokenNumberTableIdx, IsPeiDb);\r
2ab6330e 1387 for (Index = 0; Index < SkuIdTable[0]; Index++) {\r
1388 if (SkuIdTable[1 + Index] == mPcdDatabase->PeiDb.Init.SystemSkuId) {\r
1389 SizeTable[SizeTableIdx + 1 + Index] = (SIZE_INFO) *CurrentSize;\r
80408db0 1390 return TRUE;\r
1391 }\r
1392 }\r
1393 SizeTable[SizeTableIdx + 1] = (SIZE_INFO) *CurrentSize;\r
1394 return TRUE;\r
1395 }\r
1396 }\r
1397}\r