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