/** @file Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include #include #include #include #include /** Find configuration data header by its tag and platform ID. @param[in] PidMask Platform ID mask. @param[in] Tag Configuration TAG ID to find. @param[in] IsInternal Search for internal data base only if it is non-zero. @param[in] Level Nested call level. @retval Configuration data header pointer. NULL if the tag cannot be found. **/ CDATA_HEADER * FindConfigHdrByPidMaskTag ( UINT32 PidMask, UINT32 Tag, UINT8 IsInternal, UINT32 Level ) { CDATA_BLOB *CdataBlob; CDATA_HEADER *CdataHdr; UINT8 Idx; REFERENCE_CFG_DATA *Refer; UINT32 Offset; CdataBlob = (CDATA_BLOB *) GetConfigDataPtr (); Offset = IsInternal > 0 ? (CdataBlob->InternalDataOffset * 4) : CdataBlob->HeaderLength; while (Offset < CdataBlob->UsedLength) { CdataHdr = (CDATA_HEADER *) ((UINT8 *)CdataBlob + Offset); if (CdataHdr->Tag == Tag) { for (Idx = 0; Idx < CdataHdr->ConditionNum; Idx++) { if ((PidMask & CdataHdr->Condition[Idx].Value) != 0) { // Found a match if ((CdataHdr->Flags & CDATA_FLAG_TYPE_MASK) == CDATA_FLAG_TYPE_REFER) { if (Level > 0) { // Prevent multiple level nesting return NULL; } else { Refer = (REFERENCE_CFG_DATA *) ((UINT8 *)CdataHdr + sizeof (CDATA_HEADER) + sizeof ( CDATA_COND) * CdataHdr->ConditionNum); return FindConfigHdrByPidMaskTag (PID_TO_MASK (Refer->PlatformId), \ Refer->Tag, (UINT8)Refer->IsInternal, 1); } } else { return (VOID *)CdataHdr; } } } } Offset += (CdataHdr->Length << 2); } return NULL; } /** Find configuration data header by its tag. @param[in] Tag Configuration TAG ID to find. @retval Configuration data header pointer. NULL if the tag cannot be found. **/ CDATA_HEADER * EFIAPI FindConfigHdrByTag ( UINT32 Tag ) { UINT16 PlatformId; PlatformId = GetPlatformId (); return FindConfigHdrByPidMaskTag (PID_TO_MASK (PlatformId), Tag, 0, 0); } /** Find configuration data by its tag and PlatforID. @param[in] PlatformId Platform ID. @param[in] Tag Configuration TAG ID to find. @retval Configuration data pointer. NULL if the tag cannot be found. **/ VOID * EFIAPI FindConfigDataByPidTag ( UINT16 PlatformId, UINT32 Tag ) { CDATA_HEADER *CdataHdr; VOID *Cdata; CdataHdr = FindConfigHdrByPidMaskTag (PID_TO_MASK (PlatformId), Tag, 0, 0); if (CdataHdr == NULL) { Cdata = NULL; } else { Cdata = (VOID *) ((UINT8 *)CdataHdr + sizeof (CDATA_HEADER) + sizeof (CDATA_COND) * CdataHdr->ConditionNum); } return Cdata; } /** Find configuration data by its tag. @param[in] Tag Configuration TAG ID to find. @retval Configuration data pointer. NULL if the tag cannot be found. **/ VOID * EFIAPI FindConfigDataByTag ( UINT32 Tag ) { CDATA_HEADER *CdataHdr; VOID *Cdata; CdataHdr = FindConfigHdrByTag (Tag); if (CdataHdr == NULL) { Cdata = NULL; } else { Cdata = (VOID *) ((UINT8 *)CdataHdr + sizeof (CDATA_HEADER) + sizeof (CDATA_COND) * CdataHdr->ConditionNum); } return Cdata; } /** Add new Config Data Ext/Built-In Config Data for a specific board is added to the Config Data Blob present at the CfgDataPtr in the LDR_GLOBAL_DATA. Exclude the CFG_BLOB header here as it is already there with CfgDataPtr. @param[in] CfgAddPtr Address of the CfgBlob that is to be added @retval EFI_SUCCESS if the CfgBlob is added successfully @retval EFI_UNSUPPORTED if not a valid CfgBlob @retval EFI_OUT_OF_RESOURCES if not enough memory available to add Config Data **/ EFI_STATUS EFIAPI AddConfigData ( IN UINT8 *CfgAddPtr ) { CDATA_BLOB *LdrCfgBlob; CDATA_BLOB *CfgAddBlob; INT32 CfgAddSize; LdrCfgBlob = (CDATA_BLOB *) GetConfigDataPtr (); CfgAddBlob = (CDATA_BLOB *) CfgAddPtr; if ((CfgAddBlob == NULL) || (CfgAddBlob->Signature != CFG_DATA_SIGNATURE)) { return EFI_UNSUPPORTED; } CfgAddSize = CfgAddBlob->UsedLength - (UINT32) (CfgAddBlob->HeaderLength); if (CfgAddSize < 0) { return EFI_UNSUPPORTED; } else if (CfgAddSize > (INT32) (LdrCfgBlob->TotalLength - LdrCfgBlob->UsedLength)) { return EFI_OUT_OF_RESOURCES; } if (LdrCfgBlob->InternalDataOffset == 0) { // Append new config data before internal config data is available. CopyMem ((UINT8 *)LdrCfgBlob + LdrCfgBlob->UsedLength, (UINT8 *)CfgAddBlob + CfgAddBlob->HeaderLength, CfgAddSize); } else { // // Newly added config data has high priority // so move the the old config data firstly, // then copy new config data just below header // CopyMem ((UINT8 *)LdrCfgBlob + LdrCfgBlob->HeaderLength + CfgAddSize, (UINT8 *)LdrCfgBlob + LdrCfgBlob->HeaderLength, LdrCfgBlob->UsedLength - LdrCfgBlob->HeaderLength); CopyMem ((UINT8 *)LdrCfgBlob + LdrCfgBlob->HeaderLength, (UINT8 *)CfgAddBlob + CfgAddBlob->HeaderLength, CfgAddSize); LdrCfgBlob->InternalDataOffset += (UINT16) (CfgAddSize >> 2); } LdrCfgBlob->UsedLength += CfgAddSize; return EFI_SUCCESS; } /** Get the source of the external configuration data to load. @param[in] Index Index of the source @retval PDR if external data is loaded from SPI Flash PDR region @retval BIOS if external data is loaded from SPI Flash BIOS region @retval NULL if external data is loaded from niether **/ CHAR8 * GetCfgDataSource ( IN UINT8 Index ) { if (Index == 0) { return "PDR"; } else if (Index == 1) { return "BIOS"; } else { return "NULL"; } }