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