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