Check in the Pcd service Driver/PEIM according to the new way of generating PCD Database
[mirror_edk2.git] / EdkModulePkg / Universal / PCD / Common / PcdCommon.c
CommitLineData
878ddf1f 1/** @file\r
2Common functions used by PCD PEIM and PCD DXE.\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: PcdCommon.c\r
15\r
16**/\r
17#include "PcdCommon.h"\r
18\r
19\r
20\r
21/**\r
22 The function retrieves the PCD data value according to\r
23 the PCD_DATA_TYPE specified.\r
24\r
25 @param[in] Type The PCD_DATA_TYPE used to interpret the data.\r
26 @param[in] InData The input data.\r
27 @param[in] OutData The output data.\r
28 @param[in] Len The length of the data; it is mainly used for PcdPointer type.\r
29\r
30 @retval VOID\r
31--*/\r
32VOID\r
33GetDataBasedOnType (\r
34 IN PCD_DATA_TYPE Type,\r
35 IN VOID *InData,\r
36 OUT VOID *OutData,\r
37 IN UINTN Len\r
38 )\r
39{\r
40 if (Type == PcdPointer) {\r
41 //\r
42 // When the Type is PcdPointer, we are returning \r
43 // the address of the internal buffer kpet by\r
44 // PCD database. Therefore, we treat OutData as\r
45 // a pointer to a "VOID *". Thus, the ugly type cast\r
46 // (VOID **) is used.\r
47 //\r
48\r
49 *((VOID **) OutData) = InData;\r
50 } else {\r
51 CopyMem (OutData, InData, Len);\r
52 }\r
53 \r
54 return;\r
55 \r
56}\r
57\r
58UINTN\r
59GetExtendedDataOffset (\r
60 IN CONST PCD_INDEX *PcdIndex,\r
61 IN UINTN SkuIdx,\r
62 IN CONST PCD_DATABASE_HEADER *Info\r
63 )\r
64{\r
65 UINT8 *OffsetAddress;\r
66 UINTN Offset;\r
67\r
68 OffsetAddress = GetAbsoluteAddress (PcdIndex->ExtendedDataOffset, \r
69 Info->ImageIndexOffset, \r
70 Info\r
71 );\r
72\r
73 OffsetAddress += (SkuIdx * Info->ExtendedOffsetLength);\r
74\r
75\r
76 CopyMem (&Offset, OffsetAddress, Info->ExtendedOffsetLength);\r
77\r
78 return Offset;\r
79}\r
80\r
81\r
82\r
83VOID\r
84GetHiiDataProperty (\r
85 IN CONST PCD_INDEX *PcdIndex,\r
86 IN UINTN SkuIdx,\r
87 IN CONST PCD_DATABASE_HEADER *Info,\r
88 OUT EFI_GUID **VariableGuid,\r
89 OUT UINT16 **VariableName\r
90 )\r
91{\r
92 UINT16 NameOffset;\r
93 UINT16 GuidOffset;\r
94 UINT8 *HiiDataOffset;\r
95\r
96 HiiDataOffset = GetAbsoluteAddress (PcdIndex->HiiData, Info->ImageIndexOffset, Info);\r
97 HiiDataOffset += (SkuIdx * (Info->HiiGuidOffsetLength + Info->HiiVariableOffsetLength));\r
98\r
99 CopyMem (&GuidOffset, HiiDataOffset, Info->HiiGuidOffsetLength);\r
100 CopyMem (&NameOffset, HiiDataOffset + Info->HiiGuidOffsetLength, Info->HiiVariableOffsetLength);\r
101 \r
102 *VariableGuid = (EFI_GUID *) GetAbsoluteAddress (GuidOffset * sizeof (EFI_GUID), Info->GuidTableOffset, Info);\r
103 *VariableName = (UINT16 *) GetAbsoluteAddress (NameOffset * sizeof (UINT16) , Info->StringTableOffset, Info);\r
104 \r
105 return;\r
106}\r
107\r
108\r
109\r
110UINTN\r
111GetSkuIdIdx (\r
112 IN CONST PCD_INDEX *PcdIndex,\r
113 IN CONST PCD_DATABASE_HEADER *Info\r
114 )\r
115{\r
116 UINT8 *SkuIdArray;\r
117 UINTN SkuIdx;\r
118\r
119 SkuIdArray = GetAbsoluteAddress (PcdIndex->SkuIdArray, Info->ImageIndexOffset, Info);\r
120 \r
121 SkuIdx = 0;\r
122\r
123 if (PcdIndex->StateByte.SkuEnable) {\r
124\r
125 for (; SkuIdx < PcdIndex->SkuCount; SkuIdx++) {\r
126 if (SkuIdArray[SkuIdx] == Info->SkuId) {\r
127 break;\r
128 }\r
129 }\r
130\r
131 if (SkuIdx > PcdIndex->SkuCount) {\r
132 if (Info->SkuId == 0) {\r
133 //\r
134 // If no SKU_ID is set previously\r
135 // Just retrieve the first value\r
136 //\r
137 SkuIdx = 0;\r
138 } else {\r
139 //\r
140 // Just can't find the SKU_ID, ASSERT according to Spec.\r
141 //\r
142 ASSERT (FALSE);\r
143 }\r
144 }\r
145 \r
146 }\r
147\r
148 return SkuIdx;\r
149\r
150}\r
151\r
152\r
153\r
154/**\r
155 The function is the worker function to get the data of a PCD entry.\r
156\r
157 @param[in] PcdIndex The PCD Index.\r
158 @param[in] Info The attributes of the PCD database.\r
159 @param[out] Data The output data.\r
160\r
161 @retval VOID\r
162--*/\r
163UINT8*\r
164GetPcdDataPtr (\r
165 IN CONST PCD_INDEX *PcdIndex,\r
166 IN CONST PCD_DATABASE_HEADER *Info\r
167 )\r
168{\r
169 UINTN VariableDataSize;\r
170 VOID *VariableData;\r
171 UINT16 *VariableName;\r
172 UINT8 *PcdData;\r
173 EFI_GUID *VariableGuid;\r
174 EFI_STATUS Status;\r
175 UINTN SkuIdx;\r
176 UINTN ExtendedOffset;\r
177\r
178 //\r
179 // If Sku is not enalbed for this PCD Entry.\r
180 // SkuIdx 0 will be used to compute PcdData\r
181 //\r
182 SkuIdx = GetSkuIdIdx (PcdIndex, Info);\r
183\r
184 if (PcdIndex->StateByte.HiiEnable) {\r
185\r
186 GetHiiDataProperty (PcdIndex, SkuIdx, Info, &VariableGuid, &VariableName);\r
187\r
188 Status = GetHiiVariable (VariableGuid, VariableName, &VariableData, &VariableDataSize);\r
189 ASSERT_EFI_ERROR (Status);\r
190 ASSERT (VariableDataSize >= (PcdIndex->DatumSize + PcdIndex->ExtendedDataOffset));\r
191\r
192 PcdData = (UINT8 *) VariableData + PcdIndex->ExtendedDataOffset;\r
193\r
194 return PcdData;\r
195 }\r
196\r
197 //\r
198 // For VPD and Data type, we need the ExtendedOffset.\r
199 // So get it here.\r
200 //\r
201 ExtendedOffset = GetExtendedDataOffset (PcdIndex, SkuIdx, Info);\r
202\r
203 if (PcdIndex->StateByte.VpdEnable) {\r
204\r
205 PcdData = (VOID *) (Info->VpdStart + ExtendedOffset);\r
206 \r
207 return PcdData;\r
208 }\r
209\r
210 //\r
211 // For data type, we just need the pointer\r
212 //\r
213 PcdData = GetAbsoluteAddress (\r
214 ExtendedOffset,\r
215 Info->DataBufferOffset,\r
216 Info\r
217 );\r
218\r
219 return PcdData;\r
220\r
221}\r
222\r
223\r
224\r
225/**\r
226 The function locates the PCD_INDEX according to TokeNumber and GUID space given.\r
227\r
228 @param[in] TokenNumber The token number.\r
229 @param[in] Guid The GUID token space.\r
230 @param[out] Info The attributes of the PCD database.\r
231\r
232 @retval PCD_INDEX* The PCD_INDEX found.\r
233--*/\r
234PCD_INDEX *\r
235FindPcdIndex (\r
236 IN UINTN TokenNumber,\r
237 IN CONST EFI_GUID *Guid,\r
238 IN CONST PCD_DATABASE_HEADER *Info,\r
239 OUT UINTN *Index\r
240 )\r
241{\r
242 PCD_INDEX *PcdIndex;\r
243 UINTN Idx;\r
244 EFI_GUID *GuidSpace;\r
245\r
246 PcdIndex = (PCD_INDEX *) GetAbsoluteAddress (0, Info->PcdIndexOffset, Info);\r
247\r
248 for (Idx = 0; Idx < Info->EntryCount; Idx++, PcdIndex++) {\r
249 if (Index != NULL) {\r
250 *Index = Idx;\r
251 }\r
252 \r
253 if (PcdIndex->TokenNumber == TokenNumber) {\r
254 if (Guid == NULL) {\r
255 if (!PcdIndex->StateByte.ExtendedGuidPresent) {\r
256 return PcdIndex;\r
257 }\r
258 } else {\r
259 if (PcdIndex->StateByte.ExtendedGuidPresent) {\r
260 GuidSpace = (EFI_GUID *) GetAbsoluteAddress (PcdIndex->DynamicExGuid, Info->GuidTableOffset, Info);\r
261 if (CompareGuid (GuidSpace, Guid)) {\r
262 return PcdIndex;\r
263 }\r
264 }\r
265 }\r
266 }\r
267\r
268 }\r
269\r
270 if (Index != NULL) {\r
271 *Index = 0;\r
272 }\r
273 \r
274 return NULL;\r
275\r
276}\r
277\r
278\r
279\r
280/**\r
281 The function set the PCD Entry data value according to the\r
282 PCD_DATA_TYPE given.\r
283\r
284 @param[out] OutData The output data.\r
285 @param[in] InData The input data.\r
286 @param[in] Len The length of the data.\r
287\r
288\r
289 @retval EFI_SUCESS If data value is found according to SKU_ID.\r
290 @retval EFI_NOT_FOUND If not such a value is found.\r
291\r
292--*/\r
293VOID\r
294SetDataBasedOnType (\r
295 OUT VOID * OutData,\r
296 IN CONST VOID * InData,\r
297 IN UINTN Len\r
298)\r
299{\r
300 CopyMem (OutData, InData, Len);\r
301\r
302 return;\r
303}\r
304\r
305\r
306\r
307/**\r
308 The function returns the actual address of item in the PCD\r
309 database according to its Segment and Offset.\r
310\r
311 @param[out] Offset The offset within the segment.\r
312 @param[in] SegmentStart The starting address of the segment.\r
313 @param[in] DatabaseStart The base address of the PCD DataBase.\r
314\r
315\r
316 @retval UINT8* The absolute address.\r
317\r
318--*/\r
319UINT8 *\r
320GetAbsoluteAddress (\r
321 IN UINTN Offset,\r
322 IN UINTN SegmentStart,\r
323 IN CONST PCD_DATABASE_HEADER *DatabaseStart\r
324 )\r
325{\r
326 UINT8 *Address;\r
327\r
328 Address = (UINT8 *) DatabaseStart + SegmentStart + Offset;\r
329\r
330 return Address;\r
331}\r
332\r
333\r
334\r
335/**\r
336 The function retrieves the PCD data value according to\r
337 TokenNumber and Guid space given.\r
338\r
339 @param[in] Database The PCD Database Instance.\r
340 @param[in] TokenNumber The token number.\r
341 @param[in] Guid The Guid space.\r
342 @param[in] Type The storage type.\r
343 @param[out] Data The output data.\r
344\r
345 @retval VOID\r
346\r
347--*/\r
348VOID\r
349GetPcdEntryWorker (\r
350 IN CONST PCD_DATABASE_HEADER *Info,\r
351 IN UINTN TokenNumber,\r
352 IN CONST EFI_GUID *Guid, OPTIONAL\r
353 IN PCD_DATA_TYPE Type,\r
354 OUT VOID *Data\r
355 )\r
356{\r
357 PCD_INDEX *PcdIndex;\r
358 UINT8 *PcdData;\r
359\r
360 ASSERT (Data != NULL);\r
361\r
362 //\r
363 // Find the PCD entry in list in memory first\r
364 //\r
365 PcdIndex = FindPcdIndex (TokenNumber, Guid, Info, NULL);\r
366\r
367 ASSERT (PcdIndex != NULL);\r
368\r
369 ASSERT (PcdIndex->StateByte.DataType == Type);\r
370\r
371 PcdData = GetPcdDataPtr (PcdIndex, Info);\r
372\r
373 GetDataBasedOnType (PcdIndex->StateByte.DataType, PcdData, Data, PcdIndex->DatumSize);\r
374\r
375 return;\r
376}\r
377\r
378\r
379\r
380/**\r
381 The function retrieves the PCD data value according to\r
382 TokenNumber and Guid space given.\r
383\r
384 @param[in] Database The PCD Database Instance.\r
385 @param[in] TokenNumber The token number.\r
386 @param[in] Guid The Guid space.\r
387\r
388 @retval UINTN The size of the PCD Entry.\r
389\r
390--*/\r
391UINTN\r
392GetPcdEntrySizeWorker (\r
393 IN CONST PCD_DATABASE_HEADER *Info,\r
394 IN UINTN TokenNumber,\r
395 IN CONST EFI_GUID *Guid OPTIONAL\r
396 )\r
397{\r
398 PCD_INDEX *PcdIndex;\r
399\r
400 //\r
401 // Find the PCD entry in list in memory first\r
402 //\r
403 PcdIndex = FindPcdIndex (TokenNumber, Guid, Info, NULL);\r
404\r
405 ASSERT (PcdIndex != NULL);\r
406\r
407 return PcdIndex->DatumSize;\r
408\r
409}\r
410\r
411\r
412\r
413/**\r
414 The function checks if given GUID space match the record\r
415 in the PCD_INDEX.\r
416\r
417 @param[in] Guid The GUID space.\r
418 @param[in] PcdIndex The PCD_INDEX.\r
419 @param[in] Info The attribute of the PCD DATABASE.\r
420\r
421 @retval TRUE The GUID space match the record.\r
422 @retval FALSE Othewise.\r
423\r
424--*/\r
425BOOLEAN\r
426PeiImageIndexMatchGuidSpace (\r
427 IN CONST EFI_GUID *Guid,\r
428 IN CONST PCD_INDEX *PcdIndex,\r
429 IN CONST PCD_DATABASE_HEADER *Info\r
430)\r
431{\r
432 EFI_GUID *GuidSpace;\r
433\r
434 if (PcdIndex->StateByte.ExtendedGuidPresent) {\r
435 GuidSpace = (EFI_GUID *) GetAbsoluteAddress (PcdIndex->DynamicExGuid, Info->GuidTableOffset, Info);\r
436 return CompareGuid (GuidSpace, Guid);\r
437 }\r
438\r
439 return FALSE;\r
440}\r
441\r
442\r
443/**\r
444 The function looks for the next PCD ENTRY.\r
445 If *TokenNumber is 0, the first TokenNumber in\r
446 the GUID token space is return.\r
447 If there is no next TokenNumber found,\r
448 *TokenNumber will be 0.\r
449\r
450 @param[in] Database The PCD Database Instance.\r
451 @param[in,out] TokenNumber The token number.\r
452 @param[in] Guid The Guid space.\r
453\r
454 @retval EFI_NOT_FOUND Can't find the PCD_ENTRY.\r
455 @retval EFI_SUCCESS Operation succesful.\r
456\r
457--*/\r
458EFI_STATUS\r
459GetNextTokenWorker (\r
460 IN CONST PCD_DATABASE_HEADER *Info,\r
461 IN OUT UINTN *TokenNumber,\r
462 IN CONST EFI_GUID *Guid OPTIONAL\r
463 )\r
464{\r
465 PCD_INDEX *PcdIndex;\r
466 UINTN Idx;\r
467 BOOLEAN Found;\r
468\r
469 Idx = 0;\r
470 Found = FALSE;\r
471 PcdIndex = (PCD_INDEX *) GetAbsoluteAddress (0, Info->PcdIndexOffset, Info);\r
472\r
473 while ((Idx < Info->EntryCount) && !Found) {\r
474 if (*TokenNumber == 0) {\r
475 if (Guid == NULL || PeiImageIndexMatchGuidSpace (Guid, PcdIndex, Info)) {\r
476 *TokenNumber = PcdIndex->TokenNumber;\r
477 return EFI_SUCCESS;\r
478 }\r
479 } else {\r
480 if (PcdIndex->TokenNumber == *TokenNumber) {\r
481 if (Guid == NULL || PeiImageIndexMatchGuidSpace (Guid, PcdIndex, Info)) {\r
482 Found = TRUE;\r
483 }\r
484 }\r
485 }\r
486\r
487 PcdIndex++;\r
488 Idx++;\r
489 }\r
490\r
491 //\r
492 // No PCD Entry in the database match the GUID space given.\r
493 //\r
494 if (*TokenNumber == 0) {\r
495 return EFI_SUCCESS;\r
496 }\r
497\r
498 //\r
499 // Can't find the PCD Entry\r
500 //\r
501 if (!Found) {\r
502 return EFI_NOT_FOUND;\r
503 }\r
504\r
505 //\r
506 // Move to the Next Entry\r
507 //\r
508 Idx++;\r
509 PcdIndex++;\r
510\r
511 //\r
512 // Now look for the Next TokenNumber\r
513 //\r
514 while (Idx < Info->EntryCount) {\r
515 if (Guid == NULL || PeiImageIndexMatchGuidSpace (Guid, PcdIndex, Info)) {\r
516 *TokenNumber = PcdIndex->TokenNumber;\r
517 return EFI_SUCCESS;\r
518 }\r
519 PcdIndex++;\r
520 Idx++;\r
521 }\r
522\r
523 //\r
524 // Reache the last TokeNumber.\r
525 //\r
526 *TokenNumber = 0;\r
527 return EFI_SUCCESS;\r
528}\r
529\r
530\r
531/**\r
532 The function is the worker function to set the data of a PCD entry.\r
533\r
534 @param[in] PcdIndex The PCD Index.\r
535 @param[in] Info The attributes of the PCD database.\r
536 @param[in] Data The input data.\r
537\r
538 @retval VOID\r
539--*/\r
540EFI_STATUS\r
541SetPcdData (\r
542 IN CONST PCD_INDEX *PcdIndex,\r
543 IN CONST PCD_DATABASE_HEADER *Info,\r
544 IN CONST VOID *Data\r
545 )\r
546{\r
547 UINT16 *VariableName;\r
548 UINT8 *PcdData;\r
549 EFI_GUID *VariableGuid;\r
550 EFI_STATUS Status;\r
551 UINTN SkuIdx;\r
552 UINTN ExtendedOffset;\r
553\r
554 if (PcdIndex->StateByte.VpdEnable) {\r
555 ASSERT (FALSE);\r
556 return EFI_INVALID_PARAMETER;\r
557 }\r
558\r
559 SkuIdx = GetSkuIdIdx (PcdIndex, Info);\r
560\r
561 //\r
562 // For Hii and Data type, we need the ExtendedOffset.\r
563 // So get it here.\r
564 //\r
565 ExtendedOffset = GetExtendedDataOffset (PcdIndex, SkuIdx, Info);\r
566\r
567 if (PcdIndex->StateByte.HiiEnable) {\r
568 GetHiiDataProperty (PcdIndex, SkuIdx, Info, &VariableGuid, &VariableName);\r
569\r
570 Status = SetHiiVariable (VariableGuid,\r
571 VariableName,\r
572 Data,\r
573 PcdIndex->DatumSize,\r
574 ExtendedOffset\r
575 );\r
576\r
577 return Status;\r
578 }\r
579\r
580\r
581 PcdData = GetAbsoluteAddress (\r
582 ExtendedOffset,\r
583 Info->DataBufferOffset,\r
584 Info\r
585 );\r
586\r
587 CopyMem (PcdData, Data, PcdIndex->DatumSize);\r
588\r
589 return EFI_SUCCESS;\r
590\r
591}\r
592\r