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