]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/PCD/Dxe/Service.c
MdePkg and MdeModulePkg Pcd: Add the new EFI_GET_PCD_INFO_PROTOCOL and EFI_GET_PCD_IN...
[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
0b1ef275 4Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>\r
e5eed7d3 5This program and the accompanying materials\r
80408db0 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
419db80b 16#include <Library/DxeServicesLib.h>\r
80408db0 17\r
419db80b
BF
18PCD_DATABASE mPcdDatabase;\r
19\r
20UINT32 mPcdTotalTokenCount; \r
21UINT32 mPeiLocalTokenCount; \r
22UINT32 mDxeLocalTokenCount; \r
23UINT32 mPeiNexTokenCount; \r
24UINT32 mDxeNexTokenCount; \r
25UINT32 mPeiExMapppingTableSize;\r
26UINT32 mDxeExMapppingTableSize;\r
27UINT32 mPeiGuidTableSize;\r
28UINT32 mDxeGuidTableSize;\r
29\r
30BOOLEAN mPeiExMapTableEmpty; \r
31BOOLEAN mDxeExMapTableEmpty; \r
32BOOLEAN mPeiDatabaseEmpty;\r
80408db0 33\r
b07a5b68 34LIST_ENTRY *mCallbackFnTable;\r
419db80b
BF
35EFI_GUID **TmpTokenSpaceBuffer;\r
36UINTN TmpTokenSpaceBufferCount; \r
37\r
96d6d004
SZ
38/**\r
39 Get Local Token Number by Token Number.\r
40\r
41 @param[in] IsPeiDb If TRUE, the pcd entry is initialized in PEI phase,\r
42 If FALSE, the pcd entry is initialized in DXE phase.\r
43 @param[in] TokenNumber The PCD token number.\r
44\r
45 @return Local Token Number.\r
46**/\r
47UINT32\r
48GetLocalTokenNumber (\r
49 IN BOOLEAN IsPeiDb,\r
50 IN UINTN TokenNumber\r
51 )\r
52{\r
53 UINT32 *LocalTokenNumberTable;\r
54 UINT32 LocalTokenNumber;\r
55 UINTN Size;\r
56 UINTN MaxSize;\r
57\r
58 //\r
59 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.\r
60 // We have to decrement TokenNumber by 1 to make it usable\r
61 // as the array index.\r
62 //\r
63 TokenNumber--;\r
64\r
65 LocalTokenNumberTable = IsPeiDb ? (UINT32 *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->LocalTokenNumberTableOffset) : \r
66 (UINT32 *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->LocalTokenNumberTableOffset);\r
67 TokenNumber = IsPeiDb ? TokenNumber : TokenNumber - mPeiLocalTokenCount;\r
68\r
69 LocalTokenNumber = LocalTokenNumberTable[TokenNumber];\r
70\r
71 Size = (LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) >> PCD_DATUM_TYPE_SHIFT;\r
72\r
73 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == PCD_TYPE_SKU_ENABLED) {\r
74 if (Size == 0) {\r
75 GetPtrTypeSize (TokenNumber, &MaxSize);\r
76 } else {\r
77 MaxSize = Size;\r
78 }\r
79 LocalTokenNumber = GetSkuEnabledTokenNumber (LocalTokenNumber & ~PCD_TYPE_SKU_ENABLED, MaxSize, IsPeiDb);\r
80 }\r
81\r
82 return LocalTokenNumber;\r
83}\r
84\r
85/**\r
86 Get PCD type by Local Token Number.\r
87\r
88 @param[in] LocalTokenNumber The PCD local token number.\r
89\r
90 @return PCD type.\r
91**/\r
92EFI_PCD_TYPE\r
93GetPcdType (\r
94 IN UINT32 LocalTokenNumber\r
95 )\r
96{\r
97 switch (LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) {\r
98 case PCD_DATUM_TYPE_POINTER:\r
99 return EFI_PCD_TYPE_PTR;\r
100 case PCD_DATUM_TYPE_UINT8:\r
101 if (LocalTokenNumber & PCD_DATUM_TYPE_UINT8_BOOLEAN) {\r
102 return EFI_PCD_TYPE_BOOL;\r
103 } else {\r
104 return EFI_PCD_TYPE_8;\r
105 }\r
106 case PCD_DATUM_TYPE_UINT16:\r
107 return EFI_PCD_TYPE_16;\r
108 case PCD_DATUM_TYPE_UINT32:\r
109 return EFI_PCD_TYPE_32;\r
110 case PCD_DATUM_TYPE_UINT64:\r
111 return EFI_PCD_TYPE_64;\r
112 default:\r
113 ASSERT (FALSE);\r
114 return EFI_PCD_TYPE_8;\r
115 }\r
116}\r
117\r
118/**\r
119 Get PCD name.\r
120\r
121 @param[in] OnlyTokenSpaceName If TRUE, only need to get the TokenSpaceCName.\r
122 If FALSE, need to get the full PCD name.\r
123 @param[in] IsPeiDb If TRUE, the pcd entry is initialized in PEI phase,\r
124 If FALSE, the pcd entry is initialized in DXE phase.\r
125 @param[in] TokenNumber The PCD token number.\r
126\r
127 @return The TokenSpaceCName or full PCD name.\r
128**/\r
129CHAR8 *\r
130GetPcdName (\r
131 IN BOOLEAN OnlyTokenSpaceName,\r
132 IN BOOLEAN IsPeiDb,\r
133 IN UINTN TokenNumber\r
134 )\r
135{\r
136 PCD_DATABASE_INIT *Database;\r
137 UINT8 *StringTable;\r
138 PCD_NAME_INDEX *PcdNameIndex;\r
139 CHAR8 *TokenSpaceName;\r
140 CHAR8 *PcdName;\r
141 CHAR8 *Name;\r
142\r
143 //\r
144 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.\r
145 // We have to decrement TokenNumber by 1 to make it usable\r
146 // as the array index.\r
147 //\r
148 TokenNumber--;\r
149\r
150 Database = IsPeiDb ? mPcdDatabase.PeiDb: mPcdDatabase.DxeDb;\r
151 TokenNumber = IsPeiDb ? TokenNumber : TokenNumber - mPeiLocalTokenCount;\r
152\r
153 StringTable = (UINT8 *) Database + Database->StringTableOffset;\r
154\r
155 //\r
156 // Get the PCD name index.\r
157 //\r
158 PcdNameIndex = (PCD_NAME_INDEX *)((UINT8 *) Database + Database->PcdNameTableOffset) + TokenNumber;\r
159 TokenSpaceName = (CHAR8 *)&StringTable[PcdNameIndex->TokenSpaceCNameIndex];\r
160 PcdName = (CHAR8 *)&StringTable[PcdNameIndex->PcdCNameIndex];\r
161\r
162 if (OnlyTokenSpaceName) {\r
163 //\r
164 // Only need to get the TokenSpaceCName.\r
165 //\r
166 Name = AllocateCopyPool (AsciiStrSize (TokenSpaceName), TokenSpaceName);\r
167 } else {\r
168 //\r
169 // Need to get the full PCD name.\r
170 //\r
171 Name = AllocateZeroPool (AsciiStrSize (TokenSpaceName) + AsciiStrSize (PcdName));\r
172 //\r
173 // Catenate TokenSpaceCName and PcdCName with a '.' to form the full PCD name.\r
174 //\r
175 AsciiStrCat (Name, TokenSpaceName);\r
176 Name[AsciiStrSize (TokenSpaceName) - sizeof (CHAR8)] = '.';\r
177 AsciiStrCat (Name, PcdName); \r
178 }\r
179\r
180 return Name;\r
181}\r
182\r
183/**\r
184 Retrieve additional information associated with a PCD token.\r
185\r
186 This includes information such as the type of value the TokenNumber is associated with as well as possible\r
187 human readable name that is associated with the token.\r
188\r
189 @param[in] IsPeiDb If TRUE, the pcd entry is initialized in PEI phase,\r
190 If FALSE, the pcd entry is initialized in DXE phase.\r
191 @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.\r
192 @param[in] TokenNumber The PCD token number.\r
193 @param[out] PcdInfo The returned information associated with the requested TokenNumber.\r
194 The caller is responsible for freeing the buffer that is allocated by callee for PcdInfo->PcdName. \r
195\r
196 @retval EFI_SUCCESS The PCD information was returned successfully\r
197 @retval EFI_NOT_FOUND The PCD service could not find the requested token number.\r
198**/\r
199EFI_STATUS\r
200ExGetPcdInfo (\r
201 IN BOOLEAN IsPeiDb,\r
202 IN CONST EFI_GUID *Guid,\r
203 IN UINTN TokenNumber,\r
204 OUT EFI_PCD_INFO *PcdInfo\r
205 )\r
206{\r
207 PCD_DATABASE_INIT *Database;\r
208 UINTN GuidTableIdx;\r
209 EFI_GUID *MatchGuid;\r
210 EFI_GUID *GuidTable;\r
211 DYNAMICEX_MAPPING *ExMapTable;\r
212 UINTN Index;\r
213 UINT32 LocalTokenNumber;\r
214\r
215 Database = IsPeiDb ? mPcdDatabase.PeiDb: mPcdDatabase.DxeDb;\r
216\r
217 GuidTable = (EFI_GUID *)((UINT8 *)Database + Database->GuidTableOffset);\r
218 MatchGuid = ScanGuid (GuidTable, Database->GuidTableCount * sizeof(EFI_GUID), Guid);\r
219\r
220 if (MatchGuid == NULL) {\r
221 return EFI_NOT_FOUND;\r
222 }\r
223\r
224 GuidTableIdx = MatchGuid - GuidTable;\r
225\r
226 ExMapTable = (DYNAMICEX_MAPPING *)((UINT8 *)Database + Database->ExMapTableOffset);\r
227\r
228 //\r
229 // Find the PCD by GuidTableIdx and ExTokenNumber in ExMapTable.\r
230 //\r
231 for (Index = 0; Index < Database->ExTokenCount; Index++) {\r
232 if (ExMapTable[Index].ExGuidIndex == GuidTableIdx) {\r
233 if (TokenNumber == PCD_INVALID_TOKEN_NUMBER) {\r
234 //\r
235 // TokenNumber is 0, follow spec to set PcdType to EFI_PCD_TYPE_8,\r
236 // PcdSize to 0 and PcdName to the null-terminated ASCII string\r
237 // associated with the token's namespace Guid.\r
238 //\r
239 PcdInfo->PcdType = EFI_PCD_TYPE_8;\r
240 PcdInfo->PcdSize = 0;\r
241 //\r
242 // Here use one representative in the token space to get the TokenSpaceCName.\r
243 // \r
244 PcdInfo->PcdName = GetPcdName (TRUE, IsPeiDb, ExMapTable[Index].TokenNumber);\r
245 return EFI_SUCCESS;\r
246 } else if (ExMapTable[Index].ExTokenNumber == TokenNumber) {\r
247 PcdInfo->PcdSize = DxePcdGetSize (ExMapTable[Index].TokenNumber);\r
248 LocalTokenNumber = GetLocalTokenNumber (IsPeiDb, ExMapTable[Index].TokenNumber);\r
249 PcdInfo->PcdType = GetPcdType (LocalTokenNumber);\r
250 PcdInfo->PcdName = GetPcdName (FALSE, IsPeiDb, ExMapTable[Index].TokenNumber);\r
251 return EFI_SUCCESS;\r
252 }\r
253 }\r
254 }\r
255\r
256 return EFI_NOT_FOUND;\r
257}\r
258\r
259/**\r
260 Retrieve additional information associated with a PCD token.\r
261\r
262 This includes information such as the type of value the TokenNumber is associated with as well as possible\r
263 human readable name that is associated with the token.\r
264\r
265 @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.\r
266 @param[in] TokenNumber The PCD token number.\r
267 @param[out] PcdInfo The returned information associated with the requested TokenNumber.\r
268 The caller is responsible for freeing the buffer that is allocated by callee for PcdInfo->PcdName.\r
269\r
270 @retval EFI_SUCCESS The PCD information was returned successfully.\r
271 @retval EFI_NOT_FOUND The PCD service could not find the requested token number.\r
272**/\r
273EFI_STATUS\r
274DxeGetPcdInfo (\r
275 IN CONST EFI_GUID *Guid,\r
276 IN UINTN TokenNumber,\r
277 OUT EFI_PCD_INFO *PcdInfo\r
278 )\r
279{\r
280 EFI_STATUS Status;\r
281 BOOLEAN PeiExMapTableEmpty;\r
282 BOOLEAN DxeExMapTableEmpty;\r
283 UINT32 LocalTokenNumber;\r
284 BOOLEAN IsPeiDb;\r
285\r
286 if (!FeaturePcdGet (PcdPcdInfoGeneration)) {\r
287 return EFI_UNSUPPORTED;\r
288 }\r
289\r
290 ASSERT (PcdInfo != NULL);\r
291\r
292 Status = EFI_NOT_FOUND;\r
293 PeiExMapTableEmpty = mPeiExMapTableEmpty;\r
294 DxeExMapTableEmpty = mDxeExMapTableEmpty;\r
295\r
296 if (Guid == NULL) {\r
297 if (((TokenNumber + 1 > mPeiNexTokenCount + 1) && (TokenNumber + 1 <= mPeiLocalTokenCount + 1)) ||\r
298 ((TokenNumber + 1 > (mPeiLocalTokenCount + mDxeNexTokenCount + 1)))) {\r
299 return EFI_NOT_FOUND;\r
300 } else if (TokenNumber == PCD_INVALID_TOKEN_NUMBER) {\r
301 //\r
302 // TokenNumber is 0, follow spec to set PcdType to EFI_PCD_TYPE_8,\r
303 // PcdSize to 0 and PcdName to NULL for default Token Space.\r
304 //\r
305 PcdInfo->PcdType = EFI_PCD_TYPE_8;\r
306 PcdInfo->PcdSize = 0;\r
307 PcdInfo->PcdName = NULL;\r
308 } else {\r
309 PcdInfo->PcdSize = DxePcdGetSize (TokenNumber);\r
310 IsPeiDb = FALSE;\r
311 if ((TokenNumber + 1 <= mPeiNexTokenCount + 1)) {\r
312 IsPeiDb = TRUE;\r
313 }\r
314 LocalTokenNumber = GetLocalTokenNumber (IsPeiDb, TokenNumber);\r
315 PcdInfo->PcdType = GetPcdType (LocalTokenNumber);\r
316 PcdInfo->PcdName = GetPcdName (FALSE, IsPeiDb, TokenNumber);\r
317 }\r
318 return EFI_SUCCESS;\r
319 }\r
320\r
321 if (PeiExMapTableEmpty && DxeExMapTableEmpty) {\r
322 return EFI_NOT_FOUND;\r
323 }\r
324\r
325 if (!PeiExMapTableEmpty) {\r
326 Status = ExGetPcdInfo (\r
327 TRUE,\r
328 Guid,\r
329 TokenNumber,\r
330 PcdInfo\r
331 );\r
332 }\r
333\r
334 if (Status == EFI_SUCCESS) {\r
335 return Status;\r
336 }\r
337\r
338 if (!DxeExMapTableEmpty) {\r
339 Status = ExGetPcdInfo (\r
340 FALSE,\r
341 Guid,\r
342 TokenNumber,\r
343 PcdInfo\r
344 );\r
345 }\r
346\r
347 return Status;\r
348}\r
80408db0 349\r
2ab6330e 350/**\r
351 Get the PCD entry pointer in PCD database.\r
352 \r
353 This routine will visit PCD database to find the PCD entry according to given\r
354 token number. The given token number is autogened by build tools and it will be \r
355 translated to local token number. Local token number contains PCD's type and \r
356 offset of PCD entry in PCD database.\r
357\r
358 @param TokenNumber Token's number, it is autogened by build tools\r
359 @param GetSize The size of token's value\r
360\r
361 @return PCD entry pointer in PCD database\r
362\r
363**/\r
80408db0 364VOID *\r
365GetWorker (\r
2ab6330e 366 IN UINTN TokenNumber,\r
367 IN UINTN GetSize\r
80408db0 368 )\r
369{\r
80408db0 370 EFI_GUID *GuidTable;\r
d0965169 371 UINT8 *StringTable;\r
80408db0 372 EFI_GUID *Guid;\r
373 UINT16 *Name;\r
374 VARIABLE_HEAD *VariableHead;\r
375 UINT8 *VaraiableDefaultBuffer;\r
376 UINT8 *Data;\r
377 VPD_HEAD *VpdHead;\r
378 UINT8 *PcdDb;\r
379 VOID *RetPtr;\r
80408db0 380 UINTN TmpTokenNumber;\r
381 UINTN DataSize;\r
382 EFI_STATUS Status;\r
383 UINT32 LocalTokenNumber;\r
384 UINT32 Offset;\r
6cfc7292 385 STRING_HEAD StringTableIdx; \r
80408db0 386 BOOLEAN IsPeiDb;\r
387\r
388 //\r
389 // Aquire lock to prevent reentrance from TPL_CALLBACK level\r
390 //\r
391 EfiAcquireLock (&mPcdDatabaseLock);\r
392\r
393 RetPtr = NULL;\r
419db80b
BF
394\r
395 ASSERT (TokenNumber > 0);\r
80408db0 396 //\r
397 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.\r
398 // We have to decrement TokenNumber by 1 to make it usable\r
399 // as the array index.\r
400 //\r
401 TokenNumber--;\r
402\r
403 TmpTokenNumber = TokenNumber;\r
419db80b 404\r
80408db0 405 //\r
419db80b
BF
406 // EBC compiler is very choosy. It may report warning about comparison\r
407 // between UINTN and 0 . So we add 1 in each size of the \r
80408db0 408 // comparison.\r
409 //\r
419db80b 410 ASSERT (TokenNumber + 1 < mPcdTotalTokenCount + 1);\r
80408db0 411\r
412 ASSERT ((GetSize == DxePcdGetSize (TokenNumber + 1)) || (GetSize == 0));\r
413\r
414 // EBC compiler is very choosy. It may report warning about comparison\r
415 // between UINTN and 0 . So we add 1 in each size of the \r
416 // comparison.\r
419db80b 417 IsPeiDb = (BOOLEAN) ((TokenNumber + 1 < mPeiLocalTokenCount + 1) ? TRUE : FALSE);\r
80408db0 418\r
96d6d004 419 LocalTokenNumber = GetLocalTokenNumber (IsPeiDb, TokenNumber + 1);\r
80408db0 420\r
419db80b 421 PcdDb = IsPeiDb ? ((UINT8 *) mPcdDatabase.PeiDb) : ((UINT8 *) mPcdDatabase.DxeDb);\r
309e3122 422 \r
423 if (IsPeiDb) {\r
419db80b 424 StringTable = (UINT8 *) ((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->StringTableOffset);\r
309e3122 425 } else {\r
419db80b 426 StringTable = (UINT8 *) ((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->StringTableOffset);\r
309e3122 427 }\r
419db80b
BF
428\r
429\r
80408db0 430 Offset = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK;\r
419db80b 431\r
80408db0 432 switch (LocalTokenNumber & PCD_TYPE_ALL_SET) {\r
433 case PCD_TYPE_VPD:\r
434 VpdHead = (VPD_HEAD *) ((UINT8 *) PcdDb + Offset);\r
188e4e84 435 RetPtr = (VOID *) (UINTN) (PcdGet32 (PcdVpdBaseAddress) + VpdHead->Offset);\r
419db80b 436\r
80408db0 437 break;\r
419db80b 438\r
6ac15f7c 439 case PCD_TYPE_HII|PCD_TYPE_STRING:\r
80408db0 440 case PCD_TYPE_HII:\r
309e3122 441 if (IsPeiDb) {\r
419db80b 442 GuidTable = (EFI_GUID *) ((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->GuidTableOffset);\r
309e3122 443 } else {\r
419db80b 444 GuidTable = (EFI_GUID *) ((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->GuidTableOffset);\r
309e3122 445 }\r
419db80b 446\r
80408db0 447 VariableHead = (VARIABLE_HEAD *) (PcdDb + Offset);\r
1fef733c 448 Guid = GuidTable + VariableHead->GuidTableIndex;\r
d0965169 449 Name = (UINT16*)(StringTable + VariableHead->StringIndex);\r
419db80b 450\r
6ac15f7c 451 if ((LocalTokenNumber & PCD_TYPE_ALL_SET) == (PCD_TYPE_HII|PCD_TYPE_STRING)) {\r
419db80b
BF
452 //\r
453 // If a HII type PCD's datum type is VOID*, the DefaultValueOffset is the index of \r
454 // string array in string table.\r
455 //\r
6cfc7292 456 StringTableIdx = *(STRING_HEAD*)((UINT8 *) PcdDb + VariableHead->DefaultValueOffset); \r
6ac15f7c 457 VaraiableDefaultBuffer = (VOID *) (StringTable + StringTableIdx); \r
6ac15f7c 458 } else {\r
459 VaraiableDefaultBuffer = (UINT8 *) PcdDb + VariableHead->DefaultValueOffset;\r
419db80b
BF
460 }\r
461 Status = GetHiiVariable (Guid, Name, &Data, &DataSize);\r
462 if (Status == EFI_SUCCESS) {\r
463 if (GetSize == 0) {\r
0b1ef275 464 //\r
419db80b
BF
465 // It is a pointer type. So get the MaxSize reserved for\r
466 // this PCD entry.\r
0b1ef275 467 //\r
419db80b 468 GetPtrTypeSize (TmpTokenNumber, &GetSize);\r
6ac15f7c 469 }\r
419db80b
BF
470 //\r
471 // If the operation is successful, we copy the data\r
472 // to the default value buffer in the PCD Database.\r
473 // So that we can free the Data allocated in GetHiiVariable.\r
474 //\r
475 CopyMem (VaraiableDefaultBuffer, Data + VariableHead->Offset, GetSize);\r
476 FreePool (Data);\r
80408db0 477 }\r
419db80b 478 RetPtr = (VOID *) VaraiableDefaultBuffer;\r
80408db0 479 break;\r
480\r
481 case PCD_TYPE_STRING:\r
6cfc7292 482 StringTableIdx = *(STRING_HEAD*)((UINT8 *) PcdDb + Offset);\r
1fef733c 483 RetPtr = (VOID *) (StringTable + StringTableIdx);\r
80408db0 484 break;\r
485\r
486 case PCD_TYPE_DATA:\r
487 RetPtr = (VOID *) ((UINT8 *) PcdDb + Offset);\r
488 break;\r
489\r
490 default:\r
491 ASSERT (FALSE);\r
492 break;\r
493 \r
494 }\r
495\r
496 EfiReleaseLock (&mPcdDatabaseLock);\r
419db80b 497\r
80408db0 498 return RetPtr;\r
419db80b 499\r
80408db0 500}\r
501\r
2ab6330e 502/**\r
503 Register the callback function for a PCD entry.\r
504\r
505 This routine will register a callback function to a PCD entry by given token number\r
506 and token space guid.\r
507 \r
508 @param TokenNumber PCD token's number, it is autogened by build tools.\r
509 @param Guid PCD token space's guid, \r
510 if not NULL, this PCD is dynamicEx type PCD.\r
511 @param CallBackFunction Callback function pointer\r
80408db0 512\r
2ab6330e 513 @return EFI_SUCCESS Always success for registering callback function.\r
80408db0 514\r
2ab6330e 515**/\r
80408db0 516EFI_STATUS\r
517DxeRegisterCallBackWorker (\r
518 IN UINTN TokenNumber,\r
2ab6330e 519 IN CONST EFI_GUID *Guid, OPTIONAL\r
80408db0 520 IN PCD_PROTOCOL_CALLBACK CallBackFunction\r
521)\r
522{\r
523 CALLBACK_FN_ENTRY *FnTableEntry;\r
524 LIST_ENTRY *ListHead;\r
525 LIST_ENTRY *ListNode;\r
526\r
527 if (Guid != NULL) {\r
528 TokenNumber = GetExPcdTokenNumber (Guid, (UINT32) TokenNumber);\r
529 }\r
530\r
531 //\r
532 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.\r
533 // We have to decrement TokenNumber by 1 to make it usable\r
b07a5b68 534 // as the array index of mCallbackFnTable[].\r
80408db0 535 //\r
b07a5b68 536 ListHead = &mCallbackFnTable[TokenNumber - 1];\r
80408db0 537 ListNode = GetFirstNode (ListHead);\r
538\r
539 while (ListNode != ListHead) {\r
540 FnTableEntry = CR_FNENTRY_FROM_LISTNODE(ListNode, CALLBACK_FN_ENTRY, Node);\r
541\r
542 if (FnTableEntry->CallbackFn == CallBackFunction) {\r
543 //\r
544 // We only allow a Callback function to be register once\r
545 // for a TokenNumber. So just return EFI_SUCCESS\r
546 //\r
547 return EFI_SUCCESS;\r
548 }\r
549 ListNode = GetNextNode (ListHead, ListNode);\r
550 }\r
551\r
552 FnTableEntry = AllocatePool (sizeof(CALLBACK_FN_ENTRY));\r
553 ASSERT (FnTableEntry != NULL);\r
554\r
555 FnTableEntry->CallbackFn = CallBackFunction;\r
556 InsertTailList (ListHead, &FnTableEntry->Node);\r
557 \r
558 return EFI_SUCCESS;\r
559}\r
560\r
2ab6330e 561/**\r
562 UnRegister the callback function for a PCD entry.\r
80408db0 563\r
2ab6330e 564 This routine will unregister a callback function to a PCD entry by given token number\r
565 and token space guid.\r
80408db0 566\r
2ab6330e 567 @param TokenNumber PCD token's number, it is autogened by build tools.\r
568 @param Guid PCD token space's guid.\r
569 if not NULL, this PCD is dynamicEx type PCD.\r
570 @param CallBackFunction Callback function pointer\r
80408db0 571\r
2ab6330e 572 @retval EFI_SUCCESS Callback function is success to be unregister.\r
573 @retval EFI_INVALID_PARAMETER Can not find the PCD entry by given token number.\r
574**/\r
80408db0 575EFI_STATUS\r
576DxeUnRegisterCallBackWorker (\r
577 IN UINTN TokenNumber,\r
2ab6330e 578 IN CONST EFI_GUID *Guid, OPTIONAL\r
80408db0 579 IN PCD_PROTOCOL_CALLBACK CallBackFunction\r
580)\r
581{\r
582 CALLBACK_FN_ENTRY *FnTableEntry;\r
583 LIST_ENTRY *ListHead;\r
584 LIST_ENTRY *ListNode;\r
585\r
586 if (Guid != NULL) {\r
587 TokenNumber = GetExPcdTokenNumber (Guid, (UINT32) TokenNumber);\r
588 }\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
b07a5b68 593 // as the array index of mCallbackFnTable[].\r
80408db0 594 //\r
b07a5b68 595 ListHead = &mCallbackFnTable[TokenNumber - 1];\r
80408db0 596 ListNode = GetFirstNode (ListHead);\r
597\r
598 while (ListNode != ListHead) {\r
599 FnTableEntry = CR_FNENTRY_FROM_LISTNODE(ListNode, CALLBACK_FN_ENTRY, Node);\r
600\r
601 if (FnTableEntry->CallbackFn == CallBackFunction) {\r
602 //\r
603 // We only allow a Callback function to be register once\r
604 // for a TokenNumber. So we can safely remove the Node from\r
605 // the Link List and return EFI_SUCCESS.\r
606 //\r
607 RemoveEntryList (ListNode);\r
608 FreePool (FnTableEntry);\r
609 \r
610 return EFI_SUCCESS;\r
611 }\r
612 ListNode = GetNextNode (ListHead, ListNode);\r
613 }\r
614\r
615 return EFI_INVALID_PARAMETER;\r
616}\r
617\r
2ab6330e 618/**\r
619 Get next token number in given token space.\r
620 \r
621 This routine is used for dynamicEx type PCD. It will firstly scan token space\r
622 table to get token space according to given token space guid. Then scan given \r
623 token number in found token space, if found, then return next token number in \r
624 this token space.\r
625\r
626 @param Guid Token space guid. Next token number will be scaned in \r
627 this token space.\r
628 @param TokenNumber Token number. \r
629 If PCD_INVALID_TOKEN_NUMBER, return first token number in \r
630 token space table.\r
631 If not PCD_INVALID_TOKEN_NUMBER, return next token number\r
632 in token space table.\r
633 @param GuidTable Token space guid table. It will be used for scan token space\r
634 by given token space guid.\r
635 @param SizeOfGuidTable The size of guid table.\r
636 @param ExMapTable DynamicEx token number mapping table.\r
637 @param SizeOfExMapTable The size of dynamicEx token number mapping table.\r
638\r
639 @retval EFI_NOT_FOUND Can not given token space or token number.\r
640 @retval EFI_SUCCESS Success to get next token number.\r
80408db0 641\r
2ab6330e 642**/\r
80408db0 643EFI_STATUS\r
644ExGetNextTokeNumber (\r
645 IN CONST EFI_GUID *Guid,\r
646 IN OUT UINTN *TokenNumber,\r
647 IN EFI_GUID *GuidTable,\r
648 IN UINTN SizeOfGuidTable,\r
649 IN DYNAMICEX_MAPPING *ExMapTable,\r
650 IN UINTN SizeOfExMapTable\r
651 )\r
652{\r
653 EFI_GUID *MatchGuid;\r
2ab6330e 654 UINTN Index;\r
80408db0 655 UINTN GuidTableIdx;\r
656 BOOLEAN Found;\r
419db80b 657 UINTN ExMapTableCount;\r
80408db0 658\r
2ab6330e 659 //\r
660 // Scan token space guid \r
661 // \r
80408db0 662 MatchGuid = ScanGuid (GuidTable, SizeOfGuidTable, Guid);\r
663 if (MatchGuid == NULL) {\r
664 return EFI_NOT_FOUND;\r
665 }\r
666\r
2ab6330e 667 //\r
668 // Find the token space table in dynamicEx mapping table.\r
669 //\r
80408db0 670 Found = FALSE;\r
671 GuidTableIdx = MatchGuid - GuidTable;\r
419db80b
BF
672 ExMapTableCount = SizeOfExMapTable / sizeof(ExMapTable[0]);\r
673 for (Index = 0; Index < ExMapTableCount; Index++) {\r
2ab6330e 674 if (ExMapTable[Index].ExGuidIndex == GuidTableIdx) {\r
80408db0 675 Found = TRUE;\r
676 break;\r
677 }\r
678 }\r
679\r
680 if (Found) {\r
2ab6330e 681 //\r
682 // If given token number is PCD_INVALID_TOKEN_NUMBER, then return the first\r
683 // token number in found token space.\r
684 //\r
80408db0 685 if (*TokenNumber == PCD_INVALID_TOKEN_NUMBER) {\r
2ab6330e 686 *TokenNumber = ExMapTable[Index].ExTokenNumber;\r
80408db0 687 return EFI_SUCCESS;\r
688 }\r
689\r
419db80b 690 for ( ; Index < ExMapTableCount; Index++) {\r
2ab6330e 691 if (ExMapTable[Index].ExTokenNumber == *TokenNumber) {\r
419db80b
BF
692 break;\r
693 }\r
694 }\r
695\r
696 while (Index < ExMapTableCount) {\r
697 Index++;\r
698 if (Index == ExMapTableCount) {\r
699 //\r
700 // Exceed the length of ExMap Table\r
701 //\r
702 *TokenNumber = PCD_INVALID_TOKEN_NUMBER;\r
703 return EFI_NOT_FOUND;\r
704 } else if (ExMapTable[Index].ExGuidIndex == GuidTableIdx) {\r
705 //\r
706 // Found the next match\r
707 //\r
708 *TokenNumber = ExMapTable[Index].ExTokenNumber;\r
709 return EFI_SUCCESS;\r
80408db0 710 }\r
711 }\r
712 }\r
419db80b 713\r
80408db0 714 return EFI_NOT_FOUND;\r
715}\r
80408db0 716\r
419db80b
BF
717/**\r
718 Find the PCD database.\r
719\r
720 @retval The base address of external PCD database binary.\r
721 @retval NULL Return NULL if not find.\r
722**/\r
723DXE_PCD_DATABASE *\r
724LocateExPcdBinary (\r
725 VOID\r
726) \r
727{\r
728 DXE_PCD_DATABASE *DxePcdDbBinary;\r
729 UINTN DxePcdDbSize;\r
730 EFI_STATUS Status;\r
731 \r
732 DxePcdDbBinary = NULL;\r
733 //\r
734 // Search the External Pcd database from one section of current FFS, \r
735 // and read it to memory\r
736 //\r
737 Status = GetSectionFromFfs (\r
738 EFI_SECTION_RAW,\r
739 0,\r
740 (VOID **) &DxePcdDbBinary,\r
741 &DxePcdDbSize\r
742 );\r
743 ASSERT_EFI_ERROR (Status);\r
744\r
745 //\r
746 // Check the first bytes (Header Signature Guid) and build version.\r
747 //\r
748 if (!CompareGuid ((VOID *)DxePcdDbBinary, &gPcdDataBaseSignatureGuid) ||\r
749 (DxePcdDbBinary->BuildVersion != PCD_SERVICE_DXE_VERSION)) {\r
750 ASSERT (FALSE);\r
751 }\r
752\r
753 return DxePcdDbBinary;\r
754}\r
80408db0 755\r
2ab6330e 756/**\r
757 Initialize the PCD database in DXE phase.\r
758 \r
759 PCD database in DXE phase also contains PCD database in PEI phase which is copied\r
760 from GUID Hob.\r
80408db0 761\r
2ab6330e 762**/\r
80408db0 763VOID\r
764BuildPcdDxeDataBase (\r
765 VOID\r
766 )\r
767{\r
768 PEI_PCD_DATABASE *PeiDatabase;\r
769 EFI_HOB_GUID_TYPE *GuidHob;\r
2ab6330e 770 UINTN Index;\r
419db80b
BF
771 UINT32 PcdDxeDbLen;\r
772 VOID *PcdDxeDb;\r
80408db0 773\r
774 GuidHob = GetFirstGuidHob (&gPcdDataBaseHobGuid);\r
775 if (GuidHob != NULL) {\r
776\r
80408db0 777 // \r
778 // If no PEIMs use dynamic Pcd Entry, the Pcd Service PEIM\r
779 // should not be included at all. So the GuidHob could\r
780 // be NULL. If it is NULL, we just copy over the DXE Default\r
781 // Value to PCD Database.\r
782 //\r
783 \r
784 PeiDatabase = (PEI_PCD_DATABASE *) GET_GUID_HOB_DATA (GuidHob);\r
785 //\r
419db80b 786 // Assign PCD Entries refereneced in PEI phase to PCD DATABASE\r
80408db0 787 //\r
419db80b 788 mPcdDatabase.PeiDb = PeiDatabase;\r
80408db0 789 }\r
790\r
791 //\r
419db80b 792 // Assign PCD Entries with default value to PCD DATABASE\r
80408db0 793 //\r
419db80b
BF
794 mPcdDatabase.DxeDb = LocateExPcdBinary ();\r
795 ASSERT(mPcdDatabase.DxeDb != NULL);\r
796 PcdDxeDbLen = mPcdDatabase.DxeDb->Length + mPcdDatabase.DxeDb->UninitDataBaseSize;\r
797 PcdDxeDb = AllocateZeroPool (PcdDxeDbLen);\r
7df09571 798 ASSERT (PcdDxeDb != NULL);\r
419db80b
BF
799 CopyMem (PcdDxeDb, mPcdDatabase.DxeDb, mPcdDatabase.DxeDb->Length);\r
800 FreePool (mPcdDatabase.DxeDb);\r
801 mPcdDatabase.DxeDb = PcdDxeDb;\r
80408db0 802\r
419db80b
BF
803 //\r
804 // Initialized the external PCD database local variables\r
805 //\r
806 mPeiLocalTokenCount = mPcdDatabase.PeiDb->LocalTokenCount;\r
807 mDxeLocalTokenCount = mPcdDatabase.DxeDb->LocalTokenCount;\r
808\r
809 mPeiExMapppingTableSize = mPcdDatabase.PeiDb->ExTokenCount * sizeof (DYNAMICEX_MAPPING);\r
810 mDxeExMapppingTableSize = mPcdDatabase.DxeDb->ExTokenCount * sizeof (DYNAMICEX_MAPPING);\r
811 mPeiGuidTableSize = mPcdDatabase.PeiDb->GuidTableCount * sizeof(GUID);\r
812 mDxeGuidTableSize = mPcdDatabase.DxeDb->GuidTableCount * sizeof (GUID);\r
813\r
814 mPcdTotalTokenCount = mPeiLocalTokenCount + mDxeLocalTokenCount;\r
815 mPeiNexTokenCount = mPeiLocalTokenCount - mPcdDatabase.PeiDb->ExTokenCount;\r
816 mDxeNexTokenCount = mDxeLocalTokenCount - mPcdDatabase.DxeDb->ExTokenCount; \r
817\r
818 mPeiExMapTableEmpty = (mPcdDatabase.PeiDb->ExTokenCount == 0) ? TRUE : FALSE;\r
819 mDxeExMapTableEmpty = (mPcdDatabase.DxeDb->ExTokenCount == 0) ? TRUE : FALSE;\r
820 mPeiDatabaseEmpty = (mPeiLocalTokenCount == 0) ? TRUE : FALSE;\r
821\r
822 TmpTokenSpaceBufferCount = mPcdDatabase.PeiDb->ExTokenCount + mPcdDatabase.DxeDb->ExTokenCount;\r
823 TmpTokenSpaceBuffer = (EFI_GUID **)AllocateZeroPool(TmpTokenSpaceBufferCount * sizeof (EFI_GUID *));\r
80408db0 824\r
825 //\r
826 // Initialized the Callback Function Table\r
827 //\r
419db80b 828 mCallbackFnTable = AllocateZeroPool (mPcdTotalTokenCount * sizeof (LIST_ENTRY));\r
3fd8027e 829 ASSERT(mCallbackFnTable != NULL);\r
419db80b
BF
830\r
831 //\r
80408db0 832 // EBC compiler is very choosy. It may report warning about comparison\r
833 // between UINTN and 0 . So we add 1 in each size of the \r
834 // comparison.\r
419db80b
BF
835 //\r
836 for (Index = 0; Index + 1 < mPcdTotalTokenCount + 1; Index++) {\r
2ab6330e 837 InitializeListHead (&mCallbackFnTable[Index]);\r
80408db0 838 }\r
80408db0 839}\r
840\r
2ab6330e 841/**\r
842 Get Variable which contains HII type PCD entry.\r
80408db0 843\r
2ab6330e 844 @param VariableGuid Variable's guid\r
845 @param VariableName Variable's unicode name string\r
846 @param VariableData Variable's data pointer, \r
847 @param VariableSize Variable's size.\r
80408db0 848\r
2ab6330e 849 @return the status of gRT->GetVariable\r
850**/\r
80408db0 851EFI_STATUS\r
852GetHiiVariable (\r
853 IN EFI_GUID *VariableGuid,\r
854 IN UINT16 *VariableName,\r
855 OUT UINT8 **VariableData,\r
856 OUT UINTN *VariableSize\r
857 )\r
858{\r
859 UINTN Size;\r
860 EFI_STATUS Status;\r
861 UINT8 *Buffer;\r
862\r
863 Size = 0;\r
864 Buffer = NULL;\r
865 \r
2ab6330e 866 //\r
867 // Firstly get the real size of HII variable\r
868 //\r
80408db0 869 Status = gRT->GetVariable (\r
870 (UINT16 *)VariableName,\r
871 VariableGuid,\r
872 NULL,\r
873 &Size,\r
874 Buffer\r
875 );\r
876 \r
2ab6330e 877 //\r
878 // Allocate buffer to hold whole variable data according to variable size.\r
879 //\r
80408db0 880 if (Status == EFI_BUFFER_TOO_SMALL) {\r
881 Buffer = (UINT8 *) AllocatePool (Size);\r
882\r
883 ASSERT (Buffer != NULL);\r
884\r
885 Status = gRT->GetVariable (\r
886 VariableName,\r
887 VariableGuid,\r
888 NULL,\r
889 &Size,\r
890 Buffer\r
891 );\r
892\r
893 ASSERT (Status == EFI_SUCCESS);\r
894 *VariableData = Buffer;\r
895 *VariableSize = Size;\r
0b1ef275
LG
896 } else {\r
897 //\r
898 // Use Default Data only when variable is not found. \r
899 // For other error status, correct data can't be got, and trig ASSERT().\r
900 //\r
901 ASSERT (Status == EFI_NOT_FOUND);\r
80408db0 902 }\r
903\r
904 return Status;\r
905}\r
906\r
2ab6330e 907/**\r
908 Find the local token number according to system SKU ID.\r
909\r
910 @param LocalTokenNumber PCD token number\r
911 @param Size The size of PCD entry.\r
912 @param IsPeiDb If TRUE, the PCD entry is initialized in PEI phase.\r
913 If False, the PCD entry is initialized in DXE phase.\r
914\r
915 @return Token number according to system SKU ID.\r
80408db0 916\r
2ab6330e 917**/\r
80408db0 918UINT32\r
919GetSkuEnabledTokenNumber (\r
920 UINT32 LocalTokenNumber,\r
921 UINTN Size,\r
922 BOOLEAN IsPeiDb\r
923 ) \r
924{\r
925 SKU_HEAD *SkuHead;\r
926 SKU_ID *SkuIdTable;\r
2ab6330e 927 INTN Index;\r
80408db0 928 UINT8 *Value;\r
80408db0 929 UINT8 *PcdDb;\r
419db80b 930 BOOLEAN FoundSku;\r
80408db0 931\r
932 ASSERT ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0);\r
933\r
419db80b 934 PcdDb = IsPeiDb ? (UINT8 *) mPcdDatabase.PeiDb : (UINT8 *) mPcdDatabase.DxeDb;\r
80408db0 935\r
936 SkuHead = (SKU_HEAD *) (PcdDb + (LocalTokenNumber & PCD_DATABASE_OFFSET_MASK));\r
937 Value = (UINT8 *) (PcdDb + SkuHead->SkuDataStartOffset); \r
938\r
419db80b 939 SkuIdTable = (SKU_ID *)(PcdDb + SkuHead->SkuIdTableOffset);\r
2ab6330e 940 //\r
941 // Find the current system's SKU ID entry in SKU ID table.\r
942 //\r
419db80b 943 FoundSku = FALSE;\r
2ab6330e 944 for (Index = 0; Index < SkuIdTable[0]; Index++) {\r
419db80b
BF
945 if (mPcdDatabase.PeiDb->SystemSkuId == SkuIdTable[Index + 1]) {\r
946 FoundSku = TRUE;\r
80408db0 947 break;\r
948 }\r
949 }\r
419db80b
BF
950 \r
951 //\r
952 // Find the default SKU ID entry in SKU ID table.\r
953 //\r
954 \r
955 if(!FoundSku) {\r
956 for (Index = 0; Index < SkuIdTable[0]; Index++) {\r
957 if (0 == SkuIdTable[Index + 1]) {\r
958 break;\r
959 }\r
960 }\r
961 }\r
2ab6330e 962 ASSERT (Index < SkuIdTable[0]);\r
80408db0 963\r
964 switch (LocalTokenNumber & PCD_TYPE_ALL_SET) {\r
965 case PCD_TYPE_VPD:\r
2ab6330e 966 Value = (UINT8 *) &(((VPD_HEAD *) Value)[Index]);\r
80408db0 967 return (UINT32) ((Value - PcdDb) | PCD_TYPE_VPD);\r
968\r
969 case PCD_TYPE_HII:\r
2ab6330e 970 Value = (UINT8 *) &(((VARIABLE_HEAD *) Value)[Index]);\r
80408db0 971 return (UINT32) ((Value - PcdDb) | PCD_TYPE_HII);\r
972\r
419db80b
BF
973 case PCD_TYPE_HII|PCD_TYPE_STRING:\r
974 Value = (UINT8 *) &(((VARIABLE_HEAD *) Value)[Index]);\r
975 return (UINT32) ((Value - PcdDb) | PCD_TYPE_HII | PCD_TYPE_STRING);\r
976\r
80408db0 977 case PCD_TYPE_STRING:\r
2ab6330e 978 Value = (UINT8 *) &(((STRING_HEAD *) Value)[Index]);\r
80408db0 979 return (UINT32) ((Value - PcdDb) | PCD_TYPE_STRING);\r
980 \r
981 case PCD_TYPE_DATA:\r
2ab6330e 982 Value += Size * Index;\r
419db80b 983 return (UINT32) ((Value - PcdDb) | PCD_TYPE_DATA);\r
80408db0 984\r
985 default:\r
986 ASSERT (FALSE);\r
987 }\r
988\r
989 ASSERT (FALSE);\r
990\r
991 return 0;\r
992 \r
993}\r
994\r
2ab6330e 995/**\r
996 Invoke the callback function when dynamic PCD entry was set, if this PCD entry \r
997 has registered callback function.\r
80408db0 998\r
2ab6330e 999 @param ExTokenNumber DynamicEx PCD's token number, if this PCD entry is dyanmicEx\r
1000 type PCD.\r
1001 @param Guid DynamicEx PCD's guid, if this PCD entry is dynamicEx type\r
1002 PCD.\r
1003 @param TokenNumber PCD token number generated by build tools.\r
1004 @param Data Value want to be set for this PCD entry\r
1005 @param Size The size of value\r
80408db0 1006\r
2ab6330e 1007**/\r
80408db0 1008VOID\r
1009InvokeCallbackOnSet (\r
1010 UINT32 ExTokenNumber,\r
1011 CONST EFI_GUID *Guid, OPTIONAL\r
1012 UINTN TokenNumber,\r
1013 VOID *Data,\r
1014 UINTN Size\r
1015 )\r
1016{\r
1017 CALLBACK_FN_ENTRY *FnTableEntry;\r
1018 LIST_ENTRY *ListHead;\r
1019 LIST_ENTRY *ListNode;\r
1020\r
1021 //\r
1022 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.\r
1023 // We have to decrement TokenNumber by 1 to make it usable\r
b07a5b68 1024 // as the array index of mCallbackFnTable[].\r
80408db0 1025 //\r
b07a5b68 1026 ListHead = &mCallbackFnTable[TokenNumber - 1];\r
80408db0 1027 ListNode = GetFirstNode (ListHead);\r
1028\r
1029 while (ListNode != ListHead) {\r
b07a5b68 1030 FnTableEntry = CR_FNENTRY_FROM_LISTNODE (ListNode, CALLBACK_FN_ENTRY, Node);\r
80408db0 1031\r
1032 FnTableEntry->CallbackFn(Guid, \r
1033 (Guid == NULL) ? TokenNumber : ExTokenNumber,\r
1034 Data,\r
1035 Size);\r
1036 \r
1037 ListNode = GetNextNode (ListHead, ListNode);\r
1038 }\r
1039 \r
1040 return;\r
1041}\r
1042\r
1043\r
2ab6330e 1044/**\r
1045 Wrapper function for setting non-pointer type value for a PCD entry.\r
1046\r
1047 @param TokenNumber Pcd token number autogenerated by build tools.\r
1048 @param Data Value want to be set for PCD entry\r
1049 @param Size Size of value.\r
1050\r
1051 @return status of SetWorker.\r
1052\r
1053**/\r
80408db0 1054EFI_STATUS\r
1055SetValueWorker (\r
1056 IN UINTN TokenNumber,\r
1057 IN VOID *Data,\r
1058 IN UINTN Size\r
1059 )\r
1060{\r
1061 return SetWorker (TokenNumber, Data, &Size, FALSE);\r
1062}\r
1063\r
1064\r
2ab6330e 1065/**\r
1066 Set value for an PCD entry\r
1067\r
1068 @param TokenNumber Pcd token number autogenerated by build tools.\r
1069 @param Data Value want to be set for PCD entry\r
1070 @param Size Size of value.\r
1071 @param PtrType If TRUE, the type of PCD entry's value is Pointer.\r
1072 If False, the type of PCD entry's value is not Pointer.\r
1073\r
1074 @retval EFI_INVALID_PARAMETER If this PCD type is VPD, VPD PCD can not be set.\r
1075 @retval EFI_INVALID_PARAMETER If Size can not be set to size table.\r
149fb6d6 1076 @retval EFI_INVALID_PARAMETER If Size of non-Ptr type PCD does not match the size information in PCD database. \r
2ab6330e 1077 @retval EFI_NOT_FOUND If value type of PCD entry is intergrate, but not in\r
1078 range of UINT8, UINT16, UINT32, UINT64\r
1079 @retval EFI_NOT_FOUND Can not find the PCD type according to token number. \r
1080**/\r
80408db0 1081EFI_STATUS\r
1082SetWorker (\r
1083 IN UINTN TokenNumber,\r
1084 IN VOID *Data,\r
1085 IN OUT UINTN *Size,\r
1086 IN BOOLEAN PtrType\r
1087 )\r
1088{\r
80408db0 1089 BOOLEAN IsPeiDb;\r
1090 UINT32 LocalTokenNumber;\r
1091 EFI_GUID *GuidTable;\r
d0965169 1092 UINT8 *StringTable;\r
80408db0 1093 EFI_GUID *Guid;\r
1094 UINT16 *Name;\r
1095 UINTN VariableOffset;\r
1096 VOID *InternalData;\r
1097 VARIABLE_HEAD *VariableHead;\r
1098 UINTN Offset;\r
1099 UINT8 *PcdDb;\r
1100 EFI_STATUS Status;\r
1101 UINTN MaxSize;\r
1102 UINTN TmpTokenNumber;\r
1103\r
80408db0 1104 //\r
1105 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.\r
1106 // We have to decrement TokenNumber by 1 to make it usable\r
1107 // as the array index.\r
1108 //\r
1109 TokenNumber--;\r
1110\r
1111 TmpTokenNumber = TokenNumber;\r
1112 \r
2ab6330e 1113 //\r
80408db0 1114 // EBC compiler is very choosy. It may report warning about comparison\r
1115 // between UINTN and 0 . So we add 1 in each size of the \r
1116 // comparison.\r
2ab6330e 1117 //\r
419db80b 1118 ASSERT (TokenNumber + 1 < mPcdTotalTokenCount + 1);\r
80408db0 1119\r
8ec8bed4 1120 if (PtrType) {\r
64894410
LG
1121 //\r
1122 // Get MaxSize first, then check new size with max buffer size.\r
1123 //\r
1124 GetPtrTypeSize (TokenNumber, &MaxSize);\r
1125 if (*Size > MaxSize) {\r
cb40609c 1126 *Size = MaxSize;\r
8ec8bed4 1127 return EFI_INVALID_PARAMETER;\r
1128 }\r
1129 } else {\r
1130 if (*Size != DxePcdGetSize (TokenNumber + 1)) {\r
1131 return EFI_INVALID_PARAMETER;\r
1132 }\r
80408db0 1133 }\r
b07a5b68 1134\r
2ab6330e 1135 //\r
80408db0 1136 // EBC compiler is very choosy. It may report warning about comparison\r
1137 // between UINTN and 0 . So we add 1 in each size of the \r
1138 // comparison.\r
2ab6330e 1139 //\r
419db80b
BF
1140 if ((TokenNumber + 1 < mPeiNexTokenCount + 1) ||\r
1141 (TokenNumber + 1 >= mPeiLocalTokenCount + 1 && TokenNumber + 1 < (mPeiLocalTokenCount + mDxeNexTokenCount + 1))) {\r
b07a5b68 1142 InvokeCallbackOnSet (0, NULL, TokenNumber + 1, Data, *Size);\r
1143 }\r
80408db0 1144\r
b07a5b68 1145 //\r
1146 // Aquire lock to prevent reentrance from TPL_CALLBACK level\r
1147 //\r
1148 EfiAcquireLock (&mPcdDatabaseLock);\r
80408db0 1149\r
2ab6330e 1150 //\r
80408db0 1151 // EBC compiler is very choosy. It may report warning about comparison\r
1152 // between UINTN and 0 . So we add 1 in each size of the \r
1153 // comparison.\r
2ab6330e 1154 //\r
419db80b 1155 IsPeiDb = (BOOLEAN) ((TokenNumber + 1 < mPeiLocalTokenCount + 1) ? TRUE : FALSE);\r
b07a5b68 1156\r
96d6d004 1157 LocalTokenNumber = GetLocalTokenNumber (IsPeiDb, TokenNumber + 1);\r
80408db0 1158\r
1159 Offset = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK;\r
1160\r
419db80b 1161 PcdDb = IsPeiDb ? ((UINT8 *) mPcdDatabase.PeiDb) : ((UINT8 *) mPcdDatabase.DxeDb);\r
80408db0 1162\r
309e3122 1163 if (IsPeiDb) {\r
419db80b 1164 StringTable = (UINT8 *) ((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->StringTableOffset);\r
309e3122 1165 } else {\r
419db80b 1166 StringTable = (UINT8 *) ((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->StringTableOffset);\r
309e3122 1167 }\r
1168\r
80408db0 1169 \r
1170 InternalData = PcdDb + Offset;\r
1171\r
1172 switch (LocalTokenNumber & PCD_TYPE_ALL_SET) {\r
1173 case PCD_TYPE_VPD:\r
1174 ASSERT (FALSE);\r
1175 Status = EFI_INVALID_PARAMETER;\r
1176 break;\r
1177 \r
1178 case PCD_TYPE_STRING:\r
1179 if (SetPtrTypeSize (TmpTokenNumber, Size)) {\r
6cfc7292 1180 CopyMem (StringTable + *((STRING_HEAD *)InternalData), Data, *Size);\r
80408db0 1181 Status = EFI_SUCCESS;\r
1182 } else {\r
1183 Status = EFI_INVALID_PARAMETER;\r
1184 }\r
1185 break;\r
1186\r
6ac15f7c 1187 case PCD_TYPE_HII|PCD_TYPE_STRING:\r
80408db0 1188 case PCD_TYPE_HII:\r
1189 if (PtrType) {\r
1190 if (!SetPtrTypeSize (TmpTokenNumber, Size)) {\r
1191 Status = EFI_INVALID_PARAMETER;\r
1192 break;\r
1193 }\r
1194 }\r
419db80b 1195\r
309e3122 1196 if (IsPeiDb) {\r
419db80b 1197 GuidTable = (EFI_GUID *) ((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->GuidTableOffset);\r
309e3122 1198 } else {\r
419db80b 1199 GuidTable = (EFI_GUID *) ((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->GuidTableOffset);\r
309e3122 1200 }\r
419db80b 1201\r
80408db0 1202 VariableHead = (VARIABLE_HEAD *) (PcdDb + Offset);\r
419db80b 1203\r
1fef733c 1204 Guid = GuidTable + VariableHead->GuidTableIndex;\r
d0965169 1205 Name = (UINT16*) (StringTable + VariableHead->StringIndex);\r
80408db0 1206 VariableOffset = VariableHead->Offset;\r
80408db0 1207 Status = SetHiiVariable (Guid, Name, Data, *Size, VariableOffset);\r
419db80b 1208\r
80408db0 1209 if (EFI_NOT_FOUND == Status) {\r
6ac15f7c 1210 if ((LocalTokenNumber & PCD_TYPE_ALL_SET) == (PCD_TYPE_HII|PCD_TYPE_STRING)) {\r
1211 CopyMem (\r
6cfc7292 1212 StringTable + *(STRING_HEAD *)(PcdDb + VariableHead->DefaultValueOffset),\r
6ac15f7c 1213 Data,\r
1214 *Size\r
1215 );\r
1216 } else {\r
1217 CopyMem (PcdDb + VariableHead->DefaultValueOffset, Data, *Size);\r
1218 } \r
80408db0 1219 Status = EFI_SUCCESS;\r
6ac15f7c 1220 }\r
80408db0 1221 break;\r
1222 \r
1223 case PCD_TYPE_DATA:\r
1224 if (PtrType) {\r
1225 if (SetPtrTypeSize (TmpTokenNumber, Size)) {\r
1226 CopyMem (InternalData, Data, *Size);\r
1227 Status = EFI_SUCCESS;\r
1228 } else {\r
1229 Status = EFI_INVALID_PARAMETER;\r
1230 }\r
1231 break;\r
1232 }\r
1233\r
1234 Status = EFI_SUCCESS;\r
1235 switch (*Size) {\r
1236 case sizeof(UINT8):\r
1237 *((UINT8 *) InternalData) = *((UINT8 *) Data);\r
1238 break;\r
1239\r
1240 case sizeof(UINT16):\r
1241 *((UINT16 *) InternalData) = *((UINT16 *) Data);\r
1242 break;\r
1243\r
1244 case sizeof(UINT32):\r
1245 *((UINT32 *) InternalData) = *((UINT32 *) Data);\r
1246 break;\r
1247\r
1248 case sizeof(UINT64):\r
1249 *((UINT64 *) InternalData) = *((UINT64 *) Data);\r
1250 break;\r
1251\r
1252 default:\r
1253 ASSERT (FALSE);\r
1254 Status = EFI_NOT_FOUND;\r
1255 break;\r
1256 }\r
1257 break;\r
1258\r
1259 default:\r
1260 ASSERT (FALSE);\r
1261 Status = EFI_NOT_FOUND;\r
1262 break;\r
1263 }\r
1264\r
1265 EfiReleaseLock (&mPcdDatabaseLock);\r
1266 \r
1267 return Status;\r
1268}\r
1269\r
2ab6330e 1270/**\r
1271 Wrapper function for get PCD value for dynamic-ex PCD.\r
80408db0 1272\r
2ab6330e 1273 @param Guid Token space guid for dynamic-ex PCD.\r
3fd8027e 1274 @param ExTokenNumber Token number for dynamic-ex PCD.\r
2ab6330e 1275 @param GetSize The size of dynamic-ex PCD value.\r
80408db0 1276\r
2ab6330e 1277 @return PCD entry in PCD database.\r
80408db0 1278\r
2ab6330e 1279**/\r
80408db0 1280VOID *\r
1281ExGetWorker (\r
1282 IN CONST EFI_GUID *Guid,\r
1283 IN UINTN ExTokenNumber,\r
1284 IN UINTN GetSize\r
1285 ) \r
1286{\r
1287 return GetWorker(GetExPcdTokenNumber (Guid, (UINT32) ExTokenNumber), GetSize);\r
1288}\r
1289\r
2ab6330e 1290/**\r
1291 Wrapper function for set PCD value for non-Pointer type dynamic-ex PCD.\r
80408db0 1292\r
2ab6330e 1293 @param ExTokenNumber Token number for dynamic-ex PCD.\r
1294 @param Guid Token space guid for dynamic-ex PCD.\r
1295 @param Data Value want to be set.\r
1296 @param SetSize The size of value.\r
80408db0 1297\r
2ab6330e 1298 @return status of ExSetWorker().\r
80408db0 1299\r
2ab6330e 1300**/\r
80408db0 1301EFI_STATUS\r
1302ExSetValueWorker (\r
1303 IN UINTN ExTokenNumber,\r
1304 IN CONST EFI_GUID *Guid,\r
1305 IN VOID *Data,\r
1306 IN UINTN SetSize\r
1307 )\r
1308{\r
1309 return ExSetWorker (ExTokenNumber, Guid, Data, &SetSize, FALSE);\r
1310}\r
1311\r
2ab6330e 1312/**\r
419db80b 1313 Set value for a dynamic-ex PCD entry.\r
2ab6330e 1314 \r
1315 This routine find the local token number according to dynamic-ex PCD's token \r
1316 space guid and token number firstly, and invoke callback function if this PCD\r
1317 entry registered callback function. Finally, invoken general SetWorker to set\r
1318 PCD value.\r
1319 \r
1320 @param ExTokenNumber Dynamic-ex PCD token number.\r
1321 @param Guid Token space guid for dynamic-ex PCD.\r
1322 @param Data PCD value want to be set\r
1323 @param SetSize Size of value.\r
1324 @param PtrType If TRUE, this PCD entry is pointer type.\r
1325 If FALSE, this PCD entry is not pointer type.\r
1326\r
1327 @return status of SetWorker().\r
80408db0 1328\r
2ab6330e 1329**/\r
80408db0 1330EFI_STATUS\r
1331ExSetWorker (\r
1332 IN UINTN ExTokenNumber,\r
1333 IN CONST EFI_GUID *Guid,\r
1334 IN VOID *Data,\r
1335 IN OUT UINTN *SetSize,\r
1336 IN BOOLEAN PtrType\r
1337 )\r
1338{\r
1339 UINTN TokenNumber;\r
1340 \r
1341 TokenNumber = GetExPcdTokenNumber (Guid, (UINT32) ExTokenNumber);\r
1342\r
1343 InvokeCallbackOnSet ((UINT32) ExTokenNumber, Guid, TokenNumber, Data, *SetSize);\r
1344\r
1345 return SetWorker (TokenNumber, Data, SetSize, PtrType);\r
1346\r
1347}\r
1348\r
2ab6330e 1349/**\r
1350 Set value for HII-type PCD.\r
80408db0 1351\r
2ab6330e 1352 A HII-type PCD's value is stored in a variable. Setting/Getting the value of \r
1353 HII-type PCD is to visit this variable.\r
1354 \r
1355 @param VariableGuid Guid of variable which stored value of a HII-type PCD.\r
1356 @param VariableName Unicode name of variable which stored value of a HII-type PCD.\r
1357 @param Data Value want to be set.\r
1358 @param DataSize Size of value\r
1359 @param Offset Value offset of HII-type PCD in variable.\r
80408db0 1360\r
2ab6330e 1361 @return status of GetVariable()/SetVariable().\r
80408db0 1362\r
2ab6330e 1363**/\r
80408db0 1364EFI_STATUS\r
1365SetHiiVariable (\r
1366 IN EFI_GUID *VariableGuid,\r
1367 IN UINT16 *VariableName,\r
1368 IN CONST VOID *Data,\r
1369 IN UINTN DataSize,\r
1370 IN UINTN Offset\r
1371 )\r
1372{\r
1373 UINTN Size;\r
1374 VOID *Buffer;\r
1375 EFI_STATUS Status;\r
1376 UINT32 Attribute;\r
b13151ff 1377 UINTN SetSize;\r
80408db0 1378\r
1379 Size = 0;\r
b13151ff 1380 SetSize = 0;\r
80408db0 1381\r
746be876 1382 //\r
1383 // Try to get original variable size information.\r
1384 //\r
80408db0 1385 Status = gRT->GetVariable (\r
1386 (UINT16 *)VariableName,\r
1387 VariableGuid,\r
1388 NULL,\r
1389 &Size,\r
1390 NULL\r
1391 );\r
b13151ff 1392 \r
80408db0 1393 if (Status == EFI_BUFFER_TOO_SMALL) {\r
746be876 1394 //\r
1395 // Patch new PCD's value to offset in given HII variable.\r
1396 //\r
b13151ff
LG
1397 if (Size >= (DataSize + Offset)) {\r
1398 SetSize = Size;\r
1399 } else {\r
1400 SetSize = DataSize + Offset;\r
1401 }\r
1402 Buffer = AllocatePool (SetSize);\r
80408db0 1403 ASSERT (Buffer != NULL);\r
1404\r
1405 Status = gRT->GetVariable (\r
1406 VariableName,\r
1407 VariableGuid,\r
1408 &Attribute,\r
1409 &Size,\r
1410 Buffer\r
1411 );\r
1412 \r
1413 ASSERT_EFI_ERROR (Status);\r
1414\r
1415 CopyMem ((UINT8 *)Buffer + Offset, Data, DataSize);\r
1416\r
1417 Status = gRT->SetVariable (\r
1418 VariableName,\r
1419 VariableGuid,\r
1420 Attribute,\r
b13151ff 1421 SetSize,\r
80408db0 1422 Buffer\r
1423 );\r
1424\r
1425 FreePool (Buffer);\r
1426 return Status;\r
746be876 1427 } else if (Status == EFI_NOT_FOUND) {\r
1428 //\r
1429 // If variable does not exist, a new variable need to be created.\r
1430 //\r
1431 \r
1432 Size = Offset + DataSize;\r
1433 \r
1434 Buffer = AllocateZeroPool (Size);\r
1435 ASSERT (Buffer != NULL);\r
1436 \r
1437 CopyMem ((UINT8 *)Buffer + Offset, Data, DataSize);\r
1438 \r
1439 Status = gRT->SetVariable (\r
1440 VariableName,\r
1441 VariableGuid,\r
1442 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
1443 Size,\r
1444 Buffer\r
1445 );\r
1446\r
1447 FreePool (Buffer);\r
1448 return Status; \r
1449 }\r
80408db0 1450 \r
1451 //\r
746be876 1452 // If we drop to here, the value is failed to be written in to variable area\r
1453 // So, we will save the data in the PCD Database's volatile area.\r
80408db0 1454 //\r
1455 return Status;\r
1456}\r
1457\r
2ab6330e 1458/**\r
419db80b 1459 Get Token Number according to dynamic-ex PCD's {token space guid:token number}\r
80408db0 1460\r
2ab6330e 1461 A dynamic-ex type PCD, developer must provide pair of token space guid: token number\r
1462 in DEC file. PCD database maintain a mapping table that translate pair of {token\r
419db80b 1463 space guid: token number} to Token Number.\r
2ab6330e 1464 \r
1465 @param Guid Token space guid for dynamic-ex PCD entry.\r
b9982883 1466 @param ExTokenNumber Dynamic-ex PCD token number.\r
80408db0 1467\r
419db80b 1468 @return Token Number for dynamic-ex PCD.\r
80408db0 1469\r
2ab6330e 1470**/\r
80408db0 1471UINTN \r
1472GetExPcdTokenNumber (\r
1473 IN CONST EFI_GUID *Guid,\r
1474 IN UINT32 ExTokenNumber\r
1475 )\r
1476{\r
2ab6330e 1477 UINT32 Index;\r
80408db0 1478 DYNAMICEX_MAPPING *ExMap;\r
1479 EFI_GUID *GuidTable;\r
1480 EFI_GUID *MatchGuid;\r
1481 UINTN MatchGuidIdx;\r
1482\r
419db80b
BF
1483 if (!mPeiDatabaseEmpty) {\r
1484 ExMap = (DYNAMICEX_MAPPING *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->ExMapTableOffset);\r
1485 GuidTable = (EFI_GUID *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->GuidTableOffset);\r
1486\r
1487 MatchGuid = ScanGuid (GuidTable, mPeiGuidTableSize, Guid);\r
1488\r
80408db0 1489 if (MatchGuid != NULL) {\r
1490\r
1491 MatchGuidIdx = MatchGuid - GuidTable;\r
419db80b
BF
1492\r
1493 for (Index = 0; Index < mPeiExMapppingTableSize; Index++) {\r
2ab6330e 1494 if ((ExTokenNumber == ExMap[Index].ExTokenNumber) &&\r
1495 (MatchGuidIdx == ExMap[Index].ExGuidIndex)) {\r
419db80b 1496 return ExMap[Index].TokenNumber;\r
80408db0 1497 }\r
1498 }\r
1499 }\r
1500 }\r
80408db0 1501\r
419db80b
BF
1502 ExMap = (DYNAMICEX_MAPPING *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->ExMapTableOffset);\r
1503 GuidTable = (EFI_GUID *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->GuidTableOffset);\r
1504\r
1505 MatchGuid = ScanGuid (GuidTable, mDxeGuidTableSize, Guid);\r
80408db0 1506 //\r
1507 // We need to ASSERT here. If GUID can't be found in GuidTable, this is a\r
1508 // error in the BUILD system.\r
1509 //\r
1510 ASSERT (MatchGuid != NULL);\r
1511\r
1512 MatchGuidIdx = MatchGuid - GuidTable;\r
419db80b
BF
1513\r
1514 for (Index = 0; Index < mDxeExMapppingTableSize; Index++) {\r
2ab6330e 1515 if ((ExTokenNumber == ExMap[Index].ExTokenNumber) &&\r
1516 (MatchGuidIdx == ExMap[Index].ExGuidIndex)) {\r
419db80b 1517 return ExMap[Index].TokenNumber;\r
80408db0 1518 }\r
1519 }\r
1520\r
1521 ASSERT (FALSE);\r
1522\r
1523 return 0;\r
1524}\r
1525\r
2ab6330e 1526/**\r
3fd8027e 1527 Get SKU ID table from PCD database.\r
2ab6330e 1528\r
1529 @param LocalTokenNumberTableIdx Index of local token number in token number table.\r
419db80b
BF
1530 @param IsPeiDb If TRUE, the pcd entry is initialized in PEI phase,\r
1531 If FALSE, the pcd entry is initialized in DXE phase.\r
2ab6330e 1532 @return Pointer to SKU ID array table\r
1533\r
1534**/\r
80408db0 1535SKU_ID *\r
1536GetSkuIdArray (\r
1537 IN UINTN LocalTokenNumberTableIdx,\r
419db80b 1538 IN BOOLEAN IsPeiDb\r
80408db0 1539 )\r
1540{\r
1541 SKU_HEAD *SkuHead;\r
1542 UINTN LocalTokenNumber;\r
1543 UINT8 *Database;\r
1544\r
419db80b
BF
1545 if (IsPeiDb) {\r
1546 LocalTokenNumber = *((UINT32 *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->LocalTokenNumberTableOffset) + LocalTokenNumberTableIdx);\r
1547 Database = (UINT8 *) mPcdDatabase.PeiDb;\r
80408db0 1548 } else {\r
419db80b
BF
1549 LocalTokenNumber = *((UINT32 *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->LocalTokenNumberTableOffset) + LocalTokenNumberTableIdx);\r
1550 Database = (UINT8 *) mPcdDatabase.DxeDb;\r
80408db0 1551 }\r
1552\r
1553 ASSERT ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) != 0);\r
1554\r
1555 SkuHead = (SKU_HEAD *) ((UINT8 *)Database + (LocalTokenNumber & PCD_DATABASE_OFFSET_MASK));\r
1556\r
1557 return (SKU_ID *) (Database + SkuHead->SkuIdTableOffset);\r
1558 \r
1559}\r
1560\r
2ab6330e 1561/**\r
3d53ba8b 1562 Wrapper function of getting index of PCD entry in size table.\r
1563 \r
2ab6330e 1564 @param LocalTokenNumberTableIdx Index of this PCD in local token number table.\r
2ab6330e 1565 @param IsPeiDb If TRUE, the pcd entry is initialized in PEI phase,\r
1566 If FALSE, the pcd entry is initialized in DXE phase.\r
1567\r
1568 @return index of PCD entry in size table.\r
2ab6330e 1569**/\r
80408db0 1570UINTN\r
3d53ba8b 1571GetSizeTableIndex (\r
1572 IN UINTN LocalTokenNumberTableIdx,\r
1573 IN BOOLEAN IsPeiDb\r
80408db0 1574 )\r
1575{\r
3d53ba8b 1576 UINT32 *LocalTokenNumberTable;\r
1577 UINTN LocalTokenNumber;\r
1578 UINTN Index;\r
1579 UINTN SizeTableIdx;\r
1580 SKU_ID *SkuIdTable;\r
80408db0 1581 \r
3d53ba8b 1582 if (IsPeiDb) {\r
419db80b 1583 LocalTokenNumberTable = (UINT32 *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->LocalTokenNumberTableOffset);\r
3d53ba8b 1584 } else {\r
419db80b 1585 LocalTokenNumberTable = (UINT32 *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->LocalTokenNumberTableOffset);\r
3d53ba8b 1586 }\r
1587\r
80408db0 1588 SizeTableIdx = 0;\r
1589\r
3d53ba8b 1590 for (Index = 0; Index < LocalTokenNumberTableIdx; Index ++) {\r
2ab6330e 1591 LocalTokenNumber = LocalTokenNumberTable[Index];\r
80408db0 1592\r
1593 if ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER) {\r
1594 //\r
1595 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type \r
1596 // PCD entry.\r
1597 //\r
2ab6330e 1598 if ((LocalTokenNumber & PCD_TYPE_VPD) != 0) {\r
80408db0 1599 //\r
419db80b 1600 // We have only two entry for VPD enabled PCD entry:\r
80408db0 1601 // 1) MAX Size.\r
419db80b
BF
1602 // 2) Current Size\r
1603 // Current size is equal to MAX size.\r
80408db0 1604 //\r
419db80b 1605 SizeTableIdx += 2;\r
80408db0 1606 } else {\r
1607 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0) {\r
1608 //\r
1609 // We have only two entry for Non-Sku enabled PCD entry:\r
1610 // 1) MAX SIZE\r
1611 // 2) Current Size\r
1612 //\r
1613 SizeTableIdx += 2;\r
1614 } else {\r
1615 //\r
1616 // We have these entry for SKU enabled PCD entry\r
1617 // 1) MAX SIZE\r
1618 // 2) Current Size for each SKU_ID (It is equal to MaxSku).\r
1619 //\r
2ab6330e 1620 SkuIdTable = GetSkuIdArray (Index, IsPeiDb);\r
80408db0 1621 SizeTableIdx += (UINTN)*SkuIdTable + 1;\r
1622 }\r
1623 }\r
1624 }\r
1625\r
1626 }\r
1627\r
3d53ba8b 1628 return SizeTableIdx; \r
80408db0 1629}\r
1630\r
2ab6330e 1631/**\r
1632 Get size of POINTER type PCD value.\r
1633\r
1634 @param LocalTokenNumberTableIdx Index of local token number in local token number table.\r
1635 @param MaxSize Maxmium size of POINTER type PCD value.\r
80408db0 1636\r
2ab6330e 1637 @return size of POINTER type PCD value.\r
80408db0 1638\r
2ab6330e 1639**/\r
80408db0 1640UINTN\r
1641GetPtrTypeSize (\r
1642 IN UINTN LocalTokenNumberTableIdx,\r
1643 OUT UINTN *MaxSize\r
1644 )\r
1645{\r
1646 INTN SizeTableIdx;\r
1647 UINTN LocalTokenNumber;\r
1648 SKU_ID *SkuIdTable;\r
1649 SIZE_INFO *SizeTable;\r
2ab6330e 1650 UINTN Index;\r
80408db0 1651 BOOLEAN IsPeiDb;\r
1652 UINT32 *LocalTokenNumberTable;\r
1653\r
1654 // EBC compiler is very choosy. It may report warning about comparison\r
1655 // between UINTN and 0 . So we add 1 in each size of the \r
1656 // comparison.\r
419db80b 1657 IsPeiDb = (BOOLEAN) (LocalTokenNumberTableIdx + 1 < mPeiLocalTokenCount + 1);\r
80408db0 1658\r
1659\r
1660 if (IsPeiDb) {\r
419db80b
BF
1661 LocalTokenNumberTable = (UINT32 *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->LocalTokenNumberTableOffset);\r
1662 SizeTable = (SIZE_INFO *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->SizeTableOffset);\r
80408db0 1663 } else {\r
419db80b
BF
1664 LocalTokenNumberTableIdx -= mPeiLocalTokenCount;\r
1665 LocalTokenNumberTable = (UINT32 *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->LocalTokenNumberTableOffset);\r
1666 SizeTable = (SIZE_INFO *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->SizeTableOffset);\r
80408db0 1667 }\r
1668\r
1669 LocalTokenNumber = LocalTokenNumberTable[LocalTokenNumberTableIdx];\r
1670\r
1671 ASSERT ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER);\r
1672 \r
1673 SizeTableIdx = GetSizeTableIndex (LocalTokenNumberTableIdx, IsPeiDb);\r
1674\r
1675 *MaxSize = SizeTable[SizeTableIdx];\r
1676 //\r
1677 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type \r
1678 // PCD entry.\r
1679 //\r
2ab6330e 1680 if ((LocalTokenNumber & PCD_TYPE_VPD) != 0) {\r
80408db0 1681 //\r
419db80b 1682 // We have only two entry for VPD enabled PCD entry:\r
80408db0 1683 // 1) MAX Size.\r
419db80b 1684 // 2) Current Size\r
80408db0 1685 // We consider current size is equal to MAX size.\r
1686 //\r
1687 return *MaxSize;\r
1688 } else {\r
1689 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0) {\r
1690 //\r
1691 // We have only two entry for Non-Sku enabled PCD entry:\r
1692 // 1) MAX SIZE\r
1693 // 2) Current Size\r
1694 //\r
1695 return SizeTable[SizeTableIdx + 1];\r
1696 } else {\r
1697 //\r
1698 // We have these entry for SKU enabled PCD entry\r
1699 // 1) MAX SIZE\r
1700 // 2) Current Size for each SKU_ID (It is equal to MaxSku).\r
1701 //\r
1702 SkuIdTable = GetSkuIdArray (LocalTokenNumberTableIdx, IsPeiDb);\r
2ab6330e 1703 for (Index = 0; Index < SkuIdTable[0]; Index++) {\r
419db80b 1704 if (SkuIdTable[1 + Index] == mPcdDatabase.PeiDb->SystemSkuId) {\r
2ab6330e 1705 return SizeTable[SizeTableIdx + 1 + Index];\r
80408db0 1706 }\r
1707 }\r
1708 return SizeTable[SizeTableIdx + 1];\r
1709 }\r
1710 }\r
1711}\r
1712\r
2ab6330e 1713/**\r
3fd8027e 1714 Set size of POINTER type PCD value. The size should not exceed the maximum size\r
2ab6330e 1715 of this PCD value.\r
80408db0 1716\r
2ab6330e 1717 @param LocalTokenNumberTableIdx Index of local token number in local token number table.\r
1718 @param CurrentSize Size of POINTER type PCD value.\r
80408db0 1719\r
2ab6330e 1720 @retval TRUE Success to set size of PCD value.\r
1721 @retval FALSE Fail to set size of PCD value.\r
1722**/\r
80408db0 1723BOOLEAN\r
1724SetPtrTypeSize (\r
1725 IN UINTN LocalTokenNumberTableIdx,\r
1726 IN OUT UINTN *CurrentSize\r
1727 )\r
1728{\r
1729 INTN SizeTableIdx;\r
1730 UINTN LocalTokenNumber;\r
1731 SKU_ID *SkuIdTable;\r
1732 SIZE_INFO *SizeTable;\r
2ab6330e 1733 UINTN Index;\r
80408db0 1734 UINTN MaxSize;\r
1735 BOOLEAN IsPeiDb;\r
1736 UINT32 *LocalTokenNumberTable;\r
1737\r
2ab6330e 1738 //\r
80408db0 1739 // EBC compiler is very choosy. It may report warning about comparison\r
1740 // between UINTN and 0 . So we add 1 in each size of the \r
1741 // comparison.\r
2ab6330e 1742 //\r
419db80b 1743 IsPeiDb = (BOOLEAN) (LocalTokenNumberTableIdx + 1 < mPeiLocalTokenCount + 1);\r
80408db0 1744\r
1745 if (IsPeiDb) {\r
419db80b
BF
1746 LocalTokenNumberTable = (UINT32 *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->LocalTokenNumberTableOffset);\r
1747 SizeTable = (SIZE_INFO *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->SizeTableOffset);\r
80408db0 1748 } else {\r
419db80b
BF
1749 LocalTokenNumberTableIdx -= mPeiLocalTokenCount;\r
1750 LocalTokenNumberTable = (UINT32 *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->LocalTokenNumberTableOffset);\r
1751 SizeTable = (SIZE_INFO *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->SizeTableOffset);\r
80408db0 1752 }\r
1753\r
1754 LocalTokenNumber = LocalTokenNumberTable[LocalTokenNumberTableIdx];\r
1755\r
1756 ASSERT ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER);\r
1757 \r
1758 SizeTableIdx = GetSizeTableIndex (LocalTokenNumberTableIdx, IsPeiDb);\r
1759\r
1760 MaxSize = SizeTable[SizeTableIdx];\r
1761 //\r
1762 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type \r
1763 // PCD entry.\r
1764 //\r
2ab6330e 1765 if ((LocalTokenNumber & PCD_TYPE_VPD) != 0) {\r
80408db0 1766 //\r
1767 // We shouldn't come here as we don't support SET for VPD\r
1768 //\r
1769 ASSERT (FALSE);\r
1770 return FALSE;\r
1771 } else {\r
1772 if ((*CurrentSize > MaxSize) ||\r
1773 (*CurrentSize == MAX_ADDRESS)) {\r
1774 *CurrentSize = MaxSize;\r
1775 return FALSE;\r
1776 } \r
1777 \r
1778 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0) {\r
1779 //\r
1780 // We have only two entry for Non-Sku enabled PCD entry:\r
1781 // 1) MAX SIZE\r
1782 // 2) Current Size\r
1783 //\r
1784 SizeTable[SizeTableIdx + 1] = (SIZE_INFO) *CurrentSize;\r
1785 return TRUE;\r
1786 } else {\r
1787 //\r
1788 // We have these entry for SKU enabled PCD entry\r
1789 // 1) MAX SIZE\r
1790 // 2) Current Size for each SKU_ID (It is equal to MaxSku).\r
1791 //\r
1792 SkuIdTable = GetSkuIdArray (LocalTokenNumberTableIdx, IsPeiDb);\r
2ab6330e 1793 for (Index = 0; Index < SkuIdTable[0]; Index++) {\r
419db80b 1794 if (SkuIdTable[1 + Index] == mPcdDatabase.PeiDb->SystemSkuId) {\r
2ab6330e 1795 SizeTable[SizeTableIdx + 1 + Index] = (SIZE_INFO) *CurrentSize;\r
80408db0 1796 return TRUE;\r
1797 }\r
1798 }\r
1799 SizeTable[SizeTableIdx + 1] = (SIZE_INFO) *CurrentSize;\r
1800 return TRUE;\r
1801 }\r
1802 }\r
1803}\r