]> git.proxmox.com Git - mirror_edk2.git/blob - EdkModulePkg/Universal/PCD/Dxe/Service.c
Add Feature Flag PcdDxePcdDatabaseTraverseEnabled and PcdPeiPcdDatabaseTraverseEnabled
[mirror_edk2.git] / EdkModulePkg / Universal / PCD / Dxe / Service.c
1 /** @file
2 Private functions used by PCD DXE driver.s
3
4 Copyright (c) 2006, Intel Corporation
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13
14 Module Name: Service.c
15
16 **/
17 #include "Service.h"
18
19
20 //
21 // Build Tool will generate DXE_PCD_DB_INIT_VALUE in Autogen.h
22 // Compression Algorithm will take care of the size optimization.
23 //
24
25 PCD_DATABASE * mPcdDatabase;
26
27 LIST_ENTRY *mCallbackFnTable;
28
29 VOID *
30 GetWorker (
31 UINTN TokenNumber,
32 UINTN GetSize
33 )
34 {
35 UINT32 *LocalTokenNumberTable;
36 UINT16 *SizeTable;
37 BOOLEAN IsPeiDb;
38 UINT32 Offset;
39 EFI_GUID *GuidTable;
40 UINT16 *StringTable;
41 EFI_GUID *Guid;
42 UINT16 *Name;
43 VARIABLE_HEAD *VariableHead;
44 UINT8 *VaraiableDefaultBuffer;
45 EFI_STATUS Status;
46 UINTN DataSize;
47 UINT8 *Data;
48 VPD_HEAD *VpdHead;
49 UINT8 *PcdDb;
50 UINT16 StringTableIdx;
51 UINT32 LocalTokenNumber;
52 UINTN MaxSize;
53 UINTN TmpTokenNumber;
54
55 //
56 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
57 // We have to decrement TokenNumber by 1 to make it usable
58 // as the array index.
59 //
60 TokenNumber--;
61
62 TmpTokenNumber = TokenNumber;
63
64 //
65 // PCD_TOTAL_TOKEN_NUMBER is a auto-generated constant.
66 // It could be zero. EBC compiler is very choosy. It may
67 // report warning. So we add 1 in each size of the
68 // comparison.
69 //
70 ASSERT (TokenNumber + 1 < PCD_TOTAL_TOKEN_NUMBER + 1);
71
72 ASSERT ((GetSize == DxePcdGetSize (TokenNumber + 1)) || (GetSize == 0));
73
74 // EBC compiler is very choosy. It may report warning about comparison
75 // between UINTN and 0 . So we add 1 in each size of the
76 // comparison.
77 IsPeiDb = (TokenNumber + 1 < PEI_LOCAL_TOKEN_NUMBER + 1) ? TRUE : FALSE;
78
79 LocalTokenNumberTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.LocalTokenNumberTable :
80 mPcdDatabase->DxeDb.Init.LocalTokenNumberTable;
81
82 SizeTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.SizeTable:
83 mPcdDatabase->DxeDb.Init.SizeTable;
84
85 TokenNumber = IsPeiDb ? TokenNumber :
86 TokenNumber - PEI_LOCAL_TOKEN_NUMBER;
87
88 LocalTokenNumber = LocalTokenNumberTable[TokenNumber];
89
90 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == PCD_TYPE_SKU_ENABLED) {
91 if (GetSize == 0) {
92 GetPtrTypeSize (TmpTokenNumber, &MaxSize);
93 } else {
94 MaxSize = GetSize;
95 }
96 LocalTokenNumber = GetSkuEnabledTokenNumber (LocalTokenNumber & ~PCD_TYPE_SKU_ENABLED, MaxSize, IsPeiDb);
97 }
98
99 PcdDb = IsPeiDb ? ((UINT8 *) &mPcdDatabase->PeiDb) : ((UINT8 *) &mPcdDatabase->DxeDb);
100 StringTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.StringTable :
101 mPcdDatabase->DxeDb.Init.StringTable;
102
103 Offset = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK;
104
105 switch (LocalTokenNumber & PCD_TYPE_ALL_SET) {
106 case PCD_TYPE_VPD:
107 VpdHead = (VPD_HEAD *) ((UINT8 *) PcdDb + Offset);
108 return (VOID *) (UINTN) (FixedPcdGet32(PcdVpdBaseAddress) + VpdHead->Offset);
109
110 case PCD_TYPE_HII:
111 GuidTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.GuidTable :
112 mPcdDatabase->DxeDb.Init.GuidTable;
113
114 VariableHead = (VARIABLE_HEAD *) (PcdDb + Offset);
115
116 Guid = &(GuidTable[VariableHead->GuidTableIndex]);
117 Name = &(StringTable[VariableHead->StringIndex]);
118 VaraiableDefaultBuffer = (UINT8 *) PcdDb + VariableHead->DefaultValueOffset;
119
120 Status = GetHiiVariable (Guid, Name, &Data, &DataSize);
121 if (Status == EFI_SUCCESS) {
122 if (GetSize == 0) {
123 //
124 // It is a pointer type. So get the MaxSize reserved for
125 // this PCD entry.
126 //
127 GetPtrTypeSize (TokenNumber, &GetSize);
128 }
129 CopyMem (VaraiableDefaultBuffer, Data + VariableHead->Offset, GetSize);
130 FreePool (Data);
131 }
132 //
133 // If the operation is successful, we copy the data
134 // to the default value buffer in the PCD Database.
135 // So that we can free the Data allocated in GetHiiVariable.
136 //
137 //
138 // If the operation is not successful,
139 // Return 1) either the default value specified by Platform Integrator
140 // 2) Or the value Set by a PCD set operation.
141 //
142 return (VOID *) VaraiableDefaultBuffer;
143
144 case PCD_TYPE_STRING:
145 StringTableIdx = (UINT16) *((UINT8 *) PcdDb + Offset);
146 return (VOID *) &StringTable[StringTableIdx];
147
148 case PCD_TYPE_DATA:
149 return (VOID *) ((UINT8 *) PcdDb + Offset);
150 break;
151
152 default:
153 ASSERT (FALSE);
154 break;
155
156 }
157
158 ASSERT (FALSE);
159
160 return NULL;
161
162 }
163
164
165
166 EFI_STATUS
167 DxeRegisterCallBackWorker (
168 IN UINTN TokenNumber,
169 IN CONST GUID *Guid, OPTIONAL
170 IN PCD_PROTOCOL_CALLBACK CallBackFunction
171 )
172 {
173 CALLBACK_FN_ENTRY *FnTableEntry;
174 LIST_ENTRY *ListHead;
175 LIST_ENTRY *ListNode;
176
177 if (Guid != NULL) {
178 TokenNumber = GetExPcdTokenNumber (Guid, (UINT32) TokenNumber);
179 }
180
181 //
182 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
183 // We have to decrement TokenNumber by 1 to make it usable
184 // as the array index.
185 //
186 TokenNumber--;
187
188 ListHead = &mCallbackFnTable[TokenNumber];
189 ListNode = GetFirstNode (ListHead);
190
191 while (ListNode != ListHead) {
192 FnTableEntry = CR_FNENTRY_FROM_LISTNODE(ListNode, CALLBACK_FN_ENTRY, Node);
193
194 if (FnTableEntry->CallbackFn == CallBackFunction) {
195 //
196 // We only allow a Callback function to be register once
197 // for a TokenNumber. So just return EFI_SUCCESS
198 //
199 return EFI_SUCCESS;
200 }
201 ListNode = GetNextNode (ListHead, ListNode);
202 }
203
204 FnTableEntry = AllocatePool (sizeof(CALLBACK_FN_ENTRY));
205 ASSERT (FnTableEntry != NULL);
206
207 FnTableEntry->CallbackFn = CallBackFunction;
208 InsertTailList (ListHead, &FnTableEntry->Node);
209
210 return EFI_SUCCESS;
211 }
212
213
214
215
216 EFI_STATUS
217 DxeUnRegisterCallBackWorker (
218 IN UINTN TokenNumber,
219 IN CONST GUID *Guid, OPTIONAL
220 IN PCD_PROTOCOL_CALLBACK CallBackFunction
221 )
222 {
223 CALLBACK_FN_ENTRY *FnTableEntry;
224 LIST_ENTRY *ListHead;
225 LIST_ENTRY *ListNode;
226
227 if (Guid != NULL) {
228 TokenNumber = GetExPcdTokenNumber (Guid, (UINT32) TokenNumber);
229 }
230
231 //
232 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
233 // We have to decrement TokenNumber by 1 to make it usable
234 // as the array index.
235 //
236 TokenNumber--;
237
238 ListHead = &mCallbackFnTable[TokenNumber];
239 ListNode = GetFirstNode (ListHead);
240
241 while (ListNode != ListHead) {
242 FnTableEntry = CR_FNENTRY_FROM_LISTNODE(ListNode, CALLBACK_FN_ENTRY, Node);
243
244 if (FnTableEntry->CallbackFn == CallBackFunction) {
245 //
246 // We only allow a Callback function to be register once
247 // for a TokenNumber. So we can safely remove the Node from
248 // the Link List and return EFI_SUCCESS.
249 //
250 RemoveEntryList (ListNode);
251 FreePool (FnTableEntry);
252
253 return EFI_SUCCESS;
254 }
255 ListNode = GetNextNode (ListHead, ListNode);
256 }
257
258 return EFI_INVALID_PARAMETER;
259 }
260
261
262
263 EFI_STATUS
264 ExGetNextTokeNumber (
265 IN CONST EFI_GUID *Guid,
266 IN OUT UINTN *TokenNumber,
267 IN EFI_GUID *GuidTable,
268 IN UINTN SizeOfGuidTable,
269 IN DYNAMICEX_MAPPING *ExMapTable,
270 IN UINTN SizeOfExMapTable
271 )
272 {
273 EFI_GUID *MatchGuid;
274 UINTN Idx;
275 UINTN GuidTableIdx;
276 BOOLEAN Found;
277
278 MatchGuid = ScanGuid (GuidTable, SizeOfGuidTable, Guid);
279 if (MatchGuid == NULL) {
280 return EFI_NOT_FOUND;
281 }
282
283 Found = FALSE;
284 GuidTableIdx = MatchGuid - GuidTable;
285 for (Idx = 0; Idx < SizeOfExMapTable; Idx++) {
286 if (ExMapTable[Idx].ExGuidIndex == GuidTableIdx) {
287 Found = TRUE;
288 break;
289 }
290 }
291
292 if (Found) {
293 if (*TokenNumber == PCD_INVALID_TOKEN_NUMBER) {
294 *TokenNumber = ExMapTable[Idx].ExTokenNumber;
295 return EFI_SUCCESS;
296 }
297
298 for ( ; Idx < SizeOfExMapTable; Idx++) {
299 if (ExMapTable[Idx].ExTokenNumber == *TokenNumber) {
300 Idx++;
301 if (Idx == SizeOfExMapTable) {
302 //
303 // Exceed the length of ExMap Table
304 //
305 *TokenNumber = PCD_INVALID_TOKEN_NUMBER;
306 return EFI_SUCCESS;
307 } else if (ExMapTable[Idx].ExGuidIndex == GuidTableIdx) {
308 //
309 // Found the next match
310 //
311 *TokenNumber = ExMapTable[Idx].ExTokenNumber;
312 return EFI_SUCCESS;
313 } else {
314 //
315 // Guid has been changed. It is the next Token Space Guid.
316 // We should flag no more TokenNumber.
317 //
318 *TokenNumber = PCD_INVALID_TOKEN_NUMBER;
319 return EFI_SUCCESS;
320 }
321 }
322 }
323 }
324
325 return EFI_NOT_FOUND;
326 }
327
328
329
330
331 VOID
332 BuildPcdDxeDataBase (
333 VOID
334 )
335 {
336 PEI_PCD_DATABASE *PeiDatabase;
337 EFI_HOB_GUID_TYPE *GuidHob;
338 UINTN Idx;
339
340 mPcdDatabase = AllocateZeroPool (sizeof(PCD_DATABASE));
341 ASSERT (mPcdDatabase != NULL);
342
343 GuidHob = GetFirstGuidHob (&gPcdDataBaseHobGuid);
344
345 if (GuidHob != NULL) {
346
347 //
348 // We will copy over the PEI phase's PCD Database.
349 //
350 // If no PEIMs use dynamic Pcd Entry, the Pcd Service PEIM
351 // should not be included at all. So the GuidHob could
352 // be NULL. If it is NULL, we just copy over the DXE Default
353 // Value to PCD Database.
354 //
355
356 PeiDatabase = (PEI_PCD_DATABASE *) GET_GUID_HOB_DATA (GuidHob);
357 //
358 // Copy PCD Entries refereneced in PEI phase to PCD DATABASE
359 //
360 CopyMem (&mPcdDatabase->PeiDb, PeiDatabase, sizeof (PEI_PCD_DATABASE));
361 }
362
363 //
364 // Copy PCD Entries with default value to PCD DATABASE
365 //
366 CopyMem (&mPcdDatabase->DxeDb.Init, &gDXEPcdDbInit, sizeof(DXE_PCD_DATABASE_INIT));
367
368
369 //
370 // Initialized the Callback Function Table
371 //
372
373 mCallbackFnTable = AllocateZeroPool (PCD_TOTAL_TOKEN_NUMBER * sizeof (LIST_ENTRY));
374
375 // EBC compiler is very choosy. It may report warning about comparison
376 // between UINTN and 0 . So we add 1 in each size of the
377 // comparison.
378 for (Idx = 0; Idx + 1 < PCD_TOTAL_TOKEN_NUMBER + 1; Idx++) {
379 InitializeListHead (&mCallbackFnTable[Idx]);
380 }
381
382 return;
383 }
384
385
386
387 EFI_STATUS
388 GetHiiVariable (
389 IN EFI_GUID *VariableGuid,
390 IN UINT16 *VariableName,
391 OUT UINT8 **VariableData,
392 OUT UINTN *VariableSize
393 )
394 {
395 UINTN Size;
396 EFI_STATUS Status;
397 UINT8 *Buffer;
398
399 Size = 0;
400 Buffer = NULL;
401
402 Status = gRT->GetVariable (
403 (UINT16 *)VariableName,
404 VariableGuid,
405 NULL,
406 &Size,
407 Buffer
408 );
409
410 if (Status == EFI_BUFFER_TOO_SMALL) {
411 Buffer = (UINT8 *) AllocatePool (Size);
412
413 ASSERT (Buffer != NULL);
414
415 Status = gRT->GetVariable (
416 VariableName,
417 VariableGuid,
418 NULL,
419 &Size,
420 Buffer
421 );
422
423 ASSERT (Status == EFI_SUCCESS);
424 *VariableData = Buffer;
425 *VariableSize = Size;
426 }
427
428 return Status;
429 }
430
431
432 UINT32
433 GetSkuEnabledTokenNumber (
434 UINT32 LocalTokenNumber,
435 UINTN Size,
436 BOOLEAN IsPeiDb
437 )
438 {
439 SKU_HEAD *SkuHead;
440 SKU_ID *SkuIdTable;
441 INTN i;
442 UINT8 *Value;
443 SKU_ID *PhaseSkuIdTable;
444 UINT8 *PcdDb;
445
446 ASSERT ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0);
447
448 PcdDb = IsPeiDb ? (UINT8 *) &mPcdDatabase->PeiDb : (UINT8 *) &mPcdDatabase->DxeDb;
449
450 SkuHead = (SKU_HEAD *) (PcdDb + (LocalTokenNumber & PCD_DATABASE_OFFSET_MASK));
451 Value = (UINT8 *) (PcdDb + SkuHead->SkuDataStartOffset);
452
453 PhaseSkuIdTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.SkuIdTable :
454 mPcdDatabase->DxeDb.Init.SkuIdTable;
455
456 SkuIdTable = &PhaseSkuIdTable[SkuHead->SkuIdTableOffset];
457
458 for (i = 0; i < SkuIdTable[0]; i++) {
459 if (mPcdDatabase->PeiDb.Init.SystemSkuId == SkuIdTable[i + 1]) {
460 break;
461 }
462 }
463 ASSERT (i < SkuIdTable[0]);
464
465 switch (LocalTokenNumber & PCD_TYPE_ALL_SET) {
466 case PCD_TYPE_VPD:
467 Value = (UINT8 *) &(((VPD_HEAD *) Value)[i]);
468 return (UINT32) ((Value - PcdDb) | PCD_TYPE_VPD);
469
470 case PCD_TYPE_HII:
471 Value = (UINT8 *) &(((VARIABLE_HEAD *) Value)[i]);
472 return (UINT32) ((Value - PcdDb) | PCD_TYPE_HII);
473
474 case PCD_TYPE_STRING:
475 Value = (UINT8 *) &(((STRING_HEAD *) Value)[i]);
476 return (UINT32) ((Value - PcdDb) | PCD_TYPE_STRING);
477
478 case PCD_TYPE_DATA:
479 Value += Size * i;
480 return (UINT32) (Value - PcdDb);
481
482 default:
483 ASSERT (FALSE);
484 }
485
486 ASSERT (FALSE);
487
488 return 0;
489
490 }
491
492
493
494
495
496 VOID
497 InvokeCallbackOnSet (
498 UINT32 ExTokenNumber,
499 CONST EFI_GUID *Guid, OPTIONAL
500 UINTN TokenNumber,
501 VOID *Data,
502 UINTN Size
503 )
504 {
505 CALLBACK_FN_ENTRY *FnTableEntry;
506 LIST_ENTRY *ListHead;
507 LIST_ENTRY *ListNode;
508
509 //
510 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
511 // We have to decrement TokenNumber by 1 to make it usable
512 // as the array index.
513 //
514 TokenNumber--;
515
516 ListHead = &mCallbackFnTable[TokenNumber];
517 ListNode = GetFirstNode (ListHead);
518
519 while (ListNode != ListHead) {
520 FnTableEntry = CR_FNENTRY_FROM_LISTNODE(ListNode, CALLBACK_FN_ENTRY, Node);
521
522 FnTableEntry->CallbackFn(Guid,
523 (Guid == NULL) ? TokenNumber : ExTokenNumber,
524 Data,
525 Size);
526
527 ListNode = GetNextNode (ListHead, ListNode);
528 }
529
530 return;
531 }
532
533
534 EFI_STATUS
535 SetValueWorker (
536 IN UINTN TokenNumber,
537 IN VOID *Data,
538 IN UINTN Size
539 )
540 {
541 return SetWorker (TokenNumber, Data, &Size, FALSE);
542 }
543
544
545 EFI_STATUS
546 SetWorker (
547 IN UINTN TokenNumber,
548 IN VOID *Data,
549 IN OUT UINTN *Size,
550 IN BOOLEAN PtrType
551 )
552 {
553 UINT32 *LocalTokenNumberTable;
554 BOOLEAN IsPeiDb;
555 UINT32 LocalTokenNumber;
556 EFI_GUID *GuidTable;
557 UINT16 *StringTable;
558 EFI_GUID *Guid;
559 UINT16 *Name;
560 UINTN VariableOffset;
561 VOID *InternalData;
562 VARIABLE_HEAD *VariableHead;
563 UINTN Offset;
564 UINT8 *PcdDb;
565 EFI_STATUS Status;
566 UINTN MaxSize;
567 UINTN TmpTokenNumber;
568
569 //
570 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
571 // We have to decrement TokenNumber by 1 to make it usable
572 // as the array index.
573 //
574 TokenNumber--;
575
576 TmpTokenNumber = TokenNumber;
577
578 // EBC compiler is very choosy. It may report warning about comparison
579 // between UINTN and 0 . So we add 1 in each size of the
580 // comparison.
581
582 ASSERT (TokenNumber + 1 < PCD_TOTAL_TOKEN_NUMBER + 1);
583
584 if (!PtrType) {
585 ASSERT (*Size == DxePcdGetSize (TokenNumber + 1));
586 }
587
588 // EBC compiler is very choosy. It may report warning about comparison
589 // between UINTN and 0 . So we add 1 in each size of the
590 // comparison.
591 IsPeiDb = (TokenNumber + 1 < PEI_LOCAL_TOKEN_NUMBER + 1) ? TRUE : FALSE;
592
593 LocalTokenNumberTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.LocalTokenNumberTable :
594 mPcdDatabase->DxeDb.Init.LocalTokenNumberTable;
595
596 // EBC compiler is very choosy. It may report warning about comparison
597 // between UINTN and 0 . So we add 1 in each size of the
598 // comparison.
599 if ((TokenNumber + 1 < PEI_NEX_TOKEN_NUMBER + 1) ||
600 (TokenNumber + 1 >= PEI_LOCAL_TOKEN_NUMBER + 1 || TokenNumber + 1 < (PEI_LOCAL_TOKEN_NUMBER + DXE_NEX_TOKEN_NUMBER + 1))) {
601 InvokeCallbackOnSet (0, NULL, TokenNumber + 1, Data, *Size);
602 }
603
604 TokenNumber = IsPeiDb ? TokenNumber
605 : TokenNumber - PEI_LOCAL_TOKEN_NUMBER;
606
607 LocalTokenNumber = LocalTokenNumberTable[TokenNumber];
608
609 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == PCD_TYPE_SKU_ENABLED) {
610 if (PtrType) {
611 GetPtrTypeSize (TmpTokenNumber, &MaxSize);
612 } else {
613 MaxSize = *Size;
614 }
615 LocalTokenNumber = GetSkuEnabledTokenNumber (LocalTokenNumber & ~PCD_TYPE_SKU_ENABLED, MaxSize, IsPeiDb);
616 }
617
618 Offset = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK;
619
620 PcdDb = IsPeiDb ? ((UINT8 *) &mPcdDatabase->PeiDb) : ((UINT8 *) &mPcdDatabase->DxeDb);
621
622 StringTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.StringTable :
623 mPcdDatabase->DxeDb.Init.StringTable;
624
625 InternalData = PcdDb + Offset;
626
627 switch (LocalTokenNumber & PCD_TYPE_ALL_SET) {
628 case PCD_TYPE_VPD:
629 ASSERT (FALSE);
630 return EFI_INVALID_PARAMETER;
631
632 case PCD_TYPE_STRING:
633 if (SetPtrTypeSize (TokenNumber, Size)) {
634 CopyMem (&StringTable[*((UINT16 *)InternalData)], Data, *Size);
635 return EFI_SUCCESS;
636 } else {
637 return EFI_INVALID_PARAMETER;
638 }
639
640 case PCD_TYPE_HII:
641 if (PtrType) {
642 if (!SetPtrTypeSize (TokenNumber, Size)) {
643 return EFI_INVALID_PARAMETER;
644 }
645 }
646
647 GuidTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.GuidTable :
648 mPcdDatabase->DxeDb.Init.GuidTable;
649
650 VariableHead = (VARIABLE_HEAD *) (PcdDb + Offset);
651
652 Guid = &(GuidTable[VariableHead->GuidTableIndex]);
653 Name = &(StringTable[VariableHead->StringIndex]);
654 VariableOffset = VariableHead->Offset;
655
656 Status = SetHiiVariable (Guid, Name, Data, *Size, VariableOffset);
657
658 if (EFI_NOT_FOUND == Status) {
659 CopyMem (PcdDb + VariableHead->DefaultValueOffset, Data, *Size);
660 return EFI_SUCCESS;
661 } else {
662 return Status;
663 }
664
665 //
666 // Bug Bug: Please implement this
667 //
668
669 case PCD_TYPE_DATA:
670 if (PtrType) {
671 if (SetPtrTypeSize (TokenNumber, Size)) {
672 CopyMem (InternalData, Data, *Size);
673 return EFI_SUCCESS;
674 } else {
675 return EFI_INVALID_PARAMETER;
676 }
677 }
678
679 switch (*Size) {
680 case sizeof(UINT8):
681 *((UINT8 *) InternalData) = *((UINT8 *) Data);
682 return EFI_SUCCESS;
683
684 case sizeof(UINT16):
685 *((UINT16 *) InternalData) = *((UINT16 *) Data);
686 return EFI_SUCCESS;
687
688 case sizeof(UINT32):
689 *((UINT32 *) InternalData) = *((UINT32 *) Data);
690 return EFI_SUCCESS;
691
692 case sizeof(UINT64):
693 *((UINT64 *) InternalData) = *((UINT64 *) Data);
694 return EFI_SUCCESS;
695
696 default:
697 ASSERT (FALSE);
698 return EFI_NOT_FOUND;
699 }
700
701 default:
702 ASSERT (FALSE);
703 break;
704 }
705
706 ASSERT (FALSE);
707 return EFI_NOT_FOUND;
708 }
709
710
711
712
713
714 VOID *
715 ExGetWorker (
716 IN CONST EFI_GUID *Guid,
717 IN UINTN ExTokenNumber,
718 IN UINTN GetSize
719 )
720 {
721 return GetWorker(GetExPcdTokenNumber (Guid, (UINT32) ExTokenNumber), GetSize);
722 }
723
724
725
726
727 EFI_STATUS
728 ExSetValueWorker (
729 IN UINTN ExTokenNumber,
730 IN CONST EFI_GUID *Guid,
731 IN VOID *Data,
732 IN UINTN SetSize
733 )
734 {
735 return ExSetWorker (ExTokenNumber, Guid, Data, &SetSize, FALSE);
736 }
737
738
739 EFI_STATUS
740 ExSetWorker (
741 IN UINTN ExTokenNumber,
742 IN CONST EFI_GUID *Guid,
743 IN VOID *Data,
744 IN OUT UINTN *SetSize,
745 IN BOOLEAN PtrType
746 )
747 {
748 UINTN TokenNumber;
749
750 TokenNumber = GetExPcdTokenNumber (Guid, (UINT32) ExTokenNumber);
751
752 InvokeCallbackOnSet ((UINT32) ExTokenNumber, Guid, TokenNumber, Data, *SetSize);
753
754 return SetWorker (TokenNumber, Data, SetSize, PtrType);
755
756 }
757
758
759
760
761 EFI_STATUS
762 SetHiiVariable (
763 IN EFI_GUID *VariableGuid,
764 IN UINT16 *VariableName,
765 IN CONST VOID *Data,
766 IN UINTN DataSize,
767 IN UINTN Offset
768 )
769 {
770 UINTN Size;
771 VOID *Buffer;
772 EFI_STATUS Status;
773 UINT32 Attribute;
774
775 Size = 0;
776
777 Status = gRT->GetVariable (
778 (UINT16 *)VariableName,
779 VariableGuid,
780 &Attribute,
781 &Size,
782 NULL
783 );
784
785 if (Status == EFI_BUFFER_TOO_SMALL) {
786
787 Buffer = AllocatePool (Size);
788
789 ASSERT (Buffer != NULL);
790
791 Status = gRT->GetVariable (
792 VariableName,
793 VariableGuid,
794 &Attribute,
795 &Size,
796 Buffer
797 );
798
799 ASSERT_EFI_ERROR (Status);
800
801 CopyMem ((UINT8 *)Buffer + Offset, Data, DataSize);
802
803 Status = gRT->SetVariable (
804 VariableName,
805 VariableGuid,
806 Attribute,
807 Size,
808 Buffer
809 );
810
811 FreePool (Buffer);
812 return Status;
813
814 }
815
816 //
817 // If we drop to here, we don't have a Variable entry in
818 // the variable service yet. So, we will save the data
819 // in the PCD Database's volatile area.
820 //
821 return Status;
822 }
823
824
825
826
827
828 UINTN
829 GetExPcdTokenNumber (
830 IN CONST EFI_GUID *Guid,
831 IN UINT32 ExTokenNumber
832 )
833 {
834 UINT32 i;
835 DYNAMICEX_MAPPING *ExMap;
836 EFI_GUID *GuidTable;
837 EFI_GUID *MatchGuid;
838 UINTN MatchGuidIdx;
839
840 if (!PEI_DATABASE_EMPTY) {
841 ExMap = mPcdDatabase->PeiDb.Init.ExMapTable;
842 GuidTable = mPcdDatabase->PeiDb.Init.GuidTable;
843
844 MatchGuid = ScanGuid (GuidTable, sizeof(mPcdDatabase->PeiDb.Init.GuidTable), Guid);
845
846 if (MatchGuid != NULL) {
847
848 MatchGuidIdx = MatchGuid - GuidTable;
849
850 for (i = 0; i < PEI_EXMAPPING_TABLE_SIZE; i++) {
851 if ((ExTokenNumber == ExMap[i].ExTokenNumber) &&
852 (MatchGuidIdx == ExMap[i].ExGuidIndex)) {
853 return ExMap[i].LocalTokenNumber;
854
855 }
856 }
857 }
858 }
859
860 ExMap = mPcdDatabase->DxeDb.Init.ExMapTable;
861 GuidTable = mPcdDatabase->DxeDb.Init.GuidTable;
862
863 MatchGuid = ScanGuid (GuidTable, sizeof(mPcdDatabase->DxeDb.Init.GuidTable), Guid);
864 //
865 // We need to ASSERT here. If GUID can't be found in GuidTable, this is a
866 // error in the BUILD system.
867 //
868 ASSERT (MatchGuid != NULL);
869
870 MatchGuidIdx = MatchGuid - GuidTable;
871
872 for (i = 0; i < DXE_EXMAPPING_TABLE_SIZE; i++) {
873 if ((ExTokenNumber == ExMap[i].ExTokenNumber) &&
874 (MatchGuidIdx == ExMap[i].ExGuidIndex)) {
875 return ExMap[i].LocalTokenNumber;
876 }
877 }
878
879 ASSERT (FALSE);
880
881 return 0;
882 }
883
884
885
886 SKU_ID *
887 GetSkuIdArray (
888 IN UINTN LocalTokenNumberTableIdx,
889 IN BOOLEAN IsPeiPcd
890 )
891 {
892 SKU_HEAD *SkuHead;
893 UINTN LocalTokenNumber;
894 UINT8 *Database;
895
896 if (IsPeiPcd) {
897 LocalTokenNumber = mPcdDatabase->PeiDb.Init.LocalTokenNumberTable[LocalTokenNumberTableIdx];
898 Database = (UINT8 *) &mPcdDatabase->PeiDb;
899 } else {
900 LocalTokenNumber = mPcdDatabase->DxeDb.Init.LocalTokenNumberTable[LocalTokenNumberTableIdx - PEI_LOCAL_TOKEN_NUMBER];
901 Database = (UINT8 *) &mPcdDatabase->DxeDb;
902 }
903
904 ASSERT ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) != 0);
905
906 SkuHead = (SKU_HEAD *) ((UINT8 *)Database + (LocalTokenNumber & PCD_DATABASE_OFFSET_MASK));
907
908 return (SKU_ID *) (Database + SkuHead->SkuIdTableOffset);
909
910 }
911
912
913
914 UINTN
915 GetSizeTableIndexA (
916 IN UINTN LocalTokenNumberTableIdx,
917 IN UINT32 *LocalTokenNumberTable,
918 IN BOOLEAN IsPeiDb
919 )
920 {
921 UINTN i;
922 UINTN SizeTableIdx;
923 UINTN LocalTokenNumber;
924 SKU_ID *SkuIdTable;
925
926 SizeTableIdx = 0;
927
928 for (i=0; i<LocalTokenNumberTableIdx; i++) {
929 LocalTokenNumber = LocalTokenNumberTable[i];
930
931 if ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER) {
932 //
933 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type
934 // PCD entry.
935 //
936 if (LocalTokenNumber & PCD_TYPE_VPD) {
937 //
938 // We have only one entry for VPD enabled PCD entry:
939 // 1) MAX Size.
940 // We consider current size is equal to MAX size.
941 //
942 SizeTableIdx++;
943 } else {
944 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0) {
945 //
946 // We have only two entry for Non-Sku enabled PCD entry:
947 // 1) MAX SIZE
948 // 2) Current Size
949 //
950 SizeTableIdx += 2;
951 } else {
952 //
953 // We have these entry for SKU enabled PCD entry
954 // 1) MAX SIZE
955 // 2) Current Size for each SKU_ID (It is equal to MaxSku).
956 //
957 SkuIdTable = GetSkuIdArray (i, IsPeiDb);
958 SizeTableIdx += (UINTN)*SkuIdTable + 1;
959 }
960 }
961 }
962
963 }
964
965 return SizeTableIdx;
966 }
967
968
969
970
971 UINTN
972 GetSizeTableIndex (
973 IN UINTN LocalTokenNumberTableIdx,
974 IN BOOLEAN IsPeiDb
975 )
976 {
977 UINT32 *LocalTokenNumberTable;
978
979 if (IsPeiDb) {
980 LocalTokenNumberTable = mPcdDatabase->PeiDb.Init.LocalTokenNumberTable;
981 } else {
982 LocalTokenNumberTable = mPcdDatabase->DxeDb.Init.LocalTokenNumberTable;
983 }
984 return GetSizeTableIndexA (LocalTokenNumberTableIdx,
985 LocalTokenNumberTable,
986 IsPeiDb);
987 }
988
989
990
991 UINTN
992 GetPtrTypeSize (
993 IN UINTN LocalTokenNumberTableIdx,
994 OUT UINTN *MaxSize
995 )
996 {
997 INTN SizeTableIdx;
998 UINTN LocalTokenNumber;
999 SKU_ID *SkuIdTable;
1000 SIZE_INFO *SizeTable;
1001 UINTN i;
1002 BOOLEAN IsPeiDb;
1003 UINT32 *LocalTokenNumberTable;
1004
1005 // EBC compiler is very choosy. It may report warning about comparison
1006 // between UINTN and 0 . So we add 1 in each size of the
1007 // comparison.
1008 IsPeiDb = (BOOLEAN) (LocalTokenNumberTableIdx + 1 < PEI_LOCAL_TOKEN_NUMBER + 1);
1009
1010
1011 if (IsPeiDb) {
1012 LocalTokenNumberTable = mPcdDatabase->PeiDb.Init.LocalTokenNumberTable;
1013 SizeTable = mPcdDatabase->PeiDb.Init.SizeTable;
1014 } else {
1015 LocalTokenNumberTableIdx -= PEI_LOCAL_TOKEN_NUMBER;
1016 LocalTokenNumberTable = mPcdDatabase->DxeDb.Init.LocalTokenNumberTable;
1017 SizeTable = mPcdDatabase->DxeDb.Init.SizeTable;
1018 }
1019
1020 LocalTokenNumber = LocalTokenNumberTable[LocalTokenNumberTableIdx];
1021
1022 ASSERT ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER);
1023
1024 SizeTableIdx = GetSizeTableIndex (LocalTokenNumberTableIdx, IsPeiDb);
1025
1026 *MaxSize = SizeTable[SizeTableIdx];
1027 //
1028 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type
1029 // PCD entry.
1030 //
1031 if (LocalTokenNumber & PCD_TYPE_VPD) {
1032 //
1033 // We have only one entry for VPD enabled PCD entry:
1034 // 1) MAX Size.
1035 // We consider current size is equal to MAX size.
1036 //
1037 return *MaxSize;
1038 } else {
1039 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0) {
1040 //
1041 // We have only two entry for Non-Sku enabled PCD entry:
1042 // 1) MAX SIZE
1043 // 2) Current Size
1044 //
1045 return SizeTable[SizeTableIdx + 1];
1046 } else {
1047 //
1048 // We have these entry for SKU enabled PCD entry
1049 // 1) MAX SIZE
1050 // 2) Current Size for each SKU_ID (It is equal to MaxSku).
1051 //
1052 SkuIdTable = GetSkuIdArray (LocalTokenNumberTableIdx, IsPeiDb);
1053 for (i = 0; i < SkuIdTable[0]; i++) {
1054 if (SkuIdTable[1 + i] == mPcdDatabase->PeiDb.Init.SystemSkuId) {
1055 return SizeTable[SizeTableIdx + 1 + i];
1056 }
1057 }
1058 return SizeTable[SizeTableIdx + 1];
1059 }
1060 }
1061 }
1062
1063
1064
1065 BOOLEAN
1066 SetPtrTypeSize (
1067 IN UINTN LocalTokenNumberTableIdx,
1068 IN OUT UINTN *CurrentSize
1069 )
1070 {
1071 INTN SizeTableIdx;
1072 UINTN LocalTokenNumber;
1073 SKU_ID *SkuIdTable;
1074 SIZE_INFO *SizeTable;
1075 UINTN i;
1076 UINTN MaxSize;
1077 BOOLEAN IsPeiDb;
1078 UINT32 *LocalTokenNumberTable;
1079
1080 // EBC compiler is very choosy. It may report warning about comparison
1081 // between UINTN and 0 . So we add 1 in each size of the
1082 // comparison.
1083 IsPeiDb = (BOOLEAN) (LocalTokenNumberTableIdx + 1 < PEI_LOCAL_TOKEN_NUMBER + 1);
1084
1085 if (IsPeiDb) {
1086 LocalTokenNumberTable = mPcdDatabase->PeiDb.Init.LocalTokenNumberTable;
1087 SizeTable = mPcdDatabase->PeiDb.Init.SizeTable;
1088 } else {
1089 LocalTokenNumberTableIdx -= PEI_LOCAL_TOKEN_NUMBER;
1090 LocalTokenNumberTable = mPcdDatabase->DxeDb.Init.LocalTokenNumberTable;
1091 SizeTable = mPcdDatabase->DxeDb.Init.SizeTable;
1092 }
1093
1094 LocalTokenNumber = LocalTokenNumberTable[LocalTokenNumberTableIdx];
1095
1096 ASSERT ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER);
1097
1098 SizeTableIdx = GetSizeTableIndex (LocalTokenNumberTableIdx, IsPeiDb);
1099
1100 MaxSize = SizeTable[SizeTableIdx];
1101 //
1102 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type
1103 // PCD entry.
1104 //
1105 if (LocalTokenNumber & PCD_TYPE_VPD) {
1106 //
1107 // We shouldn't come here as we don't support SET for VPD
1108 //
1109 ASSERT (FALSE);
1110 return FALSE;
1111 } else {
1112 if ((*CurrentSize > MaxSize) ||
1113 (*CurrentSize == MAX_ADDRESS)) {
1114 *CurrentSize = MaxSize;
1115 return FALSE;
1116 }
1117
1118 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0) {
1119 //
1120 // We have only two entry for Non-Sku enabled PCD entry:
1121 // 1) MAX SIZE
1122 // 2) Current Size
1123 //
1124 SizeTable[SizeTableIdx + 1] = (SIZE_INFO) *CurrentSize;
1125 return TRUE;
1126 } else {
1127 //
1128 // We have these entry for SKU enabled PCD entry
1129 // 1) MAX SIZE
1130 // 2) Current Size for each SKU_ID (It is equal to MaxSku).
1131 //
1132 SkuIdTable = GetSkuIdArray (LocalTokenNumberTableIdx, IsPeiDb);
1133 for (i = 0; i < SkuIdTable[0]; i++) {
1134 if (SkuIdTable[1 + i] == mPcdDatabase->PeiDb.Init.SystemSkuId) {
1135 SizeTable[SizeTableIdx + 1 + i] = (SIZE_INFO) *CurrentSize;
1136 return TRUE;
1137 }
1138 }
1139 SizeTable[SizeTableIdx + 1] = (SIZE_INFO) *CurrentSize;
1140 return TRUE;
1141 }
1142 }
1143 }
1144