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