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