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