]> git.proxmox.com Git - mirror_edk2.git/blob - EdkModulePkg/Universal/PCD/Dxe/Service.c
Partially make EdkModulePkg pass intel IPF compiler with /W4 /WX switched on.
[mirror_edk2.git] / EdkModulePkg / 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 #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 EFI_GUID *GuidTable;
32 UINT16 *StringTable;
33 EFI_GUID *Guid;
34 UINT16 *Name;
35 VARIABLE_HEAD *VariableHead;
36 UINT8 *VaraiableDefaultBuffer;
37 UINT8 *Data;
38 VPD_HEAD *VpdHead;
39 UINT8 *PcdDb;
40 VOID *RetPtr;
41 UINTN MaxSize;
42 UINTN TmpTokenNumber;
43 UINTN DataSize;
44 EFI_STATUS Status;
45 UINT32 LocalTokenNumber;
46 UINT32 Offset;
47 UINT16 StringTableIdx;
48 BOOLEAN IsPeiDb;
49
50 //
51 // Aquire lock to prevent reentrance from TPL_CALLBACK level
52 //
53 EfiAcquireLock (&mPcdDatabaseLock);
54
55 RetPtr = NULL;
56 //
57 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
58 // We have to decrement TokenNumber by 1 to make it usable
59 // as the array index.
60 //
61 TokenNumber--;
62
63 TmpTokenNumber = TokenNumber;
64
65 //
66 // PCD_TOTAL_TOKEN_NUMBER is a auto-generated constant.
67 // It could be zero. EBC compiler is very choosy. It may
68 // report warning. So we add 1 in each size of the
69 // comparison.
70 //
71 ASSERT (TokenNumber + 1 < PCD_TOTAL_TOKEN_NUMBER + 1);
72
73 ASSERT ((GetSize == DxePcdGetSize (TokenNumber + 1)) || (GetSize == 0));
74
75 // EBC compiler is very choosy. It may report warning about comparison
76 // between UINTN and 0 . So we add 1 in each size of the
77 // comparison.
78 IsPeiDb = (BOOLEAN) ((TokenNumber + 1 < PEI_LOCAL_TOKEN_NUMBER + 1) ? TRUE : FALSE);
79
80 LocalTokenNumberTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.LocalTokenNumberTable :
81 mPcdDatabase->DxeDb.Init.LocalTokenNumberTable;
82
83 TokenNumber = IsPeiDb ? TokenNumber :
84 TokenNumber - PEI_LOCAL_TOKEN_NUMBER;
85
86 LocalTokenNumber = LocalTokenNumberTable[TokenNumber];
87
88 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == PCD_TYPE_SKU_ENABLED) {
89 if (GetSize == 0) {
90 GetPtrTypeSize (TmpTokenNumber, &MaxSize);
91 } else {
92 MaxSize = GetSize;
93 }
94 LocalTokenNumber = GetSkuEnabledTokenNumber (LocalTokenNumber & ~PCD_TYPE_SKU_ENABLED, MaxSize, IsPeiDb);
95 }
96
97 PcdDb = IsPeiDb ? ((UINT8 *) &mPcdDatabase->PeiDb) : ((UINT8 *) &mPcdDatabase->DxeDb);
98 StringTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.StringTable :
99 mPcdDatabase->DxeDb.Init.StringTable;
100
101 Offset = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK;
102
103 switch (LocalTokenNumber & PCD_TYPE_ALL_SET) {
104 case PCD_TYPE_VPD:
105 VpdHead = (VPD_HEAD *) ((UINT8 *) PcdDb + Offset);
106 RetPtr = (VOID *) (UINTN) (FixedPcdGet32(PcdVpdBaseAddress) + VpdHead->Offset);
107 break;
108
109 case PCD_TYPE_HII:
110 GuidTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.GuidTable :
111 mPcdDatabase->DxeDb.Init.GuidTable;
112
113 VariableHead = (VARIABLE_HEAD *) (PcdDb + Offset);
114
115 Guid = &(GuidTable[VariableHead->GuidTableIndex]);
116 Name = &(StringTable[VariableHead->StringIndex]);
117 VaraiableDefaultBuffer = (UINT8 *) PcdDb + VariableHead->DefaultValueOffset;
118
119 Status = GetHiiVariable (Guid, Name, &Data, &DataSize);
120 if (Status == EFI_SUCCESS) {
121 if (GetSize == 0) {
122 //
123 // It is a pointer type. So get the MaxSize reserved for
124 // this PCD entry.
125 //
126 GetPtrTypeSize (TmpTokenNumber, &GetSize);
127 }
128 CopyMem (VaraiableDefaultBuffer, Data + VariableHead->Offset, GetSize);
129 FreePool (Data);
130 }
131 //
132 // If the operation is successful, we copy the data
133 // to the default value buffer in the PCD Database.
134 // So that we can free the Data allocated in GetHiiVariable.
135 //
136 //
137 // If the operation is not successful,
138 // Return 1) either the default value specified by Platform Integrator
139 // 2) Or the value Set by a PCD set operation.
140 //
141 RetPtr = (VOID *) VaraiableDefaultBuffer;
142 break;
143
144 case PCD_TYPE_STRING:
145 StringTableIdx = (UINT16) *((UINT8 *) PcdDb + Offset);
146 RetPtr = (VOID *) &StringTable[StringTableIdx];
147 break;
148
149 case PCD_TYPE_DATA:
150 RetPtr = (VOID *) ((UINT8 *) PcdDb + Offset);
151 break;
152
153 default:
154 ASSERT (FALSE);
155 break;
156
157 }
158
159 EfiReleaseLock (&mPcdDatabaseLock);
160
161 return RetPtr;
162
163 }
164
165
166
167 EFI_STATUS
168 DxeRegisterCallBackWorker (
169 IN UINTN TokenNumber,
170 IN CONST GUID *Guid, OPTIONAL
171 IN PCD_PROTOCOL_CALLBACK CallBackFunction
172 )
173 {
174 CALLBACK_FN_ENTRY *FnTableEntry;
175 LIST_ENTRY *ListHead;
176 LIST_ENTRY *ListNode;
177
178 if (Guid != NULL) {
179 TokenNumber = GetExPcdTokenNumber (Guid, (UINT32) TokenNumber);
180 }
181
182 //
183 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
184 // We have to decrement TokenNumber by 1 to make it usable
185 // as the array index.
186 //
187 TokenNumber--;
188
189 ListHead = &mCallbackFnTable[TokenNumber];
190 ListNode = GetFirstNode (ListHead);
191
192 while (ListNode != ListHead) {
193 FnTableEntry = CR_FNENTRY_FROM_LISTNODE(ListNode, CALLBACK_FN_ENTRY, Node);
194
195 if (FnTableEntry->CallbackFn == CallBackFunction) {
196 //
197 // We only allow a Callback function to be register once
198 // for a TokenNumber. So just return EFI_SUCCESS
199 //
200 return EFI_SUCCESS;
201 }
202 ListNode = GetNextNode (ListHead, ListNode);
203 }
204
205 FnTableEntry = AllocatePool (sizeof(CALLBACK_FN_ENTRY));
206 ASSERT (FnTableEntry != NULL);
207
208 FnTableEntry->CallbackFn = CallBackFunction;
209 InsertTailList (ListHead, &FnTableEntry->Node);
210
211 return EFI_SUCCESS;
212 }
213
214
215
216
217 EFI_STATUS
218 DxeUnRegisterCallBackWorker (
219 IN UINTN TokenNumber,
220 IN CONST GUID *Guid, OPTIONAL
221 IN PCD_PROTOCOL_CALLBACK CallBackFunction
222 )
223 {
224 CALLBACK_FN_ENTRY *FnTableEntry;
225 LIST_ENTRY *ListHead;
226 LIST_ENTRY *ListNode;
227
228 if (Guid != NULL) {
229 TokenNumber = GetExPcdTokenNumber (Guid, (UINT32) TokenNumber);
230 }
231
232 //
233 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
234 // We have to decrement TokenNumber by 1 to make it usable
235 // as the array index.
236 //
237 TokenNumber--;
238
239 ListHead = &mCallbackFnTable[TokenNumber];
240 ListNode = GetFirstNode (ListHead);
241
242 while (ListNode != ListHead) {
243 FnTableEntry = CR_FNENTRY_FROM_LISTNODE(ListNode, CALLBACK_FN_ENTRY, Node);
244
245 if (FnTableEntry->CallbackFn == CallBackFunction) {
246 //
247 // We only allow a Callback function to be register once
248 // for a TokenNumber. So we can safely remove the Node from
249 // the Link List and return EFI_SUCCESS.
250 //
251 RemoveEntryList (ListNode);
252 FreePool (FnTableEntry);
253
254 return EFI_SUCCESS;
255 }
256 ListNode = GetNextNode (ListHead, ListNode);
257 }
258
259 return EFI_INVALID_PARAMETER;
260 }
261
262
263
264 EFI_STATUS
265 ExGetNextTokeNumber (
266 IN CONST EFI_GUID *Guid,
267 IN OUT UINTN *TokenNumber,
268 IN EFI_GUID *GuidTable,
269 IN UINTN SizeOfGuidTable,
270 IN DYNAMICEX_MAPPING *ExMapTable,
271 IN UINTN SizeOfExMapTable
272 )
273 {
274 EFI_GUID *MatchGuid;
275 UINTN Idx;
276 UINTN GuidTableIdx;
277 BOOLEAN Found;
278
279 MatchGuid = ScanGuid (GuidTable, SizeOfGuidTable, Guid);
280 if (MatchGuid == NULL) {
281 return EFI_NOT_FOUND;
282 }
283
284 Found = FALSE;
285 GuidTableIdx = MatchGuid - GuidTable;
286 for (Idx = 0; Idx < SizeOfExMapTable; Idx++) {
287 if (ExMapTable[Idx].ExGuidIndex == GuidTableIdx) {
288 Found = TRUE;
289 break;
290 }
291 }
292
293 if (Found) {
294 if (*TokenNumber == PCD_INVALID_TOKEN_NUMBER) {
295 *TokenNumber = ExMapTable[Idx].ExTokenNumber;
296 return EFI_SUCCESS;
297 }
298
299 for ( ; Idx < SizeOfExMapTable; Idx++) {
300 if (ExMapTable[Idx].ExTokenNumber == *TokenNumber) {
301 Idx++;
302 if (Idx == SizeOfExMapTable) {
303 //
304 // Exceed the length of ExMap Table
305 //
306 *TokenNumber = PCD_INVALID_TOKEN_NUMBER;
307 return EFI_SUCCESS;
308 } else if (ExMapTable[Idx].ExGuidIndex == GuidTableIdx) {
309 //
310 // Found the next match
311 //
312 *TokenNumber = ExMapTable[Idx].ExTokenNumber;
313 return EFI_SUCCESS;
314 } else {
315 //
316 // Guid has been changed. It is the next Token Space Guid.
317 // We should flag no more TokenNumber.
318 //
319 *TokenNumber = PCD_INVALID_TOKEN_NUMBER;
320 return EFI_SUCCESS;
321 }
322 }
323 }
324 }
325
326 return EFI_NOT_FOUND;
327 }
328
329
330
331
332 VOID
333 BuildPcdDxeDataBase (
334 VOID
335 )
336 {
337 PEI_PCD_DATABASE *PeiDatabase;
338 EFI_HOB_GUID_TYPE *GuidHob;
339 UINTN Idx;
340
341 mPcdDatabase = AllocateZeroPool (sizeof(PCD_DATABASE));
342 ASSERT (mPcdDatabase != NULL);
343
344 GuidHob = GetFirstGuidHob (&gPcdDataBaseHobGuid);
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 STATIC
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 // Aquire lock to prevent reentrance from TPL_CALLBACK level
571 //
572 EfiAcquireLock (&mPcdDatabaseLock);
573
574 //
575 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
576 // We have to decrement TokenNumber by 1 to make it usable
577 // as the array index.
578 //
579 TokenNumber--;
580
581 TmpTokenNumber = TokenNumber;
582
583 // EBC compiler is very choosy. It may report warning about comparison
584 // between UINTN and 0 . So we add 1 in each size of the
585 // comparison.
586
587 ASSERT (TokenNumber + 1 < PCD_TOTAL_TOKEN_NUMBER + 1);
588
589 if (!PtrType) {
590 ASSERT (*Size == DxePcdGetSize (TokenNumber + 1));
591 }
592
593 // EBC compiler is very choosy. It may report warning about comparison
594 // between UINTN and 0 . So we add 1 in each size of the
595 // comparison.
596 IsPeiDb = (BOOLEAN) ((TokenNumber + 1 < PEI_LOCAL_TOKEN_NUMBER + 1) ? TRUE : FALSE);
597
598 LocalTokenNumberTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.LocalTokenNumberTable :
599 mPcdDatabase->DxeDb.Init.LocalTokenNumberTable;
600
601 // EBC compiler is very choosy. It may report warning about comparison
602 // between UINTN and 0 . So we add 1 in each size of the
603 // comparison.
604 if ((TokenNumber + 1 < PEI_NEX_TOKEN_NUMBER + 1) ||
605 (TokenNumber + 1 >= PEI_LOCAL_TOKEN_NUMBER + 1 || TokenNumber + 1 < (PEI_LOCAL_TOKEN_NUMBER + DXE_NEX_TOKEN_NUMBER + 1))) {
606 InvokeCallbackOnSet (0, NULL, TokenNumber + 1, Data, *Size);
607 }
608
609 TokenNumber = IsPeiDb ? TokenNumber
610 : TokenNumber - PEI_LOCAL_TOKEN_NUMBER;
611
612 LocalTokenNumber = LocalTokenNumberTable[TokenNumber];
613
614 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == PCD_TYPE_SKU_ENABLED) {
615 if (PtrType) {
616 GetPtrTypeSize (TmpTokenNumber, &MaxSize);
617 } else {
618 MaxSize = *Size;
619 }
620 LocalTokenNumber = GetSkuEnabledTokenNumber (LocalTokenNumber & ~PCD_TYPE_SKU_ENABLED, MaxSize, IsPeiDb);
621 }
622
623 Offset = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK;
624
625 PcdDb = IsPeiDb ? ((UINT8 *) &mPcdDatabase->PeiDb) : ((UINT8 *) &mPcdDatabase->DxeDb);
626
627 StringTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.StringTable :
628 mPcdDatabase->DxeDb.Init.StringTable;
629
630 InternalData = PcdDb + Offset;
631
632 switch (LocalTokenNumber & PCD_TYPE_ALL_SET) {
633 case PCD_TYPE_VPD:
634 ASSERT (FALSE);
635 Status = EFI_INVALID_PARAMETER;
636 break;
637
638 case PCD_TYPE_STRING:
639 if (SetPtrTypeSize (TmpTokenNumber, Size)) {
640 CopyMem (&StringTable[*((UINT16 *)InternalData)], Data, *Size);
641 Status = EFI_SUCCESS;
642 } else {
643 Status = EFI_INVALID_PARAMETER;
644 }
645 break;
646
647 case PCD_TYPE_HII:
648 if (PtrType) {
649 if (!SetPtrTypeSize (TmpTokenNumber, Size)) {
650 Status = EFI_INVALID_PARAMETER;
651 break;
652 }
653 }
654
655 GuidTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.GuidTable :
656 mPcdDatabase->DxeDb.Init.GuidTable;
657
658 VariableHead = (VARIABLE_HEAD *) (PcdDb + Offset);
659
660 Guid = &(GuidTable[VariableHead->GuidTableIndex]);
661 Name = &(StringTable[VariableHead->StringIndex]);
662 VariableOffset = VariableHead->Offset;
663
664 Status = SetHiiVariable (Guid, Name, Data, *Size, VariableOffset);
665
666 if (EFI_NOT_FOUND == Status) {
667 CopyMem (PcdDb + VariableHead->DefaultValueOffset, Data, *Size);
668 Status = EFI_SUCCESS;
669 }
670 break;
671
672 case PCD_TYPE_DATA:
673 if (PtrType) {
674 if (SetPtrTypeSize (TmpTokenNumber, Size)) {
675 CopyMem (InternalData, Data, *Size);
676 Status = EFI_SUCCESS;
677 } else {
678 Status = EFI_INVALID_PARAMETER;
679 }
680 break;
681 }
682
683 Status = EFI_SUCCESS;
684 switch (*Size) {
685 case sizeof(UINT8):
686 *((UINT8 *) InternalData) = *((UINT8 *) Data);
687 break;
688
689 case sizeof(UINT16):
690 *((UINT16 *) InternalData) = *((UINT16 *) Data);
691 break;
692
693 case sizeof(UINT32):
694 *((UINT32 *) InternalData) = *((UINT32 *) Data);
695 break;
696
697 case sizeof(UINT64):
698 *((UINT64 *) InternalData) = *((UINT64 *) Data);
699 break;
700
701 default:
702 ASSERT (FALSE);
703 Status = EFI_NOT_FOUND;
704 break;
705 }
706 break;
707
708 default:
709 ASSERT (FALSE);
710 Status = EFI_NOT_FOUND;
711 break;
712 }
713
714 EfiReleaseLock (&mPcdDatabaseLock);
715
716 return Status;
717 }
718
719
720
721
722
723 VOID *
724 ExGetWorker (
725 IN CONST EFI_GUID *Guid,
726 IN UINTN ExTokenNumber,
727 IN UINTN GetSize
728 )
729 {
730 return GetWorker(GetExPcdTokenNumber (Guid, (UINT32) ExTokenNumber), GetSize);
731 }
732
733
734
735
736 EFI_STATUS
737 ExSetValueWorker (
738 IN UINTN ExTokenNumber,
739 IN CONST EFI_GUID *Guid,
740 IN VOID *Data,
741 IN UINTN SetSize
742 )
743 {
744 return ExSetWorker (ExTokenNumber, Guid, Data, &SetSize, FALSE);
745 }
746
747
748 EFI_STATUS
749 ExSetWorker (
750 IN UINTN ExTokenNumber,
751 IN CONST EFI_GUID *Guid,
752 IN VOID *Data,
753 IN OUT UINTN *SetSize,
754 IN BOOLEAN PtrType
755 )
756 {
757 UINTN TokenNumber;
758
759 TokenNumber = GetExPcdTokenNumber (Guid, (UINT32) ExTokenNumber);
760
761 InvokeCallbackOnSet ((UINT32) ExTokenNumber, Guid, TokenNumber, Data, *SetSize);
762
763 return SetWorker (TokenNumber, Data, SetSize, PtrType);
764
765 }
766
767
768
769
770 EFI_STATUS
771 SetHiiVariable (
772 IN EFI_GUID *VariableGuid,
773 IN UINT16 *VariableName,
774 IN CONST VOID *Data,
775 IN UINTN DataSize,
776 IN UINTN Offset
777 )
778 {
779 UINTN Size;
780 VOID *Buffer;
781 EFI_STATUS Status;
782 UINT32 Attribute;
783
784 Size = 0;
785
786 Status = gRT->GetVariable (
787 (UINT16 *)VariableName,
788 VariableGuid,
789 NULL,
790 &Size,
791 NULL
792 );
793
794 if (Status == EFI_BUFFER_TOO_SMALL) {
795
796 Buffer = AllocatePool (Size);
797
798 ASSERT (Buffer != NULL);
799
800 Status = gRT->GetVariable (
801 VariableName,
802 VariableGuid,
803 &Attribute,
804 &Size,
805 Buffer
806 );
807
808 ASSERT_EFI_ERROR (Status);
809
810 CopyMem ((UINT8 *)Buffer + Offset, Data, DataSize);
811
812 Status = gRT->SetVariable (
813 VariableName,
814 VariableGuid,
815 Attribute,
816 Size,
817 Buffer
818 );
819
820 FreePool (Buffer);
821 return Status;
822
823 }
824
825 //
826 // If we drop to here, we don't have a Variable entry in
827 // the variable service yet. So, we will save the data
828 // in the PCD Database's volatile area.
829 //
830 return Status;
831 }
832
833
834
835
836
837 UINTN
838 GetExPcdTokenNumber (
839 IN CONST EFI_GUID *Guid,
840 IN UINT32 ExTokenNumber
841 )
842 {
843 UINT32 i;
844 DYNAMICEX_MAPPING *ExMap;
845 EFI_GUID *GuidTable;
846 EFI_GUID *MatchGuid;
847 UINTN MatchGuidIdx;
848
849 if (!PEI_DATABASE_EMPTY) {
850 ExMap = mPcdDatabase->PeiDb.Init.ExMapTable;
851 GuidTable = mPcdDatabase->PeiDb.Init.GuidTable;
852
853 MatchGuid = ScanGuid (GuidTable, sizeof(mPcdDatabase->PeiDb.Init.GuidTable), Guid);
854
855 if (MatchGuid != NULL) {
856
857 MatchGuidIdx = MatchGuid - GuidTable;
858
859 for (i = 0; i < PEI_EXMAPPING_TABLE_SIZE; i++) {
860 if ((ExTokenNumber == ExMap[i].ExTokenNumber) &&
861 (MatchGuidIdx == ExMap[i].ExGuidIndex)) {
862 return ExMap[i].LocalTokenNumber;
863
864 }
865 }
866 }
867 }
868
869 ExMap = mPcdDatabase->DxeDb.Init.ExMapTable;
870 GuidTable = mPcdDatabase->DxeDb.Init.GuidTable;
871
872 MatchGuid = ScanGuid (GuidTable, sizeof(mPcdDatabase->DxeDb.Init.GuidTable), Guid);
873 //
874 // We need to ASSERT here. If GUID can't be found in GuidTable, this is a
875 // error in the BUILD system.
876 //
877 ASSERT (MatchGuid != NULL);
878
879 MatchGuidIdx = MatchGuid - GuidTable;
880
881 for (i = 0; i < DXE_EXMAPPING_TABLE_SIZE; i++) {
882 if ((ExTokenNumber == ExMap[i].ExTokenNumber) &&
883 (MatchGuidIdx == ExMap[i].ExGuidIndex)) {
884 return ExMap[i].LocalTokenNumber;
885 }
886 }
887
888 ASSERT (FALSE);
889
890 return 0;
891 }
892
893
894 STATIC
895 SKU_ID *
896 GetSkuIdArray (
897 IN UINTN LocalTokenNumberTableIdx,
898 IN BOOLEAN IsPeiPcd
899 )
900 {
901 SKU_HEAD *SkuHead;
902 UINTN LocalTokenNumber;
903 UINT8 *Database;
904
905 if (IsPeiPcd) {
906 LocalTokenNumber = mPcdDatabase->PeiDb.Init.LocalTokenNumberTable[LocalTokenNumberTableIdx];
907 Database = (UINT8 *) &mPcdDatabase->PeiDb;
908 } else {
909 LocalTokenNumber = mPcdDatabase->DxeDb.Init.LocalTokenNumberTable[LocalTokenNumberTableIdx - PEI_LOCAL_TOKEN_NUMBER];
910 Database = (UINT8 *) &mPcdDatabase->DxeDb;
911 }
912
913 ASSERT ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) != 0);
914
915 SkuHead = (SKU_HEAD *) ((UINT8 *)Database + (LocalTokenNumber & PCD_DATABASE_OFFSET_MASK));
916
917 return (SKU_ID *) (Database + SkuHead->SkuIdTableOffset);
918
919 }
920
921
922 STATIC
923 UINTN
924 GetSizeTableIndexA (
925 IN UINTN LocalTokenNumberTableIdx,
926 IN UINT32 *LocalTokenNumberTable,
927 IN BOOLEAN IsPeiDb
928 )
929 {
930 UINTN i;
931 UINTN SizeTableIdx;
932 UINTN LocalTokenNumber;
933 SKU_ID *SkuIdTable;
934
935 SizeTableIdx = 0;
936
937 for (i=0; i<LocalTokenNumberTableIdx; i++) {
938 LocalTokenNumber = LocalTokenNumberTable[i];
939
940 if ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER) {
941 //
942 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type
943 // PCD entry.
944 //
945 if (LocalTokenNumber & PCD_TYPE_VPD) {
946 //
947 // We have only one entry for VPD enabled PCD entry:
948 // 1) MAX Size.
949 // We consider current size is equal to MAX size.
950 //
951 SizeTableIdx++;
952 } else {
953 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0) {
954 //
955 // We have only two entry for Non-Sku enabled PCD entry:
956 // 1) MAX SIZE
957 // 2) Current Size
958 //
959 SizeTableIdx += 2;
960 } else {
961 //
962 // We have these entry for SKU enabled PCD entry
963 // 1) MAX SIZE
964 // 2) Current Size for each SKU_ID (It is equal to MaxSku).
965 //
966 SkuIdTable = GetSkuIdArray (i, IsPeiDb);
967 SizeTableIdx += (UINTN)*SkuIdTable + 1;
968 }
969 }
970 }
971
972 }
973
974 return SizeTableIdx;
975 }
976
977
978
979 STATIC
980 UINTN
981 GetSizeTableIndex (
982 IN UINTN LocalTokenNumberTableIdx,
983 IN BOOLEAN IsPeiDb
984 )
985 {
986 UINT32 *LocalTokenNumberTable;
987
988 if (IsPeiDb) {
989 LocalTokenNumberTable = mPcdDatabase->PeiDb.Init.LocalTokenNumberTable;
990 } else {
991 LocalTokenNumberTable = mPcdDatabase->DxeDb.Init.LocalTokenNumberTable;
992 }
993 return GetSizeTableIndexA (LocalTokenNumberTableIdx,
994 LocalTokenNumberTable,
995 IsPeiDb);
996 }
997
998
999
1000 UINTN
1001 GetPtrTypeSize (
1002 IN UINTN LocalTokenNumberTableIdx,
1003 OUT UINTN *MaxSize
1004 )
1005 {
1006 INTN SizeTableIdx;
1007 UINTN LocalTokenNumber;
1008 SKU_ID *SkuIdTable;
1009 SIZE_INFO *SizeTable;
1010 UINTN i;
1011 BOOLEAN IsPeiDb;
1012 UINT32 *LocalTokenNumberTable;
1013
1014 // EBC compiler is very choosy. It may report warning about comparison
1015 // between UINTN and 0 . So we add 1 in each size of the
1016 // comparison.
1017 IsPeiDb = (BOOLEAN) (LocalTokenNumberTableIdx + 1 < PEI_LOCAL_TOKEN_NUMBER + 1);
1018
1019
1020 if (IsPeiDb) {
1021 LocalTokenNumberTable = mPcdDatabase->PeiDb.Init.LocalTokenNumberTable;
1022 SizeTable = mPcdDatabase->PeiDb.Init.SizeTable;
1023 } else {
1024 LocalTokenNumberTableIdx -= PEI_LOCAL_TOKEN_NUMBER;
1025 LocalTokenNumberTable = mPcdDatabase->DxeDb.Init.LocalTokenNumberTable;
1026 SizeTable = mPcdDatabase->DxeDb.Init.SizeTable;
1027 }
1028
1029 LocalTokenNumber = LocalTokenNumberTable[LocalTokenNumberTableIdx];
1030
1031 ASSERT ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER);
1032
1033 SizeTableIdx = GetSizeTableIndex (LocalTokenNumberTableIdx, IsPeiDb);
1034
1035 *MaxSize = SizeTable[SizeTableIdx];
1036 //
1037 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type
1038 // PCD entry.
1039 //
1040 if (LocalTokenNumber & PCD_TYPE_VPD) {
1041 //
1042 // We have only one entry for VPD enabled PCD entry:
1043 // 1) MAX Size.
1044 // We consider current size is equal to MAX size.
1045 //
1046 return *MaxSize;
1047 } else {
1048 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0) {
1049 //
1050 // We have only two entry for Non-Sku enabled PCD entry:
1051 // 1) MAX SIZE
1052 // 2) Current Size
1053 //
1054 return SizeTable[SizeTableIdx + 1];
1055 } else {
1056 //
1057 // We have these entry for SKU enabled PCD entry
1058 // 1) MAX SIZE
1059 // 2) Current Size for each SKU_ID (It is equal to MaxSku).
1060 //
1061 SkuIdTable = GetSkuIdArray (LocalTokenNumberTableIdx, IsPeiDb);
1062 for (i = 0; i < SkuIdTable[0]; i++) {
1063 if (SkuIdTable[1 + i] == mPcdDatabase->PeiDb.Init.SystemSkuId) {
1064 return SizeTable[SizeTableIdx + 1 + i];
1065 }
1066 }
1067 return SizeTable[SizeTableIdx + 1];
1068 }
1069 }
1070 }
1071
1072
1073
1074 BOOLEAN
1075 SetPtrTypeSize (
1076 IN UINTN LocalTokenNumberTableIdx,
1077 IN OUT UINTN *CurrentSize
1078 )
1079 {
1080 INTN SizeTableIdx;
1081 UINTN LocalTokenNumber;
1082 SKU_ID *SkuIdTable;
1083 SIZE_INFO *SizeTable;
1084 UINTN i;
1085 UINTN MaxSize;
1086 BOOLEAN IsPeiDb;
1087 UINT32 *LocalTokenNumberTable;
1088
1089 // EBC compiler is very choosy. It may report warning about comparison
1090 // between UINTN and 0 . So we add 1 in each size of the
1091 // comparison.
1092 IsPeiDb = (BOOLEAN) (LocalTokenNumberTableIdx + 1 < PEI_LOCAL_TOKEN_NUMBER + 1);
1093
1094 if (IsPeiDb) {
1095 LocalTokenNumberTable = mPcdDatabase->PeiDb.Init.LocalTokenNumberTable;
1096 SizeTable = mPcdDatabase->PeiDb.Init.SizeTable;
1097 } else {
1098 LocalTokenNumberTableIdx -= PEI_LOCAL_TOKEN_NUMBER;
1099 LocalTokenNumberTable = mPcdDatabase->DxeDb.Init.LocalTokenNumberTable;
1100 SizeTable = mPcdDatabase->DxeDb.Init.SizeTable;
1101 }
1102
1103 LocalTokenNumber = LocalTokenNumberTable[LocalTokenNumberTableIdx];
1104
1105 ASSERT ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER);
1106
1107 SizeTableIdx = GetSizeTableIndex (LocalTokenNumberTableIdx, IsPeiDb);
1108
1109 MaxSize = SizeTable[SizeTableIdx];
1110 //
1111 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type
1112 // PCD entry.
1113 //
1114 if (LocalTokenNumber & PCD_TYPE_VPD) {
1115 //
1116 // We shouldn't come here as we don't support SET for VPD
1117 //
1118 ASSERT (FALSE);
1119 return FALSE;
1120 } else {
1121 if ((*CurrentSize > MaxSize) ||
1122 (*CurrentSize == MAX_ADDRESS)) {
1123 *CurrentSize = MaxSize;
1124 return FALSE;
1125 }
1126
1127 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0) {
1128 //
1129 // We have only two entry for Non-Sku enabled PCD entry:
1130 // 1) MAX SIZE
1131 // 2) Current Size
1132 //
1133 SizeTable[SizeTableIdx + 1] = (SIZE_INFO) *CurrentSize;
1134 return TRUE;
1135 } else {
1136 //
1137 // We have these entry for SKU enabled PCD entry
1138 // 1) MAX SIZE
1139 // 2) Current Size for each SKU_ID (It is equal to MaxSku).
1140 //
1141 SkuIdTable = GetSkuIdArray (LocalTokenNumberTableIdx, IsPeiDb);
1142 for (i = 0; i < SkuIdTable[0]; i++) {
1143 if (SkuIdTable[1 + i] == mPcdDatabase->PeiDb.Init.SystemSkuId) {
1144 SizeTable[SizeTableIdx + 1 + i] = (SIZE_INFO) *CurrentSize;
1145 return TRUE;
1146 }
1147 }
1148 SizeTable[SizeTableIdx + 1] = (SIZE_INFO) *CurrentSize;
1149 return TRUE;
1150 }
1151 }
1152 }
1153