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