]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/PCD/Dxe/Service.c
c6ad6ab9f43bb77ea4d6a0170d73d65c3b592568
[mirror_edk2.git] / MdeModulePkg / Universal / PCD / Dxe / Service.c
1 /** @file
2 Help 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
15 #include "Service.h"
16
17 PCD_DATABASE * mPcdDatabase;
18
19 LIST_ENTRY *mCallbackFnTable;
20
21 /**
22 Get the PCD entry pointer in PCD database.
23
24 This routine will visit PCD database to find the PCD entry according to given
25 token number. The given token number is autogened by build tools and it will be
26 translated to local token number. Local token number contains PCD's type and
27 offset of PCD entry in PCD database.
28
29 @param TokenNumber Token's number, it is autogened by build tools
30 @param GetSize The size of token's value
31
32 @return PCD entry pointer in PCD database
33
34 **/
35 VOID *
36 GetWorker (
37 IN UINTN TokenNumber,
38 IN UINTN GetSize
39 )
40 {
41 UINT32 *LocalTokenNumberTable;
42 EFI_GUID *GuidTable;
43 UINT16 *StringTable;
44 EFI_GUID *Guid;
45 UINT16 *Name;
46 VARIABLE_HEAD *VariableHead;
47 UINT8 *VaraiableDefaultBuffer;
48 UINT8 *Data;
49 VPD_HEAD *VpdHead;
50 UINT8 *PcdDb;
51 VOID *RetPtr;
52 UINTN MaxSize;
53 UINTN TmpTokenNumber;
54 UINTN DataSize;
55 EFI_STATUS Status;
56 UINT32 LocalTokenNumber;
57 UINT32 Offset;
58 UINT16 StringTableIdx;
59 BOOLEAN IsPeiDb;
60
61 //
62 // Aquire lock to prevent reentrance from TPL_CALLBACK level
63 //
64 EfiAcquireLock (&mPcdDatabaseLock);
65
66 RetPtr = NULL;
67 //
68 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
69 // We have to decrement TokenNumber by 1 to make it usable
70 // as the array index.
71 //
72 TokenNumber--;
73
74 TmpTokenNumber = TokenNumber;
75
76 //
77 // PCD_TOTAL_TOKEN_NUMBER is a auto-generated constant.
78 // It could be zero. EBC compiler is very choosy. It may
79 // report warning. So we add 1 in each size of the
80 // comparison.
81 //
82 ASSERT (TokenNumber + 1 < PCD_TOTAL_TOKEN_NUMBER + 1);
83
84 ASSERT ((GetSize == DxePcdGetSize (TokenNumber + 1)) || (GetSize == 0));
85
86 // EBC compiler is very choosy. It may report warning about comparison
87 // between UINTN and 0 . So we add 1 in each size of the
88 // comparison.
89 IsPeiDb = (BOOLEAN) ((TokenNumber + 1 < PEI_LOCAL_TOKEN_NUMBER + 1) ? TRUE : FALSE);
90
91 LocalTokenNumberTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.LocalTokenNumberTable :
92 mPcdDatabase->DxeDb.Init.LocalTokenNumberTable;
93
94 TokenNumber = IsPeiDb ? TokenNumber :
95 TokenNumber - PEI_LOCAL_TOKEN_NUMBER;
96
97 LocalTokenNumber = LocalTokenNumberTable[TokenNumber];
98
99 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == PCD_TYPE_SKU_ENABLED) {
100 if (GetSize == 0) {
101 GetPtrTypeSize (TmpTokenNumber, &MaxSize);
102 } else {
103 MaxSize = GetSize;
104 }
105 LocalTokenNumber = GetSkuEnabledTokenNumber (LocalTokenNumber & ~PCD_TYPE_SKU_ENABLED, MaxSize, IsPeiDb);
106 }
107
108 PcdDb = IsPeiDb ? ((UINT8 *) &mPcdDatabase->PeiDb) : ((UINT8 *) &mPcdDatabase->DxeDb);
109 StringTable = (UINT16 *) (IsPeiDb ? mPcdDatabase->PeiDb.Init.StringTable :
110 mPcdDatabase->DxeDb.Init.StringTable);
111
112 Offset = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK;
113
114 switch (LocalTokenNumber & PCD_TYPE_ALL_SET) {
115 case PCD_TYPE_VPD:
116 VpdHead = (VPD_HEAD *) ((UINT8 *) PcdDb + Offset);
117 RetPtr = (VOID *) (UINTN) (FixedPcdGet32(PcdVpdBaseAddress) + VpdHead->Offset);
118 break;
119
120 case PCD_TYPE_HII:
121 GuidTable = (EFI_GUID *) (IsPeiDb ? mPcdDatabase->PeiDb.Init.GuidTable :
122 mPcdDatabase->DxeDb.Init.GuidTable);
123
124 VariableHead = (VARIABLE_HEAD *) (PcdDb + Offset);
125
126 Guid = GuidTable + VariableHead->GuidTableIndex;
127 Name = StringTable + VariableHead->StringIndex;
128 VaraiableDefaultBuffer = (UINT8 *) PcdDb + VariableHead->DefaultValueOffset;
129
130 Status = GetHiiVariable (Guid, Name, &Data, &DataSize);
131 if (Status == EFI_SUCCESS) {
132 if (GetSize == 0) {
133 //
134 // It is a pointer type. So get the MaxSize reserved for
135 // this PCD entry.
136 //
137 GetPtrTypeSize (TmpTokenNumber, &GetSize);
138 }
139 CopyMem (VaraiableDefaultBuffer, Data + VariableHead->Offset, GetSize);
140 FreePool (Data);
141 }
142 //
143 // If the operation is successful, we copy the data
144 // to the default value buffer in the PCD Database.
145 // So that we can free the Data allocated in GetHiiVariable.
146 //
147 //
148 // If the operation is not successful,
149 // Return 1) either the default value specified by Platform Integrator
150 // 2) Or the value Set by a PCD set operation.
151 //
152 RetPtr = (VOID *) VaraiableDefaultBuffer;
153 break;
154
155 case PCD_TYPE_STRING:
156 StringTableIdx = (UINT16) *((UINT8 *) PcdDb + Offset);
157 RetPtr = (VOID *) (StringTable + StringTableIdx);
158 break;
159
160 case PCD_TYPE_DATA:
161 RetPtr = (VOID *) ((UINT8 *) PcdDb + Offset);
162 break;
163
164 default:
165 ASSERT (FALSE);
166 break;
167
168 }
169
170 EfiReleaseLock (&mPcdDatabaseLock);
171
172 return RetPtr;
173
174 }
175
176 /**
177 Register the callback function for a PCD entry.
178
179 This routine will register a callback function to a PCD entry by given token number
180 and token space guid.
181
182 @param TokenNumber PCD token's number, it is autogened by build tools.
183 @param Guid PCD token space's guid,
184 if not NULL, this PCD is dynamicEx type PCD.
185 @param CallBackFunction Callback function pointer
186
187 @return EFI_SUCCESS Always success for registering callback function.
188
189 **/
190 EFI_STATUS
191 DxeRegisterCallBackWorker (
192 IN UINTN TokenNumber,
193 IN CONST EFI_GUID *Guid, OPTIONAL
194 IN PCD_PROTOCOL_CALLBACK CallBackFunction
195 )
196 {
197 CALLBACK_FN_ENTRY *FnTableEntry;
198 LIST_ENTRY *ListHead;
199 LIST_ENTRY *ListNode;
200
201 if (Guid != NULL) {
202 TokenNumber = GetExPcdTokenNumber (Guid, (UINT32) TokenNumber);
203 }
204
205 //
206 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
207 // We have to decrement TokenNumber by 1 to make it usable
208 // as the array index.
209 //
210 TokenNumber--;
211
212 ListHead = &mCallbackFnTable[TokenNumber];
213 ListNode = GetFirstNode (ListHead);
214
215 while (ListNode != ListHead) {
216 FnTableEntry = CR_FNENTRY_FROM_LISTNODE(ListNode, CALLBACK_FN_ENTRY, Node);
217
218 if (FnTableEntry->CallbackFn == CallBackFunction) {
219 //
220 // We only allow a Callback function to be register once
221 // for a TokenNumber. So just return EFI_SUCCESS
222 //
223 return EFI_SUCCESS;
224 }
225 ListNode = GetNextNode (ListHead, ListNode);
226 }
227
228 FnTableEntry = AllocatePool (sizeof(CALLBACK_FN_ENTRY));
229 ASSERT (FnTableEntry != NULL);
230
231 FnTableEntry->CallbackFn = CallBackFunction;
232 InsertTailList (ListHead, &FnTableEntry->Node);
233
234 return EFI_SUCCESS;
235 }
236
237 /**
238 UnRegister the callback function for a PCD entry.
239
240 This routine will unregister a callback function to a PCD entry by given token number
241 and token space guid.
242
243 @param TokenNumber PCD token's number, it is autogened by build tools.
244 @param Guid PCD token space's guid.
245 if not NULL, this PCD is dynamicEx type PCD.
246 @param CallBackFunction Callback function pointer
247
248 @retval EFI_SUCCESS Callback function is success to be unregister.
249 @retval EFI_INVALID_PARAMETER Can not find the PCD entry by given token number.
250 **/
251 EFI_STATUS
252 DxeUnRegisterCallBackWorker (
253 IN UINTN TokenNumber,
254 IN CONST EFI_GUID *Guid, OPTIONAL
255 IN PCD_PROTOCOL_CALLBACK CallBackFunction
256 )
257 {
258 CALLBACK_FN_ENTRY *FnTableEntry;
259 LIST_ENTRY *ListHead;
260 LIST_ENTRY *ListNode;
261
262 if (Guid != NULL) {
263 TokenNumber = GetExPcdTokenNumber (Guid, (UINT32) TokenNumber);
264 }
265
266 //
267 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
268 // We have to decrement TokenNumber by 1 to make it usable
269 // as the array index.
270 //
271 TokenNumber--;
272
273 ListHead = &mCallbackFnTable[TokenNumber];
274 ListNode = GetFirstNode (ListHead);
275
276 while (ListNode != ListHead) {
277 FnTableEntry = CR_FNENTRY_FROM_LISTNODE(ListNode, CALLBACK_FN_ENTRY, Node);
278
279 if (FnTableEntry->CallbackFn == CallBackFunction) {
280 //
281 // We only allow a Callback function to be register once
282 // for a TokenNumber. So we can safely remove the Node from
283 // the Link List and return EFI_SUCCESS.
284 //
285 RemoveEntryList (ListNode);
286 FreePool (FnTableEntry);
287
288 return EFI_SUCCESS;
289 }
290 ListNode = GetNextNode (ListHead, ListNode);
291 }
292
293 return EFI_INVALID_PARAMETER;
294 }
295
296 /**
297 Get next token number in given token space.
298
299 This routine is used for dynamicEx type PCD. It will firstly scan token space
300 table to get token space according to given token space guid. Then scan given
301 token number in found token space, if found, then return next token number in
302 this token space.
303
304 @param Guid Token space guid. Next token number will be scaned in
305 this token space.
306 @param TokenNumber Token number.
307 If PCD_INVALID_TOKEN_NUMBER, return first token number in
308 token space table.
309 If not PCD_INVALID_TOKEN_NUMBER, return next token number
310 in token space table.
311 @param GuidTable Token space guid table. It will be used for scan token space
312 by given token space guid.
313 @param SizeOfGuidTable The size of guid table.
314 @param ExMapTable DynamicEx token number mapping table.
315 @param SizeOfExMapTable The size of dynamicEx token number mapping table.
316
317 @retval EFI_NOT_FOUND Can not given token space or token number.
318 @retval EFI_SUCCESS Success to get next token number.
319
320 **/
321 EFI_STATUS
322 ExGetNextTokeNumber (
323 IN CONST EFI_GUID *Guid,
324 IN OUT UINTN *TokenNumber,
325 IN EFI_GUID *GuidTable,
326 IN UINTN SizeOfGuidTable,
327 IN DYNAMICEX_MAPPING *ExMapTable,
328 IN UINTN SizeOfExMapTable
329 )
330 {
331 EFI_GUID *MatchGuid;
332 UINTN Index;
333 UINTN GuidTableIdx;
334 BOOLEAN Found;
335
336 //
337 // Scan token space guid
338 //
339 MatchGuid = ScanGuid (GuidTable, SizeOfGuidTable, Guid);
340 if (MatchGuid == NULL) {
341 return EFI_NOT_FOUND;
342 }
343
344 //
345 // Find the token space table in dynamicEx mapping table.
346 //
347 Found = FALSE;
348 GuidTableIdx = MatchGuid - GuidTable;
349 for (Index = 0; Index < SizeOfExMapTable; Index++) {
350 if (ExMapTable[Index].ExGuidIndex == GuidTableIdx) {
351 Found = TRUE;
352 break;
353 }
354 }
355
356 if (Found) {
357 //
358 // If given token number is PCD_INVALID_TOKEN_NUMBER, then return the first
359 // token number in found token space.
360 //
361 if (*TokenNumber == PCD_INVALID_TOKEN_NUMBER) {
362 *TokenNumber = ExMapTable[Index].ExTokenNumber;
363 return EFI_SUCCESS;
364 }
365
366 for ( ; Index < SizeOfExMapTable; Index++) {
367 if (ExMapTable[Index].ExTokenNumber == *TokenNumber) {
368 Index ++;
369 if (Index == SizeOfExMapTable) {
370 //
371 // Exceed the length of ExMap Table
372 //
373 *TokenNumber = PCD_INVALID_TOKEN_NUMBER;
374 return EFI_SUCCESS;
375 } else if (ExMapTable[Index].ExGuidIndex == GuidTableIdx) {
376 //
377 // Found the next match
378 //
379 *TokenNumber = ExMapTable[Index].ExTokenNumber;
380 return EFI_SUCCESS;
381 } else {
382 //
383 // Guid has been changed. It is the next Token Space Guid.
384 // We should flag no more TokenNumber.
385 //
386 *TokenNumber = PCD_INVALID_TOKEN_NUMBER;
387 return EFI_SUCCESS;
388 }
389 }
390 }
391 }
392
393 return EFI_NOT_FOUND;
394 }
395
396
397 /**
398 Initialize the PCD database in DXE phase.
399
400 PCD database in DXE phase also contains PCD database in PEI phase which is copied
401 from GUID Hob.
402
403 **/
404 VOID
405 BuildPcdDxeDataBase (
406 VOID
407 )
408 {
409 PEI_PCD_DATABASE *PeiDatabase;
410 EFI_HOB_GUID_TYPE *GuidHob;
411 UINTN Index;
412
413 mPcdDatabase = AllocateZeroPool (sizeof(PCD_DATABASE));
414 ASSERT (mPcdDatabase != NULL);
415
416 GuidHob = GetFirstGuidHob (&gPcdDataBaseHobGuid);
417 if (GuidHob != NULL) {
418
419 //
420 // We will copy over the PEI phase's PCD Database.
421 //
422 // If no PEIMs use dynamic Pcd Entry, the Pcd Service PEIM
423 // should not be included at all. So the GuidHob could
424 // be NULL. If it is NULL, we just copy over the DXE Default
425 // Value to PCD Database.
426 //
427
428 PeiDatabase = (PEI_PCD_DATABASE *) GET_GUID_HOB_DATA (GuidHob);
429 //
430 // Copy PCD Entries refereneced in PEI phase to PCD DATABASE
431 //
432 CopyMem (&mPcdDatabase->PeiDb, PeiDatabase, sizeof (PEI_PCD_DATABASE));
433 }
434
435 //
436 // Copy PCD Entries with default value to PCD DATABASE
437 //
438 CopyMem (&mPcdDatabase->DxeDb.Init, &gDXEPcdDbInit, sizeof(DXE_PCD_DATABASE_INIT));
439
440
441 //
442 // Initialized the Callback Function Table
443 //
444
445 mCallbackFnTable = AllocateZeroPool (PCD_TOTAL_TOKEN_NUMBER * sizeof (LIST_ENTRY));
446 ASSERT(mCallbackFnTable != NULL);
447
448 // EBC compiler is very choosy. It may report warning about comparison
449 // between UINTN and 0 . So we add 1 in each size of the
450 // comparison.
451 for (Index = 0; Index + 1 < PCD_TOTAL_TOKEN_NUMBER + 1; Index++) {
452 InitializeListHead (&mCallbackFnTable[Index]);
453 }
454 }
455
456 /**
457 Get Variable which contains HII type PCD entry.
458
459 @param VariableGuid Variable's guid
460 @param VariableName Variable's unicode name string
461 @param VariableData Variable's data pointer,
462 @param VariableSize Variable's size.
463
464 @return the status of gRT->GetVariable
465 **/
466 EFI_STATUS
467 GetHiiVariable (
468 IN EFI_GUID *VariableGuid,
469 IN UINT16 *VariableName,
470 OUT UINT8 **VariableData,
471 OUT UINTN *VariableSize
472 )
473 {
474 UINTN Size;
475 EFI_STATUS Status;
476 UINT8 *Buffer;
477
478 Size = 0;
479 Buffer = NULL;
480
481 //
482 // Firstly get the real size of HII variable
483 //
484 Status = gRT->GetVariable (
485 (UINT16 *)VariableName,
486 VariableGuid,
487 NULL,
488 &Size,
489 Buffer
490 );
491
492 //
493 // Allocate buffer to hold whole variable data according to variable size.
494 //
495 if (Status == EFI_BUFFER_TOO_SMALL) {
496 Buffer = (UINT8 *) AllocatePool (Size);
497
498 ASSERT (Buffer != NULL);
499
500 Status = gRT->GetVariable (
501 VariableName,
502 VariableGuid,
503 NULL,
504 &Size,
505 Buffer
506 );
507
508 ASSERT (Status == EFI_SUCCESS);
509 *VariableData = Buffer;
510 *VariableSize = Size;
511 }
512
513 return Status;
514 }
515
516 /**
517 Find the local token number according to system SKU ID.
518
519 @param LocalTokenNumber PCD token number
520 @param Size The size of PCD entry.
521 @param IsPeiDb If TRUE, the PCD entry is initialized in PEI phase.
522 If False, the PCD entry is initialized in DXE phase.
523
524 @return Token number according to system SKU ID.
525
526 **/
527 UINT32
528 GetSkuEnabledTokenNumber (
529 UINT32 LocalTokenNumber,
530 UINTN Size,
531 BOOLEAN IsPeiDb
532 )
533 {
534 SKU_HEAD *SkuHead;
535 SKU_ID *SkuIdTable;
536 INTN Index;
537 UINT8 *Value;
538 SKU_ID *PhaseSkuIdTable;
539 UINT8 *PcdDb;
540
541 ASSERT ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0);
542
543 PcdDb = IsPeiDb ? (UINT8 *) &mPcdDatabase->PeiDb : (UINT8 *) &mPcdDatabase->DxeDb;
544
545 SkuHead = (SKU_HEAD *) (PcdDb + (LocalTokenNumber & PCD_DATABASE_OFFSET_MASK));
546 Value = (UINT8 *) (PcdDb + SkuHead->SkuDataStartOffset);
547
548 PhaseSkuIdTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.SkuIdTable :
549 mPcdDatabase->DxeDb.Init.SkuIdTable;
550
551 SkuIdTable = &PhaseSkuIdTable[SkuHead->SkuIdTableOffset];
552
553 //
554 // Find the current system's SKU ID entry in SKU ID table.
555 //
556 for (Index = 0; Index < SkuIdTable[0]; Index++) {
557 if (mPcdDatabase->PeiDb.Init.SystemSkuId == SkuIdTable[Index + 1]) {
558 break;
559 }
560 }
561 ASSERT (Index < SkuIdTable[0]);
562
563 switch (LocalTokenNumber & PCD_TYPE_ALL_SET) {
564 case PCD_TYPE_VPD:
565 Value = (UINT8 *) &(((VPD_HEAD *) Value)[Index]);
566 return (UINT32) ((Value - PcdDb) | PCD_TYPE_VPD);
567
568 case PCD_TYPE_HII:
569 Value = (UINT8 *) &(((VARIABLE_HEAD *) Value)[Index]);
570 return (UINT32) ((Value - PcdDb) | PCD_TYPE_HII);
571
572 case PCD_TYPE_STRING:
573 Value = (UINT8 *) &(((STRING_HEAD *) Value)[Index]);
574 return (UINT32) ((Value - PcdDb) | PCD_TYPE_STRING);
575
576 case PCD_TYPE_DATA:
577 Value += Size * Index;
578 return (UINT32) (Value - PcdDb);
579
580 default:
581 ASSERT (FALSE);
582 }
583
584 ASSERT (FALSE);
585
586 return 0;
587
588 }
589
590 /**
591 Invoke the callback function when dynamic PCD entry was set, if this PCD entry
592 has registered callback function.
593
594 @param ExTokenNumber DynamicEx PCD's token number, if this PCD entry is dyanmicEx
595 type PCD.
596 @param Guid DynamicEx PCD's guid, if this PCD entry is dynamicEx type
597 PCD.
598 @param TokenNumber PCD token number generated by build tools.
599 @param Data Value want to be set for this PCD entry
600 @param Size The size of value
601
602 **/
603 VOID
604 InvokeCallbackOnSet (
605 UINT32 ExTokenNumber,
606 CONST EFI_GUID *Guid, OPTIONAL
607 UINTN TokenNumber,
608 VOID *Data,
609 UINTN Size
610 )
611 {
612 CALLBACK_FN_ENTRY *FnTableEntry;
613 LIST_ENTRY *ListHead;
614 LIST_ENTRY *ListNode;
615
616 //
617 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
618 // We have to decrement TokenNumber by 1 to make it usable
619 // as the array index.
620 //
621 TokenNumber--;
622
623 ListHead = &mCallbackFnTable[TokenNumber];
624 ListNode = GetFirstNode (ListHead);
625
626 while (ListNode != ListHead) {
627 FnTableEntry = CR_FNENTRY_FROM_LISTNODE(ListNode, CALLBACK_FN_ENTRY, Node);
628
629 FnTableEntry->CallbackFn(Guid,
630 (Guid == NULL) ? TokenNumber : ExTokenNumber,
631 Data,
632 Size);
633
634 ListNode = GetNextNode (ListHead, ListNode);
635 }
636
637 return;
638 }
639
640
641 /**
642 Wrapper function for setting non-pointer type value for a PCD entry.
643
644 @param TokenNumber Pcd token number autogenerated by build tools.
645 @param Data Value want to be set for PCD entry
646 @param Size Size of value.
647
648 @return status of SetWorker.
649
650 **/
651 EFI_STATUS
652 SetValueWorker (
653 IN UINTN TokenNumber,
654 IN VOID *Data,
655 IN UINTN Size
656 )
657 {
658 return SetWorker (TokenNumber, Data, &Size, FALSE);
659 }
660
661
662 /**
663 Set value for an PCD entry
664
665 @param TokenNumber Pcd token number autogenerated by build tools.
666 @param Data Value want to be set for PCD entry
667 @param Size Size of value.
668 @param PtrType If TRUE, the type of PCD entry's value is Pointer.
669 If False, the type of PCD entry's value is not Pointer.
670
671 @retval EFI_INVALID_PARAMETER If this PCD type is VPD, VPD PCD can not be set.
672 @retval EFI_INVALID_PARAMETER If Size can not be set to size table.
673 @retval EFI_NOT_FOUND If value type of PCD entry is intergrate, but not in
674 range of UINT8, UINT16, UINT32, UINT64
675 @retval EFI_NOT_FOUND Can not find the PCD type according to token number.
676 **/
677 EFI_STATUS
678 SetWorker (
679 IN UINTN TokenNumber,
680 IN VOID *Data,
681 IN OUT UINTN *Size,
682 IN BOOLEAN PtrType
683 )
684 {
685 UINT32 *LocalTokenNumberTable;
686 BOOLEAN IsPeiDb;
687 UINT32 LocalTokenNumber;
688 EFI_GUID *GuidTable;
689 UINT16 *StringTable;
690 EFI_GUID *Guid;
691 UINT16 *Name;
692 UINTN VariableOffset;
693 VOID *InternalData;
694 VARIABLE_HEAD *VariableHead;
695 UINTN Offset;
696 UINT8 *PcdDb;
697 EFI_STATUS Status;
698 UINTN MaxSize;
699 UINTN TmpTokenNumber;
700
701 //
702 // Aquire lock to prevent reentrance from TPL_CALLBACK level
703 //
704 EfiAcquireLock (&mPcdDatabaseLock);
705
706 //
707 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
708 // We have to decrement TokenNumber by 1 to make it usable
709 // as the array index.
710 //
711 TokenNumber--;
712
713 TmpTokenNumber = TokenNumber;
714
715 //
716 // EBC compiler is very choosy. It may report warning about comparison
717 // between UINTN and 0 . So we add 1 in each size of the
718 // comparison.
719 //
720 ASSERT (TokenNumber + 1 < PCD_TOTAL_TOKEN_NUMBER + 1);
721
722 if (!PtrType) {
723 ASSERT (*Size == DxePcdGetSize (TokenNumber + 1));
724 }
725
726 //
727 // EBC compiler is very choosy. It may report warning about comparison
728 // between UINTN and 0 . So we add 1 in each size of the
729 // comparison.
730 //
731 IsPeiDb = (BOOLEAN) ((TokenNumber + 1 < PEI_LOCAL_TOKEN_NUMBER + 1) ? TRUE : FALSE);
732
733 LocalTokenNumberTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.LocalTokenNumberTable :
734 mPcdDatabase->DxeDb.Init.LocalTokenNumberTable;
735
736 //
737 // EBC compiler is very choosy. It may report warning about comparison
738 // between UINTN and 0 . So we add 1 in each size of the
739 // comparison.
740 //
741 if ((TokenNumber + 1 < PEI_NEX_TOKEN_NUMBER + 1) ||
742 (TokenNumber + 1 >= PEI_LOCAL_TOKEN_NUMBER + 1 || TokenNumber + 1 < (PEI_LOCAL_TOKEN_NUMBER + DXE_NEX_TOKEN_NUMBER + 1))) {
743 InvokeCallbackOnSet (0, NULL, TokenNumber + 1, Data, *Size);
744 }
745
746 TokenNumber = IsPeiDb ? TokenNumber
747 : TokenNumber - PEI_LOCAL_TOKEN_NUMBER;
748
749 LocalTokenNumber = LocalTokenNumberTable[TokenNumber];
750
751 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == PCD_TYPE_SKU_ENABLED) {
752 if (PtrType) {
753 GetPtrTypeSize (TmpTokenNumber, &MaxSize);
754 } else {
755 MaxSize = *Size;
756 }
757 LocalTokenNumber = GetSkuEnabledTokenNumber (LocalTokenNumber & ~PCD_TYPE_SKU_ENABLED, MaxSize, IsPeiDb);
758 }
759
760 Offset = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK;
761
762 PcdDb = IsPeiDb ? ((UINT8 *) &mPcdDatabase->PeiDb) : ((UINT8 *) &mPcdDatabase->DxeDb);
763
764 StringTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.StringTable :
765 mPcdDatabase->DxeDb.Init.StringTable;
766
767 InternalData = PcdDb + Offset;
768
769 switch (LocalTokenNumber & PCD_TYPE_ALL_SET) {
770 case PCD_TYPE_VPD:
771 ASSERT (FALSE);
772 Status = EFI_INVALID_PARAMETER;
773 break;
774
775 case PCD_TYPE_STRING:
776 if (SetPtrTypeSize (TmpTokenNumber, Size)) {
777 CopyMem (StringTable + *((UINT16 *)InternalData), Data, *Size);
778 Status = EFI_SUCCESS;
779 } else {
780 Status = EFI_INVALID_PARAMETER;
781 }
782 break;
783
784 case PCD_TYPE_HII:
785 if (PtrType) {
786 if (!SetPtrTypeSize (TmpTokenNumber, Size)) {
787 Status = EFI_INVALID_PARAMETER;
788 break;
789 }
790 }
791
792 GuidTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.GuidTable :
793 mPcdDatabase->DxeDb.Init.GuidTable;
794
795 VariableHead = (VARIABLE_HEAD *) (PcdDb + Offset);
796
797 Guid = GuidTable + VariableHead->GuidTableIndex;
798 Name = StringTable + VariableHead->StringIndex;
799 VariableOffset = VariableHead->Offset;
800
801 Status = SetHiiVariable (Guid, Name, Data, *Size, VariableOffset);
802
803 if (EFI_NOT_FOUND == Status) {
804 CopyMem (PcdDb + VariableHead->DefaultValueOffset, Data, *Size);
805 Status = EFI_SUCCESS;
806 }
807 break;
808
809 case PCD_TYPE_DATA:
810 if (PtrType) {
811 if (SetPtrTypeSize (TmpTokenNumber, Size)) {
812 CopyMem (InternalData, Data, *Size);
813 Status = EFI_SUCCESS;
814 } else {
815 Status = EFI_INVALID_PARAMETER;
816 }
817 break;
818 }
819
820 Status = EFI_SUCCESS;
821 switch (*Size) {
822 case sizeof(UINT8):
823 *((UINT8 *) InternalData) = *((UINT8 *) Data);
824 break;
825
826 case sizeof(UINT16):
827 *((UINT16 *) InternalData) = *((UINT16 *) Data);
828 break;
829
830 case sizeof(UINT32):
831 *((UINT32 *) InternalData) = *((UINT32 *) Data);
832 break;
833
834 case sizeof(UINT64):
835 *((UINT64 *) InternalData) = *((UINT64 *) Data);
836 break;
837
838 default:
839 ASSERT (FALSE);
840 Status = EFI_NOT_FOUND;
841 break;
842 }
843 break;
844
845 default:
846 ASSERT (FALSE);
847 Status = EFI_NOT_FOUND;
848 break;
849 }
850
851 EfiReleaseLock (&mPcdDatabaseLock);
852
853 return Status;
854 }
855
856 /**
857 Wrapper function for get PCD value for dynamic-ex PCD.
858
859 @param Guid Token space guid for dynamic-ex PCD.
860 @param ExTokenNumber Token number for dynamic-ex PCD.
861 @param GetSize The size of dynamic-ex PCD value.
862
863 @return PCD entry in PCD database.
864
865 **/
866 VOID *
867 ExGetWorker (
868 IN CONST EFI_GUID *Guid,
869 IN UINTN ExTokenNumber,
870 IN UINTN GetSize
871 )
872 {
873 return GetWorker(GetExPcdTokenNumber (Guid, (UINT32) ExTokenNumber), GetSize);
874 }
875
876 /**
877 Wrapper function for set PCD value for non-Pointer type dynamic-ex PCD.
878
879 @param ExTokenNumber Token number for dynamic-ex PCD.
880 @param Guid Token space guid for dynamic-ex PCD.
881 @param Data Value want to be set.
882 @param SetSize The size of value.
883
884 @return status of ExSetWorker().
885
886 **/
887 EFI_STATUS
888 ExSetValueWorker (
889 IN UINTN ExTokenNumber,
890 IN CONST EFI_GUID *Guid,
891 IN VOID *Data,
892 IN UINTN SetSize
893 )
894 {
895 return ExSetWorker (ExTokenNumber, Guid, Data, &SetSize, FALSE);
896 }
897
898 /**
899 Set value for a dynamic PCD entry.
900
901 This routine find the local token number according to dynamic-ex PCD's token
902 space guid and token number firstly, and invoke callback function if this PCD
903 entry registered callback function. Finally, invoken general SetWorker to set
904 PCD value.
905
906 @param ExTokenNumber Dynamic-ex PCD token number.
907 @param Guid Token space guid for dynamic-ex PCD.
908 @param Data PCD value want to be set
909 @param SetSize Size of value.
910 @param PtrType If TRUE, this PCD entry is pointer type.
911 If FALSE, this PCD entry is not pointer type.
912
913 @return status of SetWorker().
914
915 **/
916 EFI_STATUS
917 ExSetWorker (
918 IN UINTN ExTokenNumber,
919 IN CONST EFI_GUID *Guid,
920 IN VOID *Data,
921 IN OUT UINTN *SetSize,
922 IN BOOLEAN PtrType
923 )
924 {
925 UINTN TokenNumber;
926
927 TokenNumber = GetExPcdTokenNumber (Guid, (UINT32) ExTokenNumber);
928
929 InvokeCallbackOnSet ((UINT32) ExTokenNumber, Guid, TokenNumber, Data, *SetSize);
930
931 return SetWorker (TokenNumber, Data, SetSize, PtrType);
932
933 }
934
935 /**
936 Set value for HII-type PCD.
937
938 A HII-type PCD's value is stored in a variable. Setting/Getting the value of
939 HII-type PCD is to visit this variable.
940
941 @param VariableGuid Guid of variable which stored value of a HII-type PCD.
942 @param VariableName Unicode name of variable which stored value of a HII-type PCD.
943 @param Data Value want to be set.
944 @param DataSize Size of value
945 @param Offset Value offset of HII-type PCD in variable.
946
947 @return status of GetVariable()/SetVariable().
948
949 **/
950 EFI_STATUS
951 SetHiiVariable (
952 IN EFI_GUID *VariableGuid,
953 IN UINT16 *VariableName,
954 IN CONST VOID *Data,
955 IN UINTN DataSize,
956 IN UINTN Offset
957 )
958 {
959 UINTN Size;
960 VOID *Buffer;
961 EFI_STATUS Status;
962 UINT32 Attribute;
963
964 Size = 0;
965
966 Status = gRT->GetVariable (
967 (UINT16 *)VariableName,
968 VariableGuid,
969 NULL,
970 &Size,
971 NULL
972 );
973
974 if (Status == EFI_BUFFER_TOO_SMALL) {
975
976 Buffer = AllocatePool (Size);
977
978 ASSERT (Buffer != NULL);
979
980 Status = gRT->GetVariable (
981 VariableName,
982 VariableGuid,
983 &Attribute,
984 &Size,
985 Buffer
986 );
987
988 ASSERT_EFI_ERROR (Status);
989
990 CopyMem ((UINT8 *)Buffer + Offset, Data, DataSize);
991
992 Status = gRT->SetVariable (
993 VariableName,
994 VariableGuid,
995 Attribute,
996 Size,
997 Buffer
998 );
999
1000 FreePool (Buffer);
1001 return Status;
1002
1003 }
1004
1005 //
1006 // If we drop to here, we don't have a Variable entry in
1007 // the variable service yet. So, we will save the data
1008 // in the PCD Database's volatile area.
1009 //
1010 return Status;
1011 }
1012
1013 /**
1014 Get local token number according to dynamic-ex PCD's {token space guid:token number}
1015
1016 A dynamic-ex type PCD, developer must provide pair of token space guid: token number
1017 in DEC file. PCD database maintain a mapping table that translate pair of {token
1018 space guid: token number} to local token number.
1019
1020 @param Guid Token space guid for dynamic-ex PCD entry.
1021 @param ExTokenNumber Dynamic-ex PCD token number.
1022
1023 @return local token number for dynamic-ex PCD.
1024
1025 **/
1026 UINTN
1027 GetExPcdTokenNumber (
1028 IN CONST EFI_GUID *Guid,
1029 IN UINT32 ExTokenNumber
1030 )
1031 {
1032 UINT32 Index;
1033 DYNAMICEX_MAPPING *ExMap;
1034 EFI_GUID *GuidTable;
1035 EFI_GUID *MatchGuid;
1036 UINTN MatchGuidIdx;
1037
1038 if (!PEI_DATABASE_EMPTY) {
1039 ExMap = mPcdDatabase->PeiDb.Init.ExMapTable;
1040 GuidTable = mPcdDatabase->PeiDb.Init.GuidTable;
1041
1042 MatchGuid = ScanGuid (GuidTable, sizeof(mPcdDatabase->PeiDb.Init.GuidTable), Guid);
1043
1044 if (MatchGuid != NULL) {
1045
1046 MatchGuidIdx = MatchGuid - GuidTable;
1047
1048 for (Index = 0; Index < PEI_EXMAPPING_TABLE_SIZE; Index++) {
1049 if ((ExTokenNumber == ExMap[Index].ExTokenNumber) &&
1050 (MatchGuidIdx == ExMap[Index].ExGuidIndex)) {
1051 return ExMap[Index].LocalTokenNumber;
1052 }
1053 }
1054 }
1055 }
1056
1057 ExMap = mPcdDatabase->DxeDb.Init.ExMapTable;
1058 GuidTable = mPcdDatabase->DxeDb.Init.GuidTable;
1059
1060 MatchGuid = ScanGuid (GuidTable, sizeof(mPcdDatabase->DxeDb.Init.GuidTable), Guid);
1061 //
1062 // We need to ASSERT here. If GUID can't be found in GuidTable, this is a
1063 // error in the BUILD system.
1064 //
1065 ASSERT (MatchGuid != NULL);
1066
1067 MatchGuidIdx = MatchGuid - GuidTable;
1068
1069 for (Index = 0; Index < DXE_EXMAPPING_TABLE_SIZE; Index++) {
1070 if ((ExTokenNumber == ExMap[Index].ExTokenNumber) &&
1071 (MatchGuidIdx == ExMap[Index].ExGuidIndex)) {
1072 return ExMap[Index].LocalTokenNumber;
1073 }
1074 }
1075
1076 ASSERT (FALSE);
1077
1078 return 0;
1079 }
1080
1081 /**
1082 Get SKU ID table from PCD database.
1083
1084 @param LocalTokenNumberTableIdx Index of local token number in token number table.
1085 @param IsPeiPcd If TRUE,
1086
1087 @return Pointer to SKU ID array table
1088
1089 **/
1090 SKU_ID *
1091 GetSkuIdArray (
1092 IN UINTN LocalTokenNumberTableIdx,
1093 IN BOOLEAN IsPeiPcd
1094 )
1095 {
1096 SKU_HEAD *SkuHead;
1097 UINTN LocalTokenNumber;
1098 UINT8 *Database;
1099
1100 if (IsPeiPcd) {
1101 LocalTokenNumber = mPcdDatabase->PeiDb.Init.LocalTokenNumberTable[LocalTokenNumberTableIdx];
1102 Database = (UINT8 *) &mPcdDatabase->PeiDb;
1103 } else {
1104 LocalTokenNumber = mPcdDatabase->DxeDb.Init.LocalTokenNumberTable[LocalTokenNumberTableIdx - PEI_LOCAL_TOKEN_NUMBER];
1105 Database = (UINT8 *) &mPcdDatabase->DxeDb;
1106 }
1107
1108 ASSERT ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) != 0);
1109
1110 SkuHead = (SKU_HEAD *) ((UINT8 *)Database + (LocalTokenNumber & PCD_DATABASE_OFFSET_MASK));
1111
1112 return (SKU_ID *) (Database + SkuHead->SkuIdTableOffset);
1113
1114 }
1115
1116
1117 /**
1118 Get index of PCD entry in size table.
1119
1120 @param LocalTokenNumberTableIdx Index of this PCD in local token number table.
1121 @param LocalTokenNumberTable Pointer to local token number table in PCD database.
1122 @param IsPeiDb If TRUE, the pcd entry is initialized in PEI phase,
1123 If FALSE, the pcd entry is initialized in DXE phase.
1124
1125 @return index of PCD entry in size table.
1126
1127 **/
1128 UINTN
1129 GetSizeTableIndexA (
1130 IN UINTN LocalTokenNumberTableIdx,
1131 IN UINT32 *LocalTokenNumberTable,
1132 IN BOOLEAN IsPeiDb
1133 )
1134 {
1135 UINTN Index;
1136 UINTN SizeTableIdx;
1137 UINTN LocalTokenNumber;
1138 SKU_ID *SkuIdTable;
1139
1140 SizeTableIdx = 0;
1141
1142 for (Index=0; Index<LocalTokenNumberTableIdx; Index++) {
1143 LocalTokenNumber = LocalTokenNumberTable[Index];
1144
1145 if ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER) {
1146 //
1147 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type
1148 // PCD entry.
1149 //
1150 if ((LocalTokenNumber & PCD_TYPE_VPD) != 0) {
1151 //
1152 // We have only one entry for VPD enabled PCD entry:
1153 // 1) MAX Size.
1154 // We consider current size is equal to MAX size.
1155 //
1156 SizeTableIdx++;
1157 } else {
1158 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0) {
1159 //
1160 // We have only two entry for Non-Sku enabled PCD entry:
1161 // 1) MAX SIZE
1162 // 2) Current Size
1163 //
1164 SizeTableIdx += 2;
1165 } else {
1166 //
1167 // We have these entry for SKU enabled PCD entry
1168 // 1) MAX SIZE
1169 // 2) Current Size for each SKU_ID (It is equal to MaxSku).
1170 //
1171 SkuIdTable = GetSkuIdArray (Index, IsPeiDb);
1172 SizeTableIdx += (UINTN)*SkuIdTable + 1;
1173 }
1174 }
1175 }
1176
1177 }
1178
1179 return SizeTableIdx;
1180 }
1181
1182
1183
1184 /**
1185 Wrapper function of getting index of PCD entry in size table.
1186
1187 @param LocalTokenNumberTableIdx Index of this PCD in local token number table.
1188 @param IsPeiDb If TRUE, the pcd entry is initialized in PEI phase,
1189 If FALSE, the pcd entry is initialized in DXE phase.
1190
1191 @return index of PCD entry in size table.
1192 **/
1193 UINTN
1194 GetSizeTableIndex (
1195 IN UINTN LocalTokenNumberTableIdx,
1196 IN BOOLEAN IsPeiDb
1197 )
1198 {
1199 UINT32 *LocalTokenNumberTable;
1200
1201 if (IsPeiDb) {
1202 LocalTokenNumberTable = mPcdDatabase->PeiDb.Init.LocalTokenNumberTable;
1203 } else {
1204 LocalTokenNumberTable = mPcdDatabase->DxeDb.Init.LocalTokenNumberTable;
1205 }
1206 return GetSizeTableIndexA (LocalTokenNumberTableIdx,
1207 LocalTokenNumberTable,
1208 IsPeiDb);
1209 }
1210
1211 /**
1212 Get size of POINTER type PCD value.
1213
1214 @param LocalTokenNumberTableIdx Index of local token number in local token number table.
1215 @param MaxSize Maxmium size of POINTER type PCD value.
1216
1217 @return size of POINTER type PCD value.
1218
1219 **/
1220 UINTN
1221 GetPtrTypeSize (
1222 IN UINTN LocalTokenNumberTableIdx,
1223 OUT UINTN *MaxSize
1224 )
1225 {
1226 INTN SizeTableIdx;
1227 UINTN LocalTokenNumber;
1228 SKU_ID *SkuIdTable;
1229 SIZE_INFO *SizeTable;
1230 UINTN Index;
1231 BOOLEAN IsPeiDb;
1232 UINT32 *LocalTokenNumberTable;
1233
1234 // EBC compiler is very choosy. It may report warning about comparison
1235 // between UINTN and 0 . So we add 1 in each size of the
1236 // comparison.
1237 IsPeiDb = (BOOLEAN) (LocalTokenNumberTableIdx + 1 < PEI_LOCAL_TOKEN_NUMBER + 1);
1238
1239
1240 if (IsPeiDb) {
1241 LocalTokenNumberTable = mPcdDatabase->PeiDb.Init.LocalTokenNumberTable;
1242 SizeTable = mPcdDatabase->PeiDb.Init.SizeTable;
1243 } else {
1244 LocalTokenNumberTableIdx -= PEI_LOCAL_TOKEN_NUMBER;
1245 LocalTokenNumberTable = mPcdDatabase->DxeDb.Init.LocalTokenNumberTable;
1246 SizeTable = mPcdDatabase->DxeDb.Init.SizeTable;
1247 }
1248
1249 LocalTokenNumber = LocalTokenNumberTable[LocalTokenNumberTableIdx];
1250
1251 ASSERT ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER);
1252
1253 SizeTableIdx = GetSizeTableIndex (LocalTokenNumberTableIdx, IsPeiDb);
1254
1255 *MaxSize = SizeTable[SizeTableIdx];
1256 //
1257 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type
1258 // PCD entry.
1259 //
1260 if ((LocalTokenNumber & PCD_TYPE_VPD) != 0) {
1261 //
1262 // We have only one entry for VPD enabled PCD entry:
1263 // 1) MAX Size.
1264 // We consider current size is equal to MAX size.
1265 //
1266 return *MaxSize;
1267 } else {
1268 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0) {
1269 //
1270 // We have only two entry for Non-Sku enabled PCD entry:
1271 // 1) MAX SIZE
1272 // 2) Current Size
1273 //
1274 return SizeTable[SizeTableIdx + 1];
1275 } else {
1276 //
1277 // We have these entry for SKU enabled PCD entry
1278 // 1) MAX SIZE
1279 // 2) Current Size for each SKU_ID (It is equal to MaxSku).
1280 //
1281 SkuIdTable = GetSkuIdArray (LocalTokenNumberTableIdx, IsPeiDb);
1282 for (Index = 0; Index < SkuIdTable[0]; Index++) {
1283 if (SkuIdTable[1 + Index] == mPcdDatabase->PeiDb.Init.SystemSkuId) {
1284 return SizeTable[SizeTableIdx + 1 + Index];
1285 }
1286 }
1287 return SizeTable[SizeTableIdx + 1];
1288 }
1289 }
1290 }
1291
1292 /**
1293 Set size of POINTER type PCD value. The size should not exceed the maximum size
1294 of this PCD value.
1295
1296 @param LocalTokenNumberTableIdx Index of local token number in local token number table.
1297 @param CurrentSize Size of POINTER type PCD value.
1298
1299 @retval TRUE Success to set size of PCD value.
1300 @retval FALSE Fail to set size of PCD value.
1301 **/
1302 BOOLEAN
1303 SetPtrTypeSize (
1304 IN UINTN LocalTokenNumberTableIdx,
1305 IN OUT UINTN *CurrentSize
1306 )
1307 {
1308 INTN SizeTableIdx;
1309 UINTN LocalTokenNumber;
1310 SKU_ID *SkuIdTable;
1311 SIZE_INFO *SizeTable;
1312 UINTN Index;
1313 UINTN MaxSize;
1314 BOOLEAN IsPeiDb;
1315 UINT32 *LocalTokenNumberTable;
1316
1317 //
1318 // EBC compiler is very choosy. It may report warning about comparison
1319 // between UINTN and 0 . So we add 1 in each size of the
1320 // comparison.
1321 //
1322 IsPeiDb = (BOOLEAN) (LocalTokenNumberTableIdx + 1 < PEI_LOCAL_TOKEN_NUMBER + 1);
1323
1324 if (IsPeiDb) {
1325 LocalTokenNumberTable = mPcdDatabase->PeiDb.Init.LocalTokenNumberTable;
1326 SizeTable = mPcdDatabase->PeiDb.Init.SizeTable;
1327 } else {
1328 LocalTokenNumberTableIdx -= PEI_LOCAL_TOKEN_NUMBER;
1329 LocalTokenNumberTable = mPcdDatabase->DxeDb.Init.LocalTokenNumberTable;
1330 SizeTable = mPcdDatabase->DxeDb.Init.SizeTable;
1331 }
1332
1333 LocalTokenNumber = LocalTokenNumberTable[LocalTokenNumberTableIdx];
1334
1335 ASSERT ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER);
1336
1337 SizeTableIdx = GetSizeTableIndex (LocalTokenNumberTableIdx, IsPeiDb);
1338
1339 MaxSize = SizeTable[SizeTableIdx];
1340 //
1341 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type
1342 // PCD entry.
1343 //
1344 if ((LocalTokenNumber & PCD_TYPE_VPD) != 0) {
1345 //
1346 // We shouldn't come here as we don't support SET for VPD
1347 //
1348 ASSERT (FALSE);
1349 return FALSE;
1350 } else {
1351 if ((*CurrentSize > MaxSize) ||
1352 (*CurrentSize == MAX_ADDRESS)) {
1353 *CurrentSize = MaxSize;
1354 return FALSE;
1355 }
1356
1357 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0) {
1358 //
1359 // We have only two entry for Non-Sku enabled PCD entry:
1360 // 1) MAX SIZE
1361 // 2) Current Size
1362 //
1363 SizeTable[SizeTableIdx + 1] = (SIZE_INFO) *CurrentSize;
1364 return TRUE;
1365 } else {
1366 //
1367 // We have these entry for SKU enabled PCD entry
1368 // 1) MAX SIZE
1369 // 2) Current Size for each SKU_ID (It is equal to MaxSku).
1370 //
1371 SkuIdTable = GetSkuIdArray (LocalTokenNumberTableIdx, IsPeiDb);
1372 for (Index = 0; Index < SkuIdTable[0]; Index++) {
1373 if (SkuIdTable[1 + Index] == mPcdDatabase->PeiDb.Init.SystemSkuId) {
1374 SizeTable[SizeTableIdx + 1 + Index] = (SIZE_INFO) *CurrentSize;
1375 return TRUE;
1376 }
1377 }
1378 SizeTable[SizeTableIdx + 1] = (SIZE_INFO) *CurrentSize;
1379 return TRUE;
1380 }
1381 }
1382 }