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