]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/PCD/Pei/Service.c
Code scrub for PCD PEIM.
[mirror_edk2.git] / MdeModulePkg / Universal / PCD / Pei / Service.c
1 /** @file
2 Private functions used by PCD PEIM.
3
4 Copyright (c) 2006, Intel Corporation
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13
14 Module Name: Service.c
15
16 **/
17
18 #include "Service.h"
19
20 /**
21 The function registers the CallBackOnSet fucntion
22 according to TokenNumber and EFI_GUID space.
23
24 @param ExTokenNumber The token number.
25 @param Guid The GUID space.
26 @param CallBackFunction The Callback function to be registered.
27 @param Register To register or unregister the callback function.
28
29 @retval EFI_SUCCESS If the Callback function is registered.
30 @retval EFI_NOT_FOUND If the PCD Entry is not found according to Token Number and GUID space.
31 @retval EFI_OUT_OF_RESOURCES If the callback function can't be registered because there is not free
32 slot left in the CallbackFnTable.
33 **/
34 EFI_STATUS
35 PeiRegisterCallBackWorker (
36 IN UINTN ExTokenNumber,
37 IN CONST EFI_GUID *Guid, OPTIONAL
38 IN PCD_PPI_CALLBACK CallBackFunction,
39 IN BOOLEAN Register
40 )
41 {
42 EFI_HOB_GUID_TYPE *GuidHob;
43 PCD_PPI_CALLBACK *CallbackTable;
44 PCD_PPI_CALLBACK Compare;
45 PCD_PPI_CALLBACK Assign;
46 UINT32 LocalTokenNumber;
47 UINTN TokenNumber;
48 UINTN Idx;
49
50 if (Guid == NULL) {
51 TokenNumber = ExTokenNumber;
52
53 //
54 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
55 // We have to decrement TokenNumber by 1 to make it usable
56 // as the array index.
57 //
58 TokenNumber--;
59 ASSERT (TokenNumber + 1 < PEI_NEX_TOKEN_NUMBER + 1);
60 } else {
61 TokenNumber = GetExPcdTokenNumber (Guid, ExTokenNumber);
62
63 //
64 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
65 // We have to decrement TokenNumber by 1 to make it usable
66 // as the array index.
67 //
68 TokenNumber--;
69 // EBC compiler is very choosy. It may report warning about comparison
70 // between UINTN and 0 . So we add 1 in each size of the
71 // comparison.
72 ASSERT (TokenNumber + 1 < PEI_LOCAL_TOKEN_NUMBER + 1);
73 }
74
75
76 LocalTokenNumber = GetPcdDatabase()->Init.LocalTokenNumberTable[TokenNumber];
77
78 //
79 // We don't support SET for HII and VPD type PCD entry in PEI phase.
80 // So we will assert if any register callback for such PCD entry.
81 //
82 ASSERT ((LocalTokenNumber & PCD_TYPE_HII) == 0);
83 ASSERT ((LocalTokenNumber & PCD_TYPE_VPD) == 0);
84
85 GuidHob = GetFirstGuidHob (&gPcdPeiCallbackFnTableHobGuid);
86 ASSERT (GuidHob != NULL);
87
88 CallbackTable = GET_GUID_HOB_DATA (GuidHob);
89 CallbackTable = CallbackTable + (TokenNumber * FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry));
90
91 Compare = Register? NULL: CallBackFunction;
92 Assign = Register? CallBackFunction: NULL;
93
94
95 for (Idx = 0; Idx < FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry); Idx++) {
96 if (CallbackTable[Idx] == Compare) {
97 CallbackTable[Idx] = Assign;
98 return EFI_SUCCESS;
99 }
100 }
101
102 return Register? EFI_OUT_OF_RESOURCES : EFI_NOT_FOUND;
103
104 }
105
106 /**
107 The function builds the PCD database.
108 **/
109 VOID
110 BuildPcdDatabase (
111 VOID
112 )
113 {
114 PEI_PCD_DATABASE *Database;
115 VOID *CallbackFnTable;
116 UINTN SizeOfCallbackFnTable;
117
118 Database = BuildGuidHob (&gPcdDataBaseHobGuid, sizeof (PEI_PCD_DATABASE));
119
120 ZeroMem (Database, sizeof (PEI_PCD_DATABASE));
121
122 //
123 // gPEIPcdDbInit is smaller than PEI_PCD_DATABASE
124 //
125
126 CopyMem (&Database->Init, &gPEIPcdDbInit, sizeof (gPEIPcdDbInit));
127
128 SizeOfCallbackFnTable = PEI_LOCAL_TOKEN_NUMBER * sizeof (PCD_PPI_CALLBACK) * FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry);
129
130 CallbackFnTable = BuildGuidHob (&gPcdPeiCallbackFnTableHobGuid, SizeOfCallbackFnTable);
131
132 ZeroMem (CallbackFnTable, SizeOfCallbackFnTable);
133 }
134
135 /**
136 The function is provided by PCD PEIM and PCD DXE driver to
137 do the work of reading a HII variable from variable service.
138
139 @param VariableGuid The Variable GUID.
140 @param VariableName The Variable Name.
141 @param VariableData The output data.
142 @param VariableSize The size of the variable.
143
144 @retval EFI_SUCCESS Operation successful.
145 @retval EFI_NOT_FOUND Variablel not found.
146 **/
147 EFI_STATUS
148 GetHiiVariable (
149 IN CONST EFI_GUID *VariableGuid,
150 IN UINT16 *VariableName,
151 OUT VOID **VariableData,
152 OUT UINTN *VariableSize
153 )
154 {
155 UINTN Size;
156 EFI_STATUS Status;
157 VOID *Buffer;
158 EFI_PEI_READ_ONLY_VARIABLE2_PPI *VariablePpi;
159
160 Status = PeiServicesLocatePpi (&gEfiPeiReadOnlyVariable2PpiGuid, 0, NULL, (VOID **) &VariablePpi);
161 ASSERT_EFI_ERROR (Status);
162
163 Size = 0;
164 Status = VariablePpi->GetVariable (
165 VariablePpi,
166 VariableName,
167 (EFI_GUID *) VariableGuid,
168 NULL,
169 &Size,
170 NULL
171 );
172 if (Status == EFI_BUFFER_TOO_SMALL) {
173
174
175 Status = PeiServicesAllocatePool (Size, &Buffer);
176 ASSERT_EFI_ERROR (Status);
177
178 Status = VariablePpi->GetVariable (
179 VariablePpi,
180 (UINT16 *) VariableName,
181 (EFI_GUID *) VariableGuid,
182 NULL,
183 &Size,
184 Buffer
185 );
186 ASSERT_EFI_ERROR (Status);
187
188 *VariableSize = Size;
189 *VariableData = Buffer;
190
191 return EFI_SUCCESS;
192 }
193
194 return EFI_NOT_FOUND;
195 }
196
197 /**
198 Find the local token number according to system SKU ID.
199
200 @param LocalTokenNumber PCD token number
201 @param Size The size of PCD entry.
202
203 @return Token number according to system SKU ID.
204
205 **/
206 UINT32
207 GetSkuEnabledTokenNumber (
208 UINT32 LocalTokenNumber,
209 UINTN Size
210 )
211 {
212 PEI_PCD_DATABASE *PeiPcdDb;
213 SKU_HEAD *SkuHead;
214 SKU_ID *SkuIdTable;
215 INTN Index;
216 UINT8 *Value;
217
218 PeiPcdDb = GetPcdDatabase ();
219
220 ASSERT ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0);
221
222 SkuHead = (SKU_HEAD *) ((UINT8 *)PeiPcdDb + (LocalTokenNumber & PCD_DATABASE_OFFSET_MASK));
223 Value = (UINT8 *) ((UINT8 *)PeiPcdDb + (SkuHead->SkuDataStartOffset));
224 SkuIdTable = (SKU_ID *) ((UINT8 *)PeiPcdDb + (SkuHead->SkuIdTableOffset));
225
226 for (Index = 0; Index < SkuIdTable[0]; Index++) {
227 if (PeiPcdDb->Init.SystemSkuId == SkuIdTable[Index + 1]) {
228 break;
229 }
230 }
231
232 switch (LocalTokenNumber & PCD_TYPE_ALL_SET) {
233 case PCD_TYPE_VPD:
234 Value = (UINT8 *) &(((VPD_HEAD *) Value)[Index]);
235 return (UINT32) ((Value - (UINT8 *) PeiPcdDb) | PCD_TYPE_VPD);
236
237 case PCD_TYPE_HII:
238 Value = (UINT8 *) &(((VARIABLE_HEAD *) Value)[Index]);
239 return (UINT32) ((Value - (UINT8 *) PeiPcdDb) | PCD_TYPE_HII);
240
241 case PCD_TYPE_STRING:
242 Value = (UINT8 *) &(((STRING_HEAD *) Value)[Index]);
243 return (UINT32) ((Value - (UINT8 *) PeiPcdDb) | PCD_TYPE_STRING);
244
245 case PCD_TYPE_DATA:
246 Value += Size * Index;
247 return (UINT32) (Value - (UINT8 *) PeiPcdDb);
248
249 default:
250 ASSERT (FALSE);
251 }
252
253 ASSERT (FALSE);
254
255 return 0;
256 }
257
258 /**
259 Invoke the callback function when dynamic PCD entry was set, if this PCD entry
260 has registered callback function.
261
262 @param ExTokenNumber DynamicEx PCD's token number, if this PCD entry is dyanmicEx
263 type PCD.
264 @param Guid DynamicEx PCD's guid, if this PCD entry is dynamicEx type
265 PCD.
266 @param TokenNumber PCD token number generated by build tools.
267 @param Data Value want to be set for this PCD entry
268 @param Size The size of value
269
270 **/
271 VOID
272 InvokeCallbackOnSet (
273 UINTN ExTokenNumber,
274 CONST EFI_GUID *Guid, OPTIONAL
275 UINTN TokenNumber,
276 VOID *Data,
277 UINTN Size
278 )
279 {
280 EFI_HOB_GUID_TYPE *GuidHob;
281 PCD_PPI_CALLBACK *CallbackTable;
282 UINTN Idx;
283
284 //
285 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
286 // We have to decrement TokenNumber by 1 to make it usable
287 // as the array index.
288 //
289 TokenNumber--;
290
291 if (Guid == NULL) {
292 // EBC compiler is very choosy. It may report warning about comparison
293 // between UINTN and 0 . So we add 1 in each size of the
294 // comparison.
295 ASSERT (TokenNumber + 1 < PEI_LOCAL_TOKEN_NUMBER + 1);
296 }
297
298 GuidHob = GetFirstGuidHob (&gPcdPeiCallbackFnTableHobGuid);
299 ASSERT (GuidHob != NULL);
300
301 CallbackTable = GET_GUID_HOB_DATA (GuidHob);
302
303 CallbackTable += (TokenNumber * FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry));
304
305 for (Idx = 0; Idx < FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry); Idx++) {
306 if (CallbackTable[Idx] != NULL) {
307 CallbackTable[Idx] (Guid,
308 (Guid == NULL)? TokenNumber: ExTokenNumber,
309 Data,
310 Size
311 );
312 }
313 }
314 }
315
316 /**
317 Wrapper function for setting non-pointer type value for a PCD entry.
318
319 @param TokenNumber Pcd token number autogenerated by build tools.
320 @param Data Value want to be set for PCD entry
321 @param Size Size of value.
322
323 @return status of SetWorker.
324
325 **/
326 EFI_STATUS
327 SetValueWorker (
328 IN UINTN TokenNumber,
329 IN VOID *Data,
330 IN UINTN Size
331 )
332 {
333 return SetWorker (TokenNumber, Data, &Size, FALSE);
334 }
335
336 /**
337 Set value for an PCD entry
338
339 @param TokenNumber Pcd token number autogenerated by build tools.
340 @param Data Value want to be set for PCD entry
341 @param Size Size of value.
342 @param PtrType If TRUE, the type of PCD entry's value is Pointer.
343 If False, the type of PCD entry's value is not Pointer.
344
345 @retval EFI_INVALID_PARAMETER If this PCD type is VPD, VPD PCD can not be set.
346 @retval EFI_INVALID_PARAMETER If Size can not be set to size table.
347 @retval EFI_NOT_FOUND If value type of PCD entry is intergrate, but not in
348 range of UINT8, UINT16, UINT32, UINT64
349 @retval EFI_NOT_FOUND Can not find the PCD type according to token number.
350 **/
351 EFI_STATUS
352 SetWorker (
353 IN UINTN TokenNumber,
354 IN VOID *Data,
355 IN OUT UINTN *Size,
356 IN BOOLEAN PtrType
357 )
358 {
359 UINT32 LocalTokenNumber;
360 PEI_PCD_DATABASE *PeiPcdDb;
361 UINT16 StringTableIdx;
362 UINTN Offset;
363 VOID *InternalData;
364 UINTN MaxSize;
365
366 if (!FeaturePcdGet(PcdPeiPcdDatabaseSetEnabled)) {
367 return EFI_UNSUPPORTED;
368 }
369
370 //
371 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
372 // We have to decrement TokenNumber by 1 to make it usable
373 // as the array index.
374 //
375 TokenNumber--;
376
377 // EBC compiler is very choosy. It may report warning about comparison
378 // between UINTN and 0 . So we add 1 in each size of the
379 // comparison.
380 ASSERT (TokenNumber + 1 < PEI_LOCAL_TOKEN_NUMBER + 1);
381
382 PeiPcdDb = GetPcdDatabase ();
383
384 LocalTokenNumber = PeiPcdDb->Init.LocalTokenNumberTable[TokenNumber];
385
386 if (!PtrType) {
387 ASSERT (PeiPcdGetSize(TokenNumber + 1) == *Size);
388 }
389
390 //
391 // We only invoke the callback function for Dynamic Type PCD Entry.
392 // For Dynamic EX PCD entry, we have invoked the callback function for Dynamic EX
393 // type PCD entry in ExSetWorker.
394 //
395 if (TokenNumber + 1 < PEI_NEX_TOKEN_NUMBER + 1) {
396 InvokeCallbackOnSet (0, NULL, TokenNumber + 1, Data, *Size);
397 }
398
399 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == PCD_TYPE_SKU_ENABLED) {
400 if (PtrType) {
401 MaxSize = GetPtrTypeSize (TokenNumber, &MaxSize, PeiPcdDb);
402 } else {
403 MaxSize = *Size;
404 }
405 LocalTokenNumber = GetSkuEnabledTokenNumber (LocalTokenNumber & ~PCD_TYPE_SKU_ENABLED, MaxSize);
406 }
407
408 Offset = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK;
409 InternalData = (VOID *) ((UINT8 *) PeiPcdDb + Offset);
410
411 switch (LocalTokenNumber & PCD_TYPE_ALL_SET) {
412 case PCD_TYPE_VPD:
413 case PCD_TYPE_HII:
414 {
415 ASSERT (FALSE);
416 return EFI_INVALID_PARAMETER;
417 }
418
419 case PCD_TYPE_STRING:
420 if (SetPtrTypeSize (TokenNumber, Size, PeiPcdDb)) {
421 StringTableIdx = *((UINT16 *)InternalData);
422 CopyMem (&PeiPcdDb->Init.StringTable[StringTableIdx], Data, *Size);
423 return EFI_SUCCESS;
424 } else {
425 return EFI_INVALID_PARAMETER;
426 }
427
428 case PCD_TYPE_DATA:
429 {
430 if (PtrType) {
431 if (SetPtrTypeSize (TokenNumber, Size, PeiPcdDb)) {
432 CopyMem (InternalData, Data, *Size);
433 return EFI_SUCCESS;
434 } else {
435 return EFI_INVALID_PARAMETER;
436 }
437 }
438
439 switch (*Size) {
440 case sizeof(UINT8):
441 *((UINT8 *) InternalData) = *((UINT8 *) Data);
442 return EFI_SUCCESS;
443
444 case sizeof(UINT16):
445 *((UINT16 *) InternalData) = *((UINT16 *) Data);
446 return EFI_SUCCESS;
447
448 case sizeof(UINT32):
449 *((UINT32 *) InternalData) = *((UINT32 *) Data);
450 return EFI_SUCCESS;
451
452 case sizeof(UINT64):
453 *((UINT64 *) InternalData) = *((UINT64 *) Data);
454 return EFI_SUCCESS;
455
456 default:
457 ASSERT (FALSE);
458 return EFI_NOT_FOUND;
459 }
460 }
461
462 }
463
464 ASSERT (FALSE);
465 return EFI_NOT_FOUND;
466
467 }
468
469 /**
470 Wrapper function for set PCD value for non-Pointer type dynamic-ex PCD.
471
472 @param ExTokenNumber Token number for dynamic-ex PCD.
473 @param Guid Token space guid for dynamic-ex PCD.
474 @param Data Value want to be set.
475 @param SetSize The size of value.
476
477 @return status of ExSetWorker().
478
479 **/
480 EFI_STATUS
481 ExSetValueWorker (
482 IN UINTN ExTokenNumber,
483 IN CONST EFI_GUID *Guid,
484 IN VOID *Data,
485 IN UINTN Size
486 )
487 {
488 return ExSetWorker (ExTokenNumber, Guid, Data, &Size, FALSE);
489 }
490
491 /**
492 Set value for a dynamic PCD entry.
493
494 This routine find the local token number according to dynamic-ex PCD's token
495 space guid and token number firstly, and invoke callback function if this PCD
496 entry registered callback function. Finally, invoken general SetWorker to set
497 PCD value.
498
499 @param ExTokenNumber Dynamic-ex PCD token number.
500 @param Guid Token space guid for dynamic-ex PCD.
501 @param Data PCD value want to be set
502 @param SetSize Size of value.
503 @param PtrType If TRUE, this PCD entry is pointer type.
504 If FALSE, this PCD entry is not pointer type.
505
506 @return status of SetWorker().
507
508 **/
509 EFI_STATUS
510 ExSetWorker (
511 IN UINTN ExTokenNumber,
512 IN CONST EFI_GUID *Guid,
513 IN VOID *Data,
514 IN OUT UINTN *Size,
515 IN BOOLEAN PtrType
516 )
517 {
518 UINTN TokenNumber;
519
520 if (!FeaturePcdGet(PcdPeiPcdDatabaseSetEnabled)) {
521 return EFI_UNSUPPORTED;
522 }
523
524 TokenNumber = GetExPcdTokenNumber (Guid, ExTokenNumber);
525
526 InvokeCallbackOnSet (ExTokenNumber, Guid, TokenNumber, Data, *Size);
527
528 return SetWorker (TokenNumber, Data, Size, PtrType);
529
530 }
531
532 /**
533 Wrapper function for get PCD value for dynamic-ex PCD.
534
535 @param Guid Token space guid for dynamic-ex PCD.
536 @param ExTokenNumber Token number for dyanmic-ex PCD.
537 @param GetSize The size of dynamic-ex PCD value.
538
539 @return PCD entry in PCD database.
540
541 **/
542 VOID *
543 ExGetWorker (
544 IN CONST EFI_GUID *Guid,
545 IN UINTN ExTokenNumber,
546 IN UINTN GetSize
547 )
548 {
549 if (!FeaturePcdGet (PcdPeiPcdDatabaseExEnabled)) {
550 ASSERT (FALSE);
551 return 0;
552 }
553
554 return GetWorker (GetExPcdTokenNumber (Guid, ExTokenNumber), GetSize);
555 }
556
557 /**
558 Get the PCD entry pointer in PCD database.
559
560 This routine will visit PCD database to find the PCD entry according to given
561 token number. The given token number is autogened by build tools and it will be
562 translated to local token number. Local token number contains PCD's type and
563 offset of PCD entry in PCD database.
564
565 @param TokenNumber Token's number, it is autogened by build tools
566 @param GetSize The size of token's value
567
568 @return PCD entry pointer in PCD database
569
570 **/
571 VOID *
572 GetWorker (
573 IN UINTN TokenNumber,
574 IN UINTN GetSize
575 )
576 {
577 UINT32 Offset;
578 EFI_GUID *Guid;
579 UINT16 *Name;
580 VARIABLE_HEAD *VariableHead;
581 EFI_STATUS Status;
582 UINTN DataSize;
583 VOID *Data;
584 UINT16 *StringTable;
585 UINT16 StringTableIdx;
586 PEI_PCD_DATABASE *PeiPcdDb;
587 UINT32 LocalTokenNumber;
588 UINTN MaxSize;
589
590 //
591 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
592 // We have to decrement TokenNumber by 1 to make it usable
593 // as the array index.
594 //
595 TokenNumber--;
596
597 // EBC compiler is very choosy. It may report warning about comparison
598 // between UINTN and 0 . So we add 1 in each size of the
599 // comparison.
600 ASSERT (TokenNumber + 1 < PEI_LOCAL_TOKEN_NUMBER + 1);
601
602 ASSERT ((GetSize == PeiPcdGetSize(TokenNumber + 1)) || (GetSize == 0));
603
604 PeiPcdDb = GetPcdDatabase ();
605
606 LocalTokenNumber = PeiPcdDb->Init.LocalTokenNumberTable[TokenNumber];
607
608 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == PCD_TYPE_SKU_ENABLED) {
609 if (GetSize == 0) {
610 MaxSize = GetPtrTypeSize (TokenNumber, &MaxSize, PeiPcdDb);
611 } else {
612 MaxSize = GetSize;
613 }
614 LocalTokenNumber = GetSkuEnabledTokenNumber (LocalTokenNumber & ~PCD_TYPE_SKU_ENABLED, MaxSize);
615 }
616
617 Offset = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK;
618 StringTable = PeiPcdDb->Init.StringTable;
619
620 switch (LocalTokenNumber & PCD_TYPE_ALL_SET) {
621 case PCD_TYPE_VPD:
622 {
623 VPD_HEAD *VpdHead;
624 VpdHead = (VPD_HEAD *) ((UINT8 *)PeiPcdDb + Offset);
625 return (VOID *) (UINTN) (FixedPcdGet32(PcdVpdBaseAddress) + VpdHead->Offset);
626 }
627
628 case PCD_TYPE_HII:
629 {
630 VariableHead = (VARIABLE_HEAD *) ((UINT8 *)PeiPcdDb + Offset);
631
632 Guid = &(PeiPcdDb->Init.GuidTable[VariableHead->GuidTableIndex]);
633 Name = &StringTable[VariableHead->StringIndex];
634
635 Status = GetHiiVariable (Guid, Name, &Data, &DataSize);
636
637 if (Status == EFI_SUCCESS) {
638 return (VOID *) ((UINT8 *) Data + VariableHead->Offset);
639 } else {
640 //
641 // Return the default value specified by Platform Integrator
642 //
643 return (VOID *) ((UINT8 *) PeiPcdDb + VariableHead->DefaultValueOffset);
644 }
645 }
646
647 case PCD_TYPE_DATA:
648 return (VOID *) ((UINT8 *)PeiPcdDb + Offset);
649
650 case PCD_TYPE_STRING:
651 StringTableIdx = (UINT16) *((UINT8 *) PeiPcdDb + Offset);
652 return (VOID *) (&StringTable[StringTableIdx]);
653
654 default:
655 ASSERT (FALSE);
656 break;
657
658 }
659
660 ASSERT (FALSE);
661
662 return NULL;
663
664 }
665
666 /**
667 Get local token number according to dynamic-ex PCD's {token space guid:token number}
668
669 A dynamic-ex type PCD, developer must provide pair of token space guid: token number
670 in DEC file. PCD database maintain a mapping table that translate pair of {token
671 space guid: token number} to local token number.
672
673 @param Guid Token space guid for dynamic-ex PCD entry.
674 @param ExTokenNumber EDES_TODO: Add parameter description
675
676 @return local token number for dynamic-ex PCD.
677
678 **/
679 UINTN
680 GetExPcdTokenNumber (
681 IN CONST EFI_GUID *Guid,
682 IN UINTN ExTokenNumber
683 )
684 {
685 UINT32 Index;
686 DYNAMICEX_MAPPING *ExMap;
687 EFI_GUID *GuidTable;
688 EFI_GUID *MatchGuid;
689 UINTN MatchGuidIdx;
690 PEI_PCD_DATABASE *PeiPcdDb;
691
692 PeiPcdDb = GetPcdDatabase();
693
694 ExMap = PeiPcdDb->Init.ExMapTable;
695 GuidTable = PeiPcdDb->Init.GuidTable;
696
697 MatchGuid = ScanGuid (GuidTable, sizeof(PeiPcdDb->Init.GuidTable), Guid);
698 //
699 // We need to ASSERT here. If GUID can't be found in GuidTable, this is a
700 // error in the BUILD system.
701 //
702 ASSERT (MatchGuid != NULL);
703
704 MatchGuidIdx = MatchGuid - GuidTable;
705
706 for (Index = 0; Index < PEI_EXMAPPING_TABLE_SIZE; Index++) {
707 if ((ExTokenNumber == ExMap[Index].ExTokenNumber) &&
708 (MatchGuidIdx == ExMap[Index].ExGuidIndex)) {
709 return ExMap[Index].LocalTokenNumber;
710 }
711 }
712
713 ASSERT (FALSE);
714
715 return 0;
716 }
717
718 /**
719 Get PCD database from GUID HOB in PEI phase.
720
721 @return Pointer to PCD database.
722
723 **/
724 PEI_PCD_DATABASE *
725 GetPcdDatabase (
726 VOID
727 )
728 {
729 EFI_HOB_GUID_TYPE *GuidHob;
730
731 GuidHob = GetFirstGuidHob (&gPcdDataBaseHobGuid);
732 ASSERT (GuidHob != NULL);
733
734 return (PEI_PCD_DATABASE *) GET_GUID_HOB_DATA (GuidHob);
735 }
736
737 /**
738 Get SKU ID tabble from PCD database.
739
740 @param LocalTokenNumberTableIdx Index of local token number in token number table.
741 @param Database PCD database.
742
743 @return Pointer to SKU ID array table
744
745 **/
746 SKU_ID *
747 GetSkuIdArray (
748 IN UINTN LocalTokenNumberTableIdx,
749 IN PEI_PCD_DATABASE *Database
750 )
751 {
752 SKU_HEAD *SkuHead;
753 UINTN LocalTokenNumber;
754
755 LocalTokenNumber = Database->Init.LocalTokenNumberTable[LocalTokenNumberTableIdx];
756
757 ASSERT ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) != 0);
758
759 SkuHead = (SKU_HEAD *) ((UINT8 *)Database + (LocalTokenNumber & PCD_DATABASE_OFFSET_MASK));
760
761 return (SKU_ID *) ((UINT8 *)Database + SkuHead->SkuIdTableOffset);
762
763 }
764
765 /**
766 Get index of PCD entry in size table.
767
768 @param LocalTokenNumberTableIdx Index of this PCD in local token number table.
769 @param Database Pointer to PCD database in PEI phase.
770
771 @return index of PCD entry in size table.
772
773 **/
774 UINTN
775 GetSizeTableIndex (
776 IN UINTN LocalTokenNumberTableIdx,
777 IN PEI_PCD_DATABASE *Database
778 )
779 {
780 UINTN Index;
781 UINTN SizeTableIdx;
782 UINTN LocalTokenNumber;
783 SKU_ID *SkuIdTable;
784
785 SizeTableIdx = 0;
786
787 for (Index=0; Index<LocalTokenNumberTableIdx; Index++) {
788 LocalTokenNumber = Database->Init.LocalTokenNumberTable[Index];
789
790 if ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER) {
791 //
792 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type
793 // PCD entry.
794 //
795 if ((LocalTokenNumber & PCD_TYPE_VPD) != 0) {
796 //
797 // We have only one entry for VPD enabled PCD entry:
798 // 1) MAX Size.
799 // We consider current size is equal to MAX size.
800 //
801 SizeTableIdx++;
802 } else {
803 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0) {
804 //
805 // We have only two entry for Non-Sku enabled PCD entry:
806 // 1) MAX SIZE
807 // 2) Current Size
808 //
809 SizeTableIdx += 2;
810 } else {
811 //
812 // We have these entry for SKU enabled PCD entry
813 // 1) MAX SIZE
814 // 2) Current Size for each SKU_ID (It is equal to MaxSku).
815 //
816 SkuIdTable = GetSkuIdArray (Index, Database);
817 SizeTableIdx += (UINTN)*SkuIdTable + 1;
818 }
819 }
820 }
821
822 }
823
824 return SizeTableIdx;
825 }