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