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