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