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