]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/PCD/Dxe/Service.c
Sync the branch changes to trunk.
[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
23f3e119 1115 UINT32 Attributes;\r
80408db0 1116 VOID *InternalData;\r
1117 VARIABLE_HEAD *VariableHead;\r
1118 UINTN Offset;\r
1119 UINT8 *PcdDb;\r
1120 EFI_STATUS Status;\r
1121 UINTN MaxSize;\r
1122 UINTN TmpTokenNumber;\r
1123\r
80408db0 1124 //\r
1125 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.\r
1126 // We have to decrement TokenNumber by 1 to make it usable\r
1127 // as the array index.\r
1128 //\r
1129 TokenNumber--;\r
1130\r
1131 TmpTokenNumber = TokenNumber;\r
1132 \r
2ab6330e 1133 //\r
80408db0 1134 // EBC compiler is very choosy. It may report warning about comparison\r
1135 // between UINTN and 0 . So we add 1 in each size of the \r
1136 // comparison.\r
2ab6330e 1137 //\r
419db80b 1138 ASSERT (TokenNumber + 1 < mPcdTotalTokenCount + 1);\r
80408db0 1139\r
8ec8bed4 1140 if (PtrType) {\r
64894410
LG
1141 //\r
1142 // Get MaxSize first, then check new size with max buffer size.\r
1143 //\r
1144 GetPtrTypeSize (TokenNumber, &MaxSize);\r
1145 if (*Size > MaxSize) {\r
cb40609c 1146 *Size = MaxSize;\r
8ec8bed4 1147 return EFI_INVALID_PARAMETER;\r
1148 }\r
1149 } else {\r
1150 if (*Size != DxePcdGetSize (TokenNumber + 1)) {\r
1151 return EFI_INVALID_PARAMETER;\r
1152 }\r
80408db0 1153 }\r
b07a5b68 1154\r
2ab6330e 1155 //\r
80408db0 1156 // EBC compiler is very choosy. It may report warning about comparison\r
1157 // between UINTN and 0 . So we add 1 in each size of the \r
1158 // comparison.\r
2ab6330e 1159 //\r
419db80b
BF
1160 if ((TokenNumber + 1 < mPeiNexTokenCount + 1) ||\r
1161 (TokenNumber + 1 >= mPeiLocalTokenCount + 1 && TokenNumber + 1 < (mPeiLocalTokenCount + mDxeNexTokenCount + 1))) {\r
b07a5b68 1162 InvokeCallbackOnSet (0, NULL, TokenNumber + 1, Data, *Size);\r
1163 }\r
80408db0 1164\r
b07a5b68 1165 //\r
1166 // Aquire lock to prevent reentrance from TPL_CALLBACK level\r
1167 //\r
1168 EfiAcquireLock (&mPcdDatabaseLock);\r
80408db0 1169\r
2ab6330e 1170 //\r
80408db0 1171 // EBC compiler is very choosy. It may report warning about comparison\r
1172 // between UINTN and 0 . So we add 1 in each size of the \r
1173 // comparison.\r
2ab6330e 1174 //\r
419db80b 1175 IsPeiDb = (BOOLEAN) ((TokenNumber + 1 < mPeiLocalTokenCount + 1) ? TRUE : FALSE);\r
b07a5b68 1176\r
96d6d004 1177 LocalTokenNumber = GetLocalTokenNumber (IsPeiDb, TokenNumber + 1);\r
80408db0 1178\r
1179 Offset = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK;\r
1180\r
419db80b 1181 PcdDb = IsPeiDb ? ((UINT8 *) mPcdDatabase.PeiDb) : ((UINT8 *) mPcdDatabase.DxeDb);\r
80408db0 1182\r
309e3122 1183 if (IsPeiDb) {\r
419db80b 1184 StringTable = (UINT8 *) ((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->StringTableOffset);\r
309e3122 1185 } else {\r
419db80b 1186 StringTable = (UINT8 *) ((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->StringTableOffset);\r
309e3122 1187 }\r
1188\r
80408db0 1189 \r
1190 InternalData = PcdDb + Offset;\r
1191\r
1192 switch (LocalTokenNumber & PCD_TYPE_ALL_SET) {\r
1193 case PCD_TYPE_VPD:\r
1194 ASSERT (FALSE);\r
1195 Status = EFI_INVALID_PARAMETER;\r
1196 break;\r
1197 \r
1198 case PCD_TYPE_STRING:\r
1199 if (SetPtrTypeSize (TmpTokenNumber, Size)) {\r
6cfc7292 1200 CopyMem (StringTable + *((STRING_HEAD *)InternalData), Data, *Size);\r
80408db0 1201 Status = EFI_SUCCESS;\r
1202 } else {\r
1203 Status = EFI_INVALID_PARAMETER;\r
1204 }\r
1205 break;\r
1206\r
6ac15f7c 1207 case PCD_TYPE_HII|PCD_TYPE_STRING:\r
80408db0 1208 case PCD_TYPE_HII:\r
1209 if (PtrType) {\r
1210 if (!SetPtrTypeSize (TmpTokenNumber, Size)) {\r
1211 Status = EFI_INVALID_PARAMETER;\r
1212 break;\r
1213 }\r
1214 }\r
419db80b 1215\r
309e3122 1216 if (IsPeiDb) {\r
419db80b 1217 GuidTable = (EFI_GUID *) ((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->GuidTableOffset);\r
309e3122 1218 } else {\r
419db80b 1219 GuidTable = (EFI_GUID *) ((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->GuidTableOffset);\r
309e3122 1220 }\r
419db80b 1221\r
80408db0 1222 VariableHead = (VARIABLE_HEAD *) (PcdDb + Offset);\r
419db80b 1223\r
1fef733c 1224 Guid = GuidTable + VariableHead->GuidTableIndex;\r
d0965169 1225 Name = (UINT16*) (StringTable + VariableHead->StringIndex);\r
80408db0 1226 VariableOffset = VariableHead->Offset;\r
23f3e119
SZ
1227 Attributes = VariableHead->Attributes;\r
1228 Status = SetHiiVariable (Guid, Name, Attributes, Data, *Size, VariableOffset);\r
80408db0 1229 break;\r
1230 \r
1231 case PCD_TYPE_DATA:\r
1232 if (PtrType) {\r
1233 if (SetPtrTypeSize (TmpTokenNumber, Size)) {\r
1234 CopyMem (InternalData, Data, *Size);\r
1235 Status = EFI_SUCCESS;\r
1236 } else {\r
1237 Status = EFI_INVALID_PARAMETER;\r
1238 }\r
1239 break;\r
1240 }\r
1241\r
1242 Status = EFI_SUCCESS;\r
1243 switch (*Size) {\r
1244 case sizeof(UINT8):\r
1245 *((UINT8 *) InternalData) = *((UINT8 *) Data);\r
1246 break;\r
1247\r
1248 case sizeof(UINT16):\r
1249 *((UINT16 *) InternalData) = *((UINT16 *) Data);\r
1250 break;\r
1251\r
1252 case sizeof(UINT32):\r
1253 *((UINT32 *) InternalData) = *((UINT32 *) Data);\r
1254 break;\r
1255\r
1256 case sizeof(UINT64):\r
1257 *((UINT64 *) InternalData) = *((UINT64 *) Data);\r
1258 break;\r
1259\r
1260 default:\r
1261 ASSERT (FALSE);\r
1262 Status = EFI_NOT_FOUND;\r
1263 break;\r
1264 }\r
1265 break;\r
1266\r
1267 default:\r
1268 ASSERT (FALSE);\r
1269 Status = EFI_NOT_FOUND;\r
1270 break;\r
1271 }\r
1272\r
1273 EfiReleaseLock (&mPcdDatabaseLock);\r
1274 \r
1275 return Status;\r
1276}\r
1277\r
2ab6330e 1278/**\r
1279 Wrapper function for get PCD value for dynamic-ex PCD.\r
80408db0 1280\r
2ab6330e 1281 @param Guid Token space guid for dynamic-ex PCD.\r
3fd8027e 1282 @param ExTokenNumber Token number for dynamic-ex PCD.\r
2ab6330e 1283 @param GetSize The size of dynamic-ex PCD value.\r
80408db0 1284\r
2ab6330e 1285 @return PCD entry in PCD database.\r
80408db0 1286\r
2ab6330e 1287**/\r
80408db0 1288VOID *\r
1289ExGetWorker (\r
1290 IN CONST EFI_GUID *Guid,\r
1291 IN UINTN ExTokenNumber,\r
1292 IN UINTN GetSize\r
1293 ) \r
1294{\r
1295 return GetWorker(GetExPcdTokenNumber (Guid, (UINT32) ExTokenNumber), GetSize);\r
1296}\r
1297\r
2ab6330e 1298/**\r
1299 Wrapper function for set PCD value for non-Pointer type dynamic-ex PCD.\r
80408db0 1300\r
2ab6330e 1301 @param ExTokenNumber Token number for dynamic-ex PCD.\r
1302 @param Guid Token space guid for dynamic-ex PCD.\r
1303 @param Data Value want to be set.\r
1304 @param SetSize The size of value.\r
80408db0 1305\r
2ab6330e 1306 @return status of ExSetWorker().\r
80408db0 1307\r
2ab6330e 1308**/\r
80408db0 1309EFI_STATUS\r
1310ExSetValueWorker (\r
1311 IN UINTN ExTokenNumber,\r
1312 IN CONST EFI_GUID *Guid,\r
1313 IN VOID *Data,\r
1314 IN UINTN SetSize\r
1315 )\r
1316{\r
1317 return ExSetWorker (ExTokenNumber, Guid, Data, &SetSize, FALSE);\r
1318}\r
1319\r
2ab6330e 1320/**\r
419db80b 1321 Set value for a dynamic-ex PCD entry.\r
2ab6330e 1322 \r
1323 This routine find the local token number according to dynamic-ex PCD's token \r
1324 space guid and token number firstly, and invoke callback function if this PCD\r
1325 entry registered callback function. Finally, invoken general SetWorker to set\r
1326 PCD value.\r
1327 \r
1328 @param ExTokenNumber Dynamic-ex PCD token number.\r
1329 @param Guid Token space guid for dynamic-ex PCD.\r
1330 @param Data PCD value want to be set\r
1331 @param SetSize Size of value.\r
1332 @param PtrType If TRUE, this PCD entry is pointer type.\r
1333 If FALSE, this PCD entry is not pointer type.\r
1334\r
1335 @return status of SetWorker().\r
80408db0 1336\r
2ab6330e 1337**/\r
80408db0 1338EFI_STATUS\r
1339ExSetWorker (\r
1340 IN UINTN ExTokenNumber,\r
1341 IN CONST EFI_GUID *Guid,\r
1342 IN VOID *Data,\r
1343 IN OUT UINTN *SetSize,\r
1344 IN BOOLEAN PtrType\r
1345 )\r
1346{\r
1347 UINTN TokenNumber;\r
1348 \r
1349 TokenNumber = GetExPcdTokenNumber (Guid, (UINT32) ExTokenNumber);\r
1350\r
1351 InvokeCallbackOnSet ((UINT32) ExTokenNumber, Guid, TokenNumber, Data, *SetSize);\r
1352\r
1353 return SetWorker (TokenNumber, Data, SetSize, PtrType);\r
1354\r
1355}\r
1356\r
2ab6330e 1357/**\r
1358 Set value for HII-type PCD.\r
80408db0 1359\r
2ab6330e 1360 A HII-type PCD's value is stored in a variable. Setting/Getting the value of \r
1361 HII-type PCD is to visit this variable.\r
1362 \r
1363 @param VariableGuid Guid of variable which stored value of a HII-type PCD.\r
1364 @param VariableName Unicode name of variable which stored value of a HII-type PCD.\r
23f3e119 1365 @param SetAttributes Attributes bitmask to set for the variable.\r
2ab6330e 1366 @param Data Value want to be set.\r
1367 @param DataSize Size of value\r
1368 @param Offset Value offset of HII-type PCD in variable.\r
80408db0 1369\r
2ab6330e 1370 @return status of GetVariable()/SetVariable().\r
80408db0 1371\r
2ab6330e 1372**/\r
80408db0 1373EFI_STATUS\r
1374SetHiiVariable (\r
1375 IN EFI_GUID *VariableGuid,\r
1376 IN UINT16 *VariableName,\r
23f3e119 1377 IN UINT32 SetAttributes,\r
80408db0 1378 IN CONST VOID *Data,\r
1379 IN UINTN DataSize,\r
1380 IN UINTN Offset\r
1381 )\r
1382{\r
1383 UINTN Size;\r
1384 VOID *Buffer;\r
1385 EFI_STATUS Status;\r
1386 UINT32 Attribute;\r
b13151ff 1387 UINTN SetSize;\r
80408db0 1388\r
1389 Size = 0;\r
b13151ff 1390 SetSize = 0;\r
80408db0 1391\r
746be876 1392 //\r
1393 // Try to get original variable size information.\r
1394 //\r
80408db0 1395 Status = gRT->GetVariable (\r
1396 (UINT16 *)VariableName,\r
1397 VariableGuid,\r
1398 NULL,\r
1399 &Size,\r
1400 NULL\r
1401 );\r
b13151ff 1402 \r
80408db0 1403 if (Status == EFI_BUFFER_TOO_SMALL) {\r
746be876 1404 //\r
1405 // Patch new PCD's value to offset in given HII variable.\r
1406 //\r
23f3e119 1407 if (Size >= (DataSize + Offset)) {\r
b13151ff
LG
1408 SetSize = Size;\r
1409 } else {\r
1410 SetSize = DataSize + Offset;\r
1411 }\r
1412 Buffer = AllocatePool (SetSize);\r
80408db0 1413 ASSERT (Buffer != NULL);\r
1414\r
1415 Status = gRT->GetVariable (\r
1416 VariableName,\r
1417 VariableGuid,\r
1418 &Attribute,\r
1419 &Size,\r
1420 Buffer\r
1421 );\r
1422 \r
1423 ASSERT_EFI_ERROR (Status);\r
1424\r
1425 CopyMem ((UINT8 *)Buffer + Offset, Data, DataSize);\r
1426\r
23f3e119
SZ
1427 if (SetAttributes == 0) {\r
1428 SetAttributes = Attribute;\r
1429 }\r
1430\r
80408db0 1431 Status = gRT->SetVariable (\r
1432 VariableName,\r
1433 VariableGuid,\r
23f3e119 1434 SetAttributes,\r
b13151ff 1435 SetSize,\r
80408db0 1436 Buffer\r
1437 );\r
1438\r
1439 FreePool (Buffer);\r
1440 return Status;\r
746be876 1441 } else if (Status == EFI_NOT_FOUND) {\r
1442 //\r
1443 // If variable does not exist, a new variable need to be created.\r
1444 //\r
1445 \r
1446 Size = Offset + DataSize;\r
1447 \r
1448 Buffer = AllocateZeroPool (Size);\r
1449 ASSERT (Buffer != NULL);\r
1450 \r
1451 CopyMem ((UINT8 *)Buffer + Offset, Data, DataSize);\r
23f3e119
SZ
1452\r
1453 if (SetAttributes == 0) {\r
1454 SetAttributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE;\r
1455 }\r
1456\r
746be876 1457 Status = gRT->SetVariable (\r
1458 VariableName,\r
1459 VariableGuid,\r
23f3e119 1460 SetAttributes,\r
746be876 1461 Size,\r
1462 Buffer\r
1463 );\r
1464\r
1465 FreePool (Buffer);\r
1466 return Status; \r
1467 }\r
80408db0 1468 \r
1469 //\r
23f3e119 1470 // If we drop to here, the value is failed to be written in to variable area.\r
80408db0 1471 //\r
1472 return Status;\r
1473}\r
1474\r
2ab6330e 1475/**\r
419db80b 1476 Get Token Number according to dynamic-ex PCD's {token space guid:token number}\r
80408db0 1477\r
2ab6330e 1478 A dynamic-ex type PCD, developer must provide pair of token space guid: token number\r
1479 in DEC file. PCD database maintain a mapping table that translate pair of {token\r
419db80b 1480 space guid: token number} to Token Number.\r
2ab6330e 1481 \r
1482 @param Guid Token space guid for dynamic-ex PCD entry.\r
b9982883 1483 @param ExTokenNumber Dynamic-ex PCD token number.\r
80408db0 1484\r
419db80b 1485 @return Token Number for dynamic-ex PCD.\r
80408db0 1486\r
2ab6330e 1487**/\r
80408db0 1488UINTN \r
1489GetExPcdTokenNumber (\r
1490 IN CONST EFI_GUID *Guid,\r
1491 IN UINT32 ExTokenNumber\r
1492 )\r
1493{\r
2ab6330e 1494 UINT32 Index;\r
80408db0 1495 DYNAMICEX_MAPPING *ExMap;\r
1496 EFI_GUID *GuidTable;\r
1497 EFI_GUID *MatchGuid;\r
1498 UINTN MatchGuidIdx;\r
1499\r
419db80b
BF
1500 if (!mPeiDatabaseEmpty) {\r
1501 ExMap = (DYNAMICEX_MAPPING *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->ExMapTableOffset);\r
1502 GuidTable = (EFI_GUID *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->GuidTableOffset);\r
1503\r
1504 MatchGuid = ScanGuid (GuidTable, mPeiGuidTableSize, Guid);\r
1505\r
80408db0 1506 if (MatchGuid != NULL) {\r
1507\r
1508 MatchGuidIdx = MatchGuid - GuidTable;\r
419db80b 1509\r
8cc87d32 1510 for (Index = 0; Index < mPcdDatabase.PeiDb->ExTokenCount; Index++) {\r
2ab6330e 1511 if ((ExTokenNumber == ExMap[Index].ExTokenNumber) &&\r
1512 (MatchGuidIdx == ExMap[Index].ExGuidIndex)) {\r
419db80b 1513 return ExMap[Index].TokenNumber;\r
80408db0 1514 }\r
1515 }\r
1516 }\r
1517 }\r
80408db0 1518\r
419db80b
BF
1519 ExMap = (DYNAMICEX_MAPPING *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->ExMapTableOffset);\r
1520 GuidTable = (EFI_GUID *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->GuidTableOffset);\r
1521\r
1522 MatchGuid = ScanGuid (GuidTable, mDxeGuidTableSize, Guid);\r
80408db0 1523 //\r
1524 // We need to ASSERT here. If GUID can't be found in GuidTable, this is a\r
1525 // error in the BUILD system.\r
1526 //\r
1527 ASSERT (MatchGuid != NULL);\r
1528\r
1529 MatchGuidIdx = MatchGuid - GuidTable;\r
419db80b 1530\r
8cc87d32 1531 for (Index = 0; Index < mPcdDatabase.DxeDb->ExTokenCount; Index++) {\r
2ab6330e 1532 if ((ExTokenNumber == ExMap[Index].ExTokenNumber) &&\r
1533 (MatchGuidIdx == ExMap[Index].ExGuidIndex)) {\r
419db80b 1534 return ExMap[Index].TokenNumber;\r
80408db0 1535 }\r
1536 }\r
1537\r
1538 ASSERT (FALSE);\r
1539\r
1540 return 0;\r
1541}\r
1542\r
2ab6330e 1543/**\r
3fd8027e 1544 Get SKU ID table from PCD database.\r
2ab6330e 1545\r
1546 @param LocalTokenNumberTableIdx Index of local token number in token number table.\r
419db80b
BF
1547 @param IsPeiDb If TRUE, the pcd entry is initialized in PEI phase,\r
1548 If FALSE, the pcd entry is initialized in DXE phase.\r
2ab6330e 1549 @return Pointer to SKU ID array table\r
1550\r
1551**/\r
80408db0 1552SKU_ID *\r
1553GetSkuIdArray (\r
1554 IN UINTN LocalTokenNumberTableIdx,\r
419db80b 1555 IN BOOLEAN IsPeiDb\r
80408db0 1556 )\r
1557{\r
1558 SKU_HEAD *SkuHead;\r
1559 UINTN LocalTokenNumber;\r
1560 UINT8 *Database;\r
1561\r
419db80b
BF
1562 if (IsPeiDb) {\r
1563 LocalTokenNumber = *((UINT32 *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->LocalTokenNumberTableOffset) + LocalTokenNumberTableIdx);\r
1564 Database = (UINT8 *) mPcdDatabase.PeiDb;\r
80408db0 1565 } else {\r
419db80b
BF
1566 LocalTokenNumber = *((UINT32 *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->LocalTokenNumberTableOffset) + LocalTokenNumberTableIdx);\r
1567 Database = (UINT8 *) mPcdDatabase.DxeDb;\r
80408db0 1568 }\r
1569\r
1570 ASSERT ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) != 0);\r
1571\r
1572 SkuHead = (SKU_HEAD *) ((UINT8 *)Database + (LocalTokenNumber & PCD_DATABASE_OFFSET_MASK));\r
1573\r
1574 return (SKU_ID *) (Database + SkuHead->SkuIdTableOffset);\r
1575 \r
1576}\r
1577\r
2ab6330e 1578/**\r
3d53ba8b 1579 Wrapper function of getting index of PCD entry in size table.\r
1580 \r
2ab6330e 1581 @param LocalTokenNumberTableIdx Index of this PCD in local token number table.\r
2ab6330e 1582 @param IsPeiDb If TRUE, the pcd entry is initialized in PEI phase,\r
1583 If FALSE, the pcd entry is initialized in DXE phase.\r
1584\r
1585 @return index of PCD entry in size table.\r
2ab6330e 1586**/\r
80408db0 1587UINTN\r
3d53ba8b 1588GetSizeTableIndex (\r
1589 IN UINTN LocalTokenNumberTableIdx,\r
1590 IN BOOLEAN IsPeiDb\r
80408db0 1591 )\r
1592{\r
3d53ba8b 1593 UINT32 *LocalTokenNumberTable;\r
1594 UINTN LocalTokenNumber;\r
1595 UINTN Index;\r
1596 UINTN SizeTableIdx;\r
1597 SKU_ID *SkuIdTable;\r
80408db0 1598 \r
3d53ba8b 1599 if (IsPeiDb) {\r
419db80b 1600 LocalTokenNumberTable = (UINT32 *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->LocalTokenNumberTableOffset);\r
3d53ba8b 1601 } else {\r
419db80b 1602 LocalTokenNumberTable = (UINT32 *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->LocalTokenNumberTableOffset);\r
3d53ba8b 1603 }\r
1604\r
80408db0 1605 SizeTableIdx = 0;\r
1606\r
3d53ba8b 1607 for (Index = 0; Index < LocalTokenNumberTableIdx; Index ++) {\r
2ab6330e 1608 LocalTokenNumber = LocalTokenNumberTable[Index];\r
80408db0 1609\r
1610 if ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER) {\r
1611 //\r
1612 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type \r
1613 // PCD entry.\r
1614 //\r
2ab6330e 1615 if ((LocalTokenNumber & PCD_TYPE_VPD) != 0) {\r
80408db0 1616 //\r
419db80b 1617 // We have only two entry for VPD enabled PCD entry:\r
80408db0 1618 // 1) MAX Size.\r
419db80b
BF
1619 // 2) Current Size\r
1620 // Current size is equal to MAX size.\r
80408db0 1621 //\r
419db80b 1622 SizeTableIdx += 2;\r
80408db0 1623 } else {\r
1624 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0) {\r
1625 //\r
1626 // We have only two entry for Non-Sku enabled PCD entry:\r
1627 // 1) MAX SIZE\r
1628 // 2) Current Size\r
1629 //\r
1630 SizeTableIdx += 2;\r
1631 } else {\r
1632 //\r
1633 // We have these entry for SKU enabled PCD entry\r
1634 // 1) MAX SIZE\r
1635 // 2) Current Size for each SKU_ID (It is equal to MaxSku).\r
1636 //\r
2ab6330e 1637 SkuIdTable = GetSkuIdArray (Index, IsPeiDb);\r
80408db0 1638 SizeTableIdx += (UINTN)*SkuIdTable + 1;\r
1639 }\r
1640 }\r
1641 }\r
1642\r
1643 }\r
1644\r
3d53ba8b 1645 return SizeTableIdx; \r
80408db0 1646}\r
1647\r
2ab6330e 1648/**\r
1649 Get size of POINTER type PCD value.\r
1650\r
1651 @param LocalTokenNumberTableIdx Index of local token number in local token number table.\r
1652 @param MaxSize Maxmium size of POINTER type PCD value.\r
80408db0 1653\r
2ab6330e 1654 @return size of POINTER type PCD value.\r
80408db0 1655\r
2ab6330e 1656**/\r
80408db0 1657UINTN\r
1658GetPtrTypeSize (\r
1659 IN UINTN LocalTokenNumberTableIdx,\r
1660 OUT UINTN *MaxSize\r
1661 )\r
1662{\r
1663 INTN SizeTableIdx;\r
1664 UINTN LocalTokenNumber;\r
1665 SKU_ID *SkuIdTable;\r
1666 SIZE_INFO *SizeTable;\r
2ab6330e 1667 UINTN Index;\r
80408db0 1668 BOOLEAN IsPeiDb;\r
1669 UINT32 *LocalTokenNumberTable;\r
1670\r
1671 // EBC compiler is very choosy. It may report warning about comparison\r
1672 // between UINTN and 0 . So we add 1 in each size of the \r
1673 // comparison.\r
419db80b 1674 IsPeiDb = (BOOLEAN) (LocalTokenNumberTableIdx + 1 < mPeiLocalTokenCount + 1);\r
80408db0 1675\r
1676\r
1677 if (IsPeiDb) {\r
419db80b
BF
1678 LocalTokenNumberTable = (UINT32 *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->LocalTokenNumberTableOffset);\r
1679 SizeTable = (SIZE_INFO *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->SizeTableOffset);\r
80408db0 1680 } else {\r
419db80b
BF
1681 LocalTokenNumberTableIdx -= mPeiLocalTokenCount;\r
1682 LocalTokenNumberTable = (UINT32 *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->LocalTokenNumberTableOffset);\r
1683 SizeTable = (SIZE_INFO *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->SizeTableOffset);\r
80408db0 1684 }\r
1685\r
1686 LocalTokenNumber = LocalTokenNumberTable[LocalTokenNumberTableIdx];\r
1687\r
1688 ASSERT ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER);\r
1689 \r
1690 SizeTableIdx = GetSizeTableIndex (LocalTokenNumberTableIdx, IsPeiDb);\r
1691\r
1692 *MaxSize = SizeTable[SizeTableIdx];\r
1693 //\r
1694 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type \r
1695 // PCD entry.\r
1696 //\r
2ab6330e 1697 if ((LocalTokenNumber & PCD_TYPE_VPD) != 0) {\r
80408db0 1698 //\r
419db80b 1699 // We have only two entry for VPD enabled PCD entry:\r
80408db0 1700 // 1) MAX Size.\r
419db80b 1701 // 2) Current Size\r
80408db0 1702 // We consider current size is equal to MAX size.\r
1703 //\r
1704 return *MaxSize;\r
1705 } else {\r
1706 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0) {\r
1707 //\r
1708 // We have only two entry for Non-Sku enabled PCD entry:\r
1709 // 1) MAX SIZE\r
1710 // 2) Current Size\r
1711 //\r
1712 return SizeTable[SizeTableIdx + 1];\r
1713 } else {\r
1714 //\r
1715 // We have these entry for SKU enabled PCD entry\r
1716 // 1) MAX SIZE\r
1717 // 2) Current Size for each SKU_ID (It is equal to MaxSku).\r
1718 //\r
1719 SkuIdTable = GetSkuIdArray (LocalTokenNumberTableIdx, IsPeiDb);\r
2ab6330e 1720 for (Index = 0; Index < SkuIdTable[0]; Index++) {\r
efd6b412 1721 if (SkuIdTable[1 + Index] == mPcdDatabase.DxeDb->SystemSkuId) {\r
2ab6330e 1722 return SizeTable[SizeTableIdx + 1 + Index];\r
80408db0 1723 }\r
1724 }\r
1725 return SizeTable[SizeTableIdx + 1];\r
1726 }\r
1727 }\r
1728}\r
1729\r
2ab6330e 1730/**\r
3fd8027e 1731 Set size of POINTER type PCD value. The size should not exceed the maximum size\r
2ab6330e 1732 of this PCD value.\r
80408db0 1733\r
2ab6330e 1734 @param LocalTokenNumberTableIdx Index of local token number in local token number table.\r
1735 @param CurrentSize Size of POINTER type PCD value.\r
80408db0 1736\r
2ab6330e 1737 @retval TRUE Success to set size of PCD value.\r
1738 @retval FALSE Fail to set size of PCD value.\r
1739**/\r
80408db0 1740BOOLEAN\r
1741SetPtrTypeSize (\r
1742 IN UINTN LocalTokenNumberTableIdx,\r
1743 IN OUT UINTN *CurrentSize\r
1744 )\r
1745{\r
1746 INTN SizeTableIdx;\r
1747 UINTN LocalTokenNumber;\r
1748 SKU_ID *SkuIdTable;\r
1749 SIZE_INFO *SizeTable;\r
2ab6330e 1750 UINTN Index;\r
80408db0 1751 UINTN MaxSize;\r
1752 BOOLEAN IsPeiDb;\r
1753 UINT32 *LocalTokenNumberTable;\r
1754\r
2ab6330e 1755 //\r
80408db0 1756 // EBC compiler is very choosy. It may report warning about comparison\r
1757 // between UINTN and 0 . So we add 1 in each size of the \r
1758 // comparison.\r
2ab6330e 1759 //\r
419db80b 1760 IsPeiDb = (BOOLEAN) (LocalTokenNumberTableIdx + 1 < mPeiLocalTokenCount + 1);\r
80408db0 1761\r
1762 if (IsPeiDb) {\r
419db80b
BF
1763 LocalTokenNumberTable = (UINT32 *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->LocalTokenNumberTableOffset);\r
1764 SizeTable = (SIZE_INFO *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->SizeTableOffset);\r
80408db0 1765 } else {\r
419db80b
BF
1766 LocalTokenNumberTableIdx -= mPeiLocalTokenCount;\r
1767 LocalTokenNumberTable = (UINT32 *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->LocalTokenNumberTableOffset);\r
1768 SizeTable = (SIZE_INFO *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->SizeTableOffset);\r
80408db0 1769 }\r
1770\r
1771 LocalTokenNumber = LocalTokenNumberTable[LocalTokenNumberTableIdx];\r
1772\r
1773 ASSERT ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER);\r
1774 \r
1775 SizeTableIdx = GetSizeTableIndex (LocalTokenNumberTableIdx, IsPeiDb);\r
1776\r
1777 MaxSize = SizeTable[SizeTableIdx];\r
1778 //\r
1779 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type \r
1780 // PCD entry.\r
1781 //\r
2ab6330e 1782 if ((LocalTokenNumber & PCD_TYPE_VPD) != 0) {\r
80408db0 1783 //\r
1784 // We shouldn't come here as we don't support SET for VPD\r
1785 //\r
1786 ASSERT (FALSE);\r
1787 return FALSE;\r
1788 } else {\r
1789 if ((*CurrentSize > MaxSize) ||\r
1790 (*CurrentSize == MAX_ADDRESS)) {\r
1791 *CurrentSize = MaxSize;\r
1792 return FALSE;\r
1793 } \r
1794 \r
1795 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0) {\r
1796 //\r
1797 // We have only two entry for Non-Sku enabled PCD entry:\r
1798 // 1) MAX SIZE\r
1799 // 2) Current Size\r
1800 //\r
1801 SizeTable[SizeTableIdx + 1] = (SIZE_INFO) *CurrentSize;\r
1802 return TRUE;\r
1803 } else {\r
1804 //\r
1805 // We have these entry for SKU enabled PCD entry\r
1806 // 1) MAX SIZE\r
1807 // 2) Current Size for each SKU_ID (It is equal to MaxSku).\r
1808 //\r
1809 SkuIdTable = GetSkuIdArray (LocalTokenNumberTableIdx, IsPeiDb);\r
2ab6330e 1810 for (Index = 0; Index < SkuIdTable[0]; Index++) {\r
efd6b412 1811 if (SkuIdTable[1 + Index] == mPcdDatabase.DxeDb->SystemSkuId) {\r
2ab6330e 1812 SizeTable[SizeTableIdx + 1 + Index] = (SIZE_INFO) *CurrentSize;\r
80408db0 1813 return TRUE;\r
1814 }\r
1815 }\r
1816 SizeTable[SizeTableIdx + 1] = (SIZE_INFO) *CurrentSize;\r
1817 return TRUE;\r
1818 }\r
1819 }\r
1820}\r
23f3e119
SZ
1821\r
1822/**\r
1823 VariableLock DynamicHiiPcd.\r
1824\r
1825 @param[in] IsPeiDb If TRUE, the pcd entry is initialized in PEI phase,\r
1826 If FALSE, the pcd entry is initialized in DXE phase.\r
1827 @param[in] VariableLock Pointer to VariableLockProtocol.\r
1828\r
1829**/\r
1830VOID\r
1831VariableLockDynamicHiiPcd (\r
1832 IN BOOLEAN IsPeiDb,\r
1833 IN EDKII_VARIABLE_LOCK_PROTOCOL *VariableLock\r
1834 )\r
1835{\r
1836 EFI_STATUS Status;\r
1837 PCD_DATABASE_INIT *Database;\r
1838 UINT32 LocalTokenCount; \r
1839 UINTN TokenNumber;\r
1840 UINT32 LocalTokenNumber;\r
1841 UINTN Offset;\r
1842 EFI_GUID *GuidTable;\r
1843 UINT8 *StringTable;\r
1844 VARIABLE_HEAD *VariableHead;\r
1845 EFI_GUID *Guid;\r
1846 UINT16 *Name;\r
1847\r
1848 Database = IsPeiDb ? mPcdDatabase.PeiDb: mPcdDatabase.DxeDb;\r
1849 LocalTokenCount = IsPeiDb ? mPeiLocalTokenCount: mDxeLocalTokenCount;\r
1850\r
1851 //\r
1852 // Go through PCD database to find out DynamicHii PCDs.\r
1853 //\r
1854 for (TokenNumber = 0; TokenNumber < LocalTokenCount; TokenNumber++) {\r
1855 if (IsPeiDb) {\r
1856 LocalTokenNumber = GetLocalTokenNumber (TRUE, TokenNumber);\r
1857 } else {\r
1858 LocalTokenNumber = GetLocalTokenNumber (FALSE, TokenNumber + mPeiLocalTokenCount);\r
1859 }\r
1860 if ((LocalTokenNumber & PCD_TYPE_HII) != 0) {\r
1861 Offset = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK;\r
1862 VariableHead = (VARIABLE_HEAD *) ((UINT8 *) Database + Offset);\r
1863 //\r
1864 // Why not to set property by VarCheckProtocol with Attributes and Property directly here?\r
1865 // It is because that set property by VarCheckProtocol will indicate the variable to\r
1866 // be a system variable, but the unknown max size of the variable is dangerous to\r
1867 // the system variable region.\r
1868 //\r
1869 if ((VariableHead->Property & VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY) != 0) {\r
1870 //\r
1871 // DynamicHii PCD with RO property set in *.dsc.\r
1872 //\r
1873 StringTable = (UINT8 *) ((UINT8 *) Database + Database->StringTableOffset);\r
1874 GuidTable = (EFI_GUID *) ((UINT8 *) Database + Database->GuidTableOffset);\r
1875 Guid = GuidTable + VariableHead->GuidTableIndex;\r
1876 Name = (UINT16*) (StringTable + VariableHead->StringIndex);\r
1877 Status = VariableLock->RequestToLock (VariableLock, Name, Guid);\r
1878 ASSERT_EFI_ERROR (Status);\r
1879 }\r
1880 }\r
1881 }\r
1882}\r
1883\r
1884/**\r
1885 VariableLockProtocol callback\r
1886 to lock the variables referenced by DynamicHii PCDs with RO property set in *.dsc.\r
1887\r
1888 @param[in] Event Event whose notification function is being invoked.\r
1889 @param[in] Context Pointer to the notification function's context.\r
1890\r
1891**/\r
1892VOID\r
1893EFIAPI\r
1894VariableLockCallBack (\r
1895 IN EFI_EVENT Event,\r
1896 IN VOID *Context\r
1897 )\r
1898{\r
1899 EFI_STATUS Status;\r
1900 EDKII_VARIABLE_LOCK_PROTOCOL *VariableLock;\r
1901\r
1902 Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **) &VariableLock);\r
1903 if (!EFI_ERROR (Status)) {\r
1904 VariableLockDynamicHiiPcd (TRUE, VariableLock);\r
1905 VariableLockDynamicHiiPcd (FALSE, VariableLock);\r
1906 }\r
1907}\r
1908\r