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