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