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