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