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