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