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