diff options
Diffstat (limited to 'EdkModulePkg/Universal/PCD/Common/PcdCommon.c')
-rw-r--r-- | EdkModulePkg/Universal/PCD/Common/PcdCommon.c | 592 |
1 files changed, 592 insertions, 0 deletions
diff --git a/EdkModulePkg/Universal/PCD/Common/PcdCommon.c b/EdkModulePkg/Universal/PCD/Common/PcdCommon.c new file mode 100644 index 0000000000..1af93c18d8 --- /dev/null +++ b/EdkModulePkg/Universal/PCD/Common/PcdCommon.c @@ -0,0 +1,592 @@ +/** @file
+Common functions used by PCD PEIM and PCD DXE.
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+Module Name: PcdCommon.c
+
+**/
+#include "PcdCommon.h"
+
+
+
+/**
+ The function retrieves the PCD data value according to
+ the PCD_DATA_TYPE specified.
+
+ @param[in] Type The PCD_DATA_TYPE used to interpret the data.
+ @param[in] InData The input data.
+ @param[in] OutData The output data.
+ @param[in] Len The length of the data; it is mainly used for PcdPointer type.
+
+ @retval VOID
+--*/
+VOID
+GetDataBasedOnType (
+ IN PCD_DATA_TYPE Type,
+ IN VOID *InData,
+ OUT VOID *OutData,
+ IN UINTN Len
+ )
+{
+ if (Type == PcdPointer) {
+ //
+ // When the Type is PcdPointer, we are returning
+ // the address of the internal buffer kpet by
+ // PCD database. Therefore, we treat OutData as
+ // a pointer to a "VOID *". Thus, the ugly type cast
+ // (VOID **) is used.
+ //
+
+ *((VOID **) OutData) = InData;
+ } else {
+ CopyMem (OutData, InData, Len);
+ }
+
+ return;
+
+}
+
+UINTN
+GetExtendedDataOffset (
+ IN CONST PCD_INDEX *PcdIndex,
+ IN UINTN SkuIdx,
+ IN CONST PCD_DATABASE_HEADER *Info
+ )
+{
+ UINT8 *OffsetAddress;
+ UINTN Offset;
+
+ OffsetAddress = GetAbsoluteAddress (PcdIndex->ExtendedDataOffset,
+ Info->ImageIndexOffset,
+ Info
+ );
+
+ OffsetAddress += (SkuIdx * Info->ExtendedOffsetLength);
+
+
+ CopyMem (&Offset, OffsetAddress, Info->ExtendedOffsetLength);
+
+ return Offset;
+}
+
+
+
+VOID
+GetHiiDataProperty (
+ IN CONST PCD_INDEX *PcdIndex,
+ IN UINTN SkuIdx,
+ IN CONST PCD_DATABASE_HEADER *Info,
+ OUT EFI_GUID **VariableGuid,
+ OUT UINT16 **VariableName
+ )
+{
+ UINT16 NameOffset;
+ UINT16 GuidOffset;
+ UINT8 *HiiDataOffset;
+
+ HiiDataOffset = GetAbsoluteAddress (PcdIndex->HiiData, Info->ImageIndexOffset, Info);
+ HiiDataOffset += (SkuIdx * (Info->HiiGuidOffsetLength + Info->HiiVariableOffsetLength));
+
+ CopyMem (&GuidOffset, HiiDataOffset, Info->HiiGuidOffsetLength);
+ CopyMem (&NameOffset, HiiDataOffset + Info->HiiGuidOffsetLength, Info->HiiVariableOffsetLength);
+
+ *VariableGuid = (EFI_GUID *) GetAbsoluteAddress (GuidOffset * sizeof (EFI_GUID), Info->GuidTableOffset, Info);
+ *VariableName = (UINT16 *) GetAbsoluteAddress (NameOffset * sizeof (UINT16) , Info->StringTableOffset, Info);
+
+ return;
+}
+
+
+
+UINTN
+GetSkuIdIdx (
+ IN CONST PCD_INDEX *PcdIndex,
+ IN CONST PCD_DATABASE_HEADER *Info
+ )
+{
+ UINT8 *SkuIdArray;
+ UINTN SkuIdx;
+
+ SkuIdArray = GetAbsoluteAddress (PcdIndex->SkuIdArray, Info->ImageIndexOffset, Info);
+
+ SkuIdx = 0;
+
+ if (PcdIndex->StateByte.SkuEnable) {
+
+ for (; SkuIdx < PcdIndex->SkuCount; SkuIdx++) {
+ if (SkuIdArray[SkuIdx] == Info->SkuId) {
+ break;
+ }
+ }
+
+ if (SkuIdx > PcdIndex->SkuCount) {
+ if (Info->SkuId == 0) {
+ //
+ // If no SKU_ID is set previously
+ // Just retrieve the first value
+ //
+ SkuIdx = 0;
+ } else {
+ //
+ // Just can't find the SKU_ID, ASSERT according to Spec.
+ //
+ ASSERT (FALSE);
+ }
+ }
+
+ }
+
+ return SkuIdx;
+
+}
+
+
+
+/**
+ The function is the worker function to get the data of a PCD entry.
+
+ @param[in] PcdIndex The PCD Index.
+ @param[in] Info The attributes of the PCD database.
+ @param[out] Data The output data.
+
+ @retval VOID
+--*/
+UINT8*
+GetPcdDataPtr (
+ IN CONST PCD_INDEX *PcdIndex,
+ IN CONST PCD_DATABASE_HEADER *Info
+ )
+{
+ UINTN VariableDataSize;
+ VOID *VariableData;
+ UINT16 *VariableName;
+ UINT8 *PcdData;
+ EFI_GUID *VariableGuid;
+ EFI_STATUS Status;
+ UINTN SkuIdx;
+ UINTN ExtendedOffset;
+
+ //
+ // If Sku is not enalbed for this PCD Entry.
+ // SkuIdx 0 will be used to compute PcdData
+ //
+ SkuIdx = GetSkuIdIdx (PcdIndex, Info);
+
+ if (PcdIndex->StateByte.HiiEnable) {
+
+ GetHiiDataProperty (PcdIndex, SkuIdx, Info, &VariableGuid, &VariableName);
+
+ Status = GetHiiVariable (VariableGuid, VariableName, &VariableData, &VariableDataSize);
+ ASSERT_EFI_ERROR (Status);
+ ASSERT (VariableDataSize >= (PcdIndex->DatumSize + PcdIndex->ExtendedDataOffset));
+
+ PcdData = (UINT8 *) VariableData + PcdIndex->ExtendedDataOffset;
+
+ return PcdData;
+ }
+
+ //
+ // For VPD and Data type, we need the ExtendedOffset.
+ // So get it here.
+ //
+ ExtendedOffset = GetExtendedDataOffset (PcdIndex, SkuIdx, Info);
+
+ if (PcdIndex->StateByte.VpdEnable) {
+
+ PcdData = (VOID *) (Info->VpdStart + ExtendedOffset);
+
+ return PcdData;
+ }
+
+ //
+ // For data type, we just need the pointer
+ //
+ PcdData = GetAbsoluteAddress (
+ ExtendedOffset,
+ Info->DataBufferOffset,
+ Info
+ );
+
+ return PcdData;
+
+}
+
+
+
+/**
+ The function locates the PCD_INDEX according to TokeNumber and GUID space given.
+
+ @param[in] TokenNumber The token number.
+ @param[in] Guid The GUID token space.
+ @param[out] Info The attributes of the PCD database.
+
+ @retval PCD_INDEX* The PCD_INDEX found.
+--*/
+PCD_INDEX *
+FindPcdIndex (
+ IN UINTN TokenNumber,
+ IN CONST EFI_GUID *Guid,
+ IN CONST PCD_DATABASE_HEADER *Info,
+ OUT UINTN *Index
+ )
+{
+ PCD_INDEX *PcdIndex;
+ UINTN Idx;
+ EFI_GUID *GuidSpace;
+
+ PcdIndex = (PCD_INDEX *) GetAbsoluteAddress (0, Info->PcdIndexOffset, Info);
+
+ for (Idx = 0; Idx < Info->EntryCount; Idx++, PcdIndex++) {
+ if (Index != NULL) {
+ *Index = Idx;
+ }
+
+ if (PcdIndex->TokenNumber == TokenNumber) {
+ if (Guid == NULL) {
+ if (!PcdIndex->StateByte.ExtendedGuidPresent) {
+ return PcdIndex;
+ }
+ } else {
+ if (PcdIndex->StateByte.ExtendedGuidPresent) {
+ GuidSpace = (EFI_GUID *) GetAbsoluteAddress (PcdIndex->DynamicExGuid, Info->GuidTableOffset, Info);
+ if (CompareGuid (GuidSpace, Guid)) {
+ return PcdIndex;
+ }
+ }
+ }
+ }
+
+ }
+
+ if (Index != NULL) {
+ *Index = 0;
+ }
+
+ return NULL;
+
+}
+
+
+
+/**
+ The function set the PCD Entry data value according to the
+ PCD_DATA_TYPE given.
+
+ @param[out] OutData The output data.
+ @param[in] InData The input data.
+ @param[in] Len The length of the data.
+
+
+ @retval EFI_SUCESS If data value is found according to SKU_ID.
+ @retval EFI_NOT_FOUND If not such a value is found.
+
+--*/
+VOID
+SetDataBasedOnType (
+ OUT VOID * OutData,
+ IN CONST VOID * InData,
+ IN UINTN Len
+)
+{
+ CopyMem (OutData, InData, Len);
+
+ return;
+}
+
+
+
+/**
+ The function returns the actual address of item in the PCD
+ database according to its Segment and Offset.
+
+ @param[out] Offset The offset within the segment.
+ @param[in] SegmentStart The starting address of the segment.
+ @param[in] DatabaseStart The base address of the PCD DataBase.
+
+
+ @retval UINT8* The absolute address.
+
+--*/
+UINT8 *
+GetAbsoluteAddress (
+ IN UINTN Offset,
+ IN UINTN SegmentStart,
+ IN CONST PCD_DATABASE_HEADER *DatabaseStart
+ )
+{
+ UINT8 *Address;
+
+ Address = (UINT8 *) DatabaseStart + SegmentStart + Offset;
+
+ return Address;
+}
+
+
+
+/**
+ The function retrieves the PCD data value according to
+ TokenNumber and Guid space given.
+
+ @param[in] Database The PCD Database Instance.
+ @param[in] TokenNumber The token number.
+ @param[in] Guid The Guid space.
+ @param[in] Type The storage type.
+ @param[out] Data The output data.
+
+ @retval VOID
+
+--*/
+VOID
+GetPcdEntryWorker (
+ IN CONST PCD_DATABASE_HEADER *Info,
+ IN UINTN TokenNumber,
+ IN CONST EFI_GUID *Guid, OPTIONAL
+ IN PCD_DATA_TYPE Type,
+ OUT VOID *Data
+ )
+{
+ PCD_INDEX *PcdIndex;
+ UINT8 *PcdData;
+
+ ASSERT (Data != NULL);
+
+ //
+ // Find the PCD entry in list in memory first
+ //
+ PcdIndex = FindPcdIndex (TokenNumber, Guid, Info, NULL);
+
+ ASSERT (PcdIndex != NULL);
+
+ ASSERT (PcdIndex->StateByte.DataType == Type);
+
+ PcdData = GetPcdDataPtr (PcdIndex, Info);
+
+ GetDataBasedOnType (PcdIndex->StateByte.DataType, PcdData, Data, PcdIndex->DatumSize);
+
+ return;
+}
+
+
+
+/**
+ The function retrieves the PCD data value according to
+ TokenNumber and Guid space given.
+
+ @param[in] Database The PCD Database Instance.
+ @param[in] TokenNumber The token number.
+ @param[in] Guid The Guid space.
+
+ @retval UINTN The size of the PCD Entry.
+
+--*/
+UINTN
+GetPcdEntrySizeWorker (
+ IN CONST PCD_DATABASE_HEADER *Info,
+ IN UINTN TokenNumber,
+ IN CONST EFI_GUID *Guid OPTIONAL
+ )
+{
+ PCD_INDEX *PcdIndex;
+
+ //
+ // Find the PCD entry in list in memory first
+ //
+ PcdIndex = FindPcdIndex (TokenNumber, Guid, Info, NULL);
+
+ ASSERT (PcdIndex != NULL);
+
+ return PcdIndex->DatumSize;
+
+}
+
+
+
+/**
+ The function checks if given GUID space match the record
+ in the PCD_INDEX.
+
+ @param[in] Guid The GUID space.
+ @param[in] PcdIndex The PCD_INDEX.
+ @param[in] Info The attribute of the PCD DATABASE.
+
+ @retval TRUE The GUID space match the record.
+ @retval FALSE Othewise.
+
+--*/
+BOOLEAN
+PeiImageIndexMatchGuidSpace (
+ IN CONST EFI_GUID *Guid,
+ IN CONST PCD_INDEX *PcdIndex,
+ IN CONST PCD_DATABASE_HEADER *Info
+)
+{
+ EFI_GUID *GuidSpace;
+
+ if (PcdIndex->StateByte.ExtendedGuidPresent) {
+ GuidSpace = (EFI_GUID *) GetAbsoluteAddress (PcdIndex->DynamicExGuid, Info->GuidTableOffset, Info);
+ return CompareGuid (GuidSpace, Guid);
+ }
+
+ return FALSE;
+}
+
+
+/**
+ The function looks for the next PCD ENTRY.
+ If *TokenNumber is 0, the first TokenNumber in
+ the GUID token space is return.
+ If there is no next TokenNumber found,
+ *TokenNumber will be 0.
+
+ @param[in] Database The PCD Database Instance.
+ @param[in,out] TokenNumber The token number.
+ @param[in] Guid The Guid space.
+
+ @retval EFI_NOT_FOUND Can't find the PCD_ENTRY.
+ @retval EFI_SUCCESS Operation succesful.
+
+--*/
+EFI_STATUS
+GetNextTokenWorker (
+ IN CONST PCD_DATABASE_HEADER *Info,
+ IN OUT UINTN *TokenNumber,
+ IN CONST EFI_GUID *Guid OPTIONAL
+ )
+{
+ PCD_INDEX *PcdIndex;
+ UINTN Idx;
+ BOOLEAN Found;
+
+ Idx = 0;
+ Found = FALSE;
+ PcdIndex = (PCD_INDEX *) GetAbsoluteAddress (0, Info->PcdIndexOffset, Info);
+
+ while ((Idx < Info->EntryCount) && !Found) {
+ if (*TokenNumber == 0) {
+ if (Guid == NULL || PeiImageIndexMatchGuidSpace (Guid, PcdIndex, Info)) {
+ *TokenNumber = PcdIndex->TokenNumber;
+ return EFI_SUCCESS;
+ }
+ } else {
+ if (PcdIndex->TokenNumber == *TokenNumber) {
+ if (Guid == NULL || PeiImageIndexMatchGuidSpace (Guid, PcdIndex, Info)) {
+ Found = TRUE;
+ }
+ }
+ }
+
+ PcdIndex++;
+ Idx++;
+ }
+
+ //
+ // No PCD Entry in the database match the GUID space given.
+ //
+ if (*TokenNumber == 0) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Can't find the PCD Entry
+ //
+ if (!Found) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Move to the Next Entry
+ //
+ Idx++;
+ PcdIndex++;
+
+ //
+ // Now look for the Next TokenNumber
+ //
+ while (Idx < Info->EntryCount) {
+ if (Guid == NULL || PeiImageIndexMatchGuidSpace (Guid, PcdIndex, Info)) {
+ *TokenNumber = PcdIndex->TokenNumber;
+ return EFI_SUCCESS;
+ }
+ PcdIndex++;
+ Idx++;
+ }
+
+ //
+ // Reache the last TokeNumber.
+ //
+ *TokenNumber = 0;
+ return EFI_SUCCESS;
+}
+
+
+/**
+ The function is the worker function to set the data of a PCD entry.
+
+ @param[in] PcdIndex The PCD Index.
+ @param[in] Info The attributes of the PCD database.
+ @param[in] Data The input data.
+
+ @retval VOID
+--*/
+EFI_STATUS
+SetPcdData (
+ IN CONST PCD_INDEX *PcdIndex,
+ IN CONST PCD_DATABASE_HEADER *Info,
+ IN CONST VOID *Data
+ )
+{
+ UINT16 *VariableName;
+ UINT8 *PcdData;
+ EFI_GUID *VariableGuid;
+ EFI_STATUS Status;
+ UINTN SkuIdx;
+ UINTN ExtendedOffset;
+
+ if (PcdIndex->StateByte.VpdEnable) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ SkuIdx = GetSkuIdIdx (PcdIndex, Info);
+
+ //
+ // For Hii and Data type, we need the ExtendedOffset.
+ // So get it here.
+ //
+ ExtendedOffset = GetExtendedDataOffset (PcdIndex, SkuIdx, Info);
+
+ if (PcdIndex->StateByte.HiiEnable) {
+ GetHiiDataProperty (PcdIndex, SkuIdx, Info, &VariableGuid, &VariableName);
+
+ Status = SetHiiVariable (VariableGuid,
+ VariableName,
+ Data,
+ PcdIndex->DatumSize,
+ ExtendedOffset
+ );
+
+ return Status;
+ }
+
+
+ PcdData = GetAbsoluteAddress (
+ ExtendedOffset,
+ Info->DataBufferOffset,
+ Info
+ );
+
+ CopyMem (PcdData, Data, PcdIndex->DatumSize);
+
+ return EFI_SUCCESS;
+
+}
+
|