https://bugzilla.tianocore.org/show_bug.cgi?id=546 BaseTools will generate the optimized PCD database to save the image size at build time for multiple SKUs. The optimized PCD database layout will be like below, the PCD database will be composed of the full default SKU data (PCD_DATABASE_INIT) and the non-default SKU delta data(PCD_DATABASE_SKU_DELTA). PCD driver will build HOB to store the full default SKU data, and patch HOB data based on non-default SKU delta data for the SKU set by SetSku(), it can save memory resource at boot time. // // PCD database layout: // +---------------------------------+ // | PCD_DATABASE_INIT (DEFAULT SKU) | // +---------------------------------+ // | PCD_DATABASE_SKU_DELTA (SKU A) | // +---------------------------------+ // | PCD_DATABASE_SKU_DELTA (SKU B) | // +---------------------------------+ // | ...... | // +---------------------------------+ // BaseTools, PCD database and driver updates are needed for this proposal. For single SKU (default) case, this proposal is expected to have no impact. For multi-SKU case, PCD database format will be changed. So, PcdDataBase Version is also updated from 6 to 7. Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Feng Bob C <bob.c.feng@intel.com> Reviewed-by: Liming Gao <liming.gao@intel.com>
1951 lines
97 KiB
Python
1951 lines
97 KiB
Python
## @file
|
|
# This file is used to create a database used by build tool
|
|
#
|
|
# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
|
|
# (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
|
|
# 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.
|
|
#
|
|
|
|
## Platform build information from DSC file
|
|
#
|
|
# This class is used to retrieve information stored in database and convert them
|
|
# into PlatformBuildClassObject form for easier use for AutoGen.
|
|
#
|
|
from Common.String import *
|
|
from Common.DataType import *
|
|
from Common.Misc import *
|
|
from types import *
|
|
|
|
from CommonDataClass.CommonClass import SkuInfoClass
|
|
|
|
from MetaDataTable import *
|
|
from MetaFileTable import *
|
|
from MetaFileParser import *
|
|
|
|
from WorkspaceCommon import GetDeclaredPcd
|
|
from Common.Misc import AnalyzeDscPcd
|
|
from Common.Misc import ProcessDuplicatedInf
|
|
import re
|
|
from Common.Parsing import IsValidWord
|
|
from Common.VariableAttributes import VariableAttributes
|
|
import Common.GlobalData as GlobalData
|
|
import subprocess
|
|
from Workspace.BuildClassObject import PlatformBuildClassObject, StructurePcd, PcdClassObject, ModuleBuildClassObject
|
|
|
|
#
|
|
# Treat CHAR16 as a synonym for UINT16. CHAR16 support is required for VFR C structs
|
|
#
|
|
PcdValueInitName = 'PcdValueInit'
|
|
PcdSupportedBaseTypes = ['BOOLEAN', 'UINT8', 'UINT16', 'UINT32', 'UINT64', 'CHAR16']
|
|
PcdSupportedBaseTypeWidth = {'BOOLEAN':8, 'UINT8':8, 'UINT16':16, 'UINT32':32, 'UINT64':64}
|
|
PcdUnsupportedBaseTypes = ['INT8', 'INT16', 'INT32', 'INT64', 'CHAR8', 'UINTN', 'INTN', 'VOID']
|
|
|
|
PcdMainCHeader = '''
|
|
/**
|
|
DO NOT EDIT
|
|
FILE auto-generated
|
|
**/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <PcdValueCommon.h>
|
|
'''
|
|
|
|
PcdMainCEntry = '''
|
|
int
|
|
main (
|
|
int argc,
|
|
char *argv[]
|
|
)
|
|
{
|
|
return PcdValueMain (argc, argv);
|
|
}
|
|
'''
|
|
|
|
PcdMakefileHeader = '''
|
|
#
|
|
# DO NOT EDIT
|
|
# This file is auto-generated by build utility
|
|
#
|
|
|
|
'''
|
|
|
|
PcdMakefileEnd = '''
|
|
!INCLUDE $(BASE_TOOLS_PATH)\Source\C\Makefiles\ms.common
|
|
|
|
CFLAGS = $(CFLAGS) /wd4200 /wd4034 /wd4101
|
|
|
|
LIBS = $(LIB_PATH)\Common.lib
|
|
|
|
!INCLUDE $(BASE_TOOLS_PATH)\Source\C\Makefiles\ms.app
|
|
'''
|
|
|
|
PcdGccMakefile = '''
|
|
ARCH ?= IA32
|
|
MAKEROOT ?= $(EDK_TOOLS_PATH)/Source/C
|
|
LIBS = -lCommon
|
|
'''
|
|
|
|
class DscBuildData(PlatformBuildClassObject):
|
|
# dict used to convert PCD type in database to string used by build tool
|
|
_PCD_TYPE_STRING_ = {
|
|
MODEL_PCD_FIXED_AT_BUILD : "FixedAtBuild",
|
|
MODEL_PCD_PATCHABLE_IN_MODULE : "PatchableInModule",
|
|
MODEL_PCD_FEATURE_FLAG : "FeatureFlag",
|
|
MODEL_PCD_DYNAMIC : "Dynamic",
|
|
MODEL_PCD_DYNAMIC_DEFAULT : "Dynamic",
|
|
MODEL_PCD_DYNAMIC_HII : "DynamicHii",
|
|
MODEL_PCD_DYNAMIC_VPD : "DynamicVpd",
|
|
MODEL_PCD_DYNAMIC_EX : "DynamicEx",
|
|
MODEL_PCD_DYNAMIC_EX_DEFAULT : "DynamicEx",
|
|
MODEL_PCD_DYNAMIC_EX_HII : "DynamicExHii",
|
|
MODEL_PCD_DYNAMIC_EX_VPD : "DynamicExVpd",
|
|
}
|
|
|
|
# dict used to convert part of [Defines] to members of DscBuildData directly
|
|
_PROPERTY_ = {
|
|
#
|
|
# Required Fields
|
|
#
|
|
TAB_DSC_DEFINES_PLATFORM_NAME : "_PlatformName",
|
|
TAB_DSC_DEFINES_PLATFORM_GUID : "_Guid",
|
|
TAB_DSC_DEFINES_PLATFORM_VERSION : "_Version",
|
|
TAB_DSC_DEFINES_DSC_SPECIFICATION : "_DscSpecification",
|
|
# TAB_DSC_DEFINES_OUTPUT_DIRECTORY : "_OutputDirectory",
|
|
# TAB_DSC_DEFINES_SUPPORTED_ARCHITECTURES : "_SupArchList",
|
|
# TAB_DSC_DEFINES_BUILD_TARGETS : "_BuildTargets",
|
|
TAB_DSC_DEFINES_SKUID_IDENTIFIER : "_SkuName",
|
|
# TAB_DSC_DEFINES_FLASH_DEFINITION : "_FlashDefinition",
|
|
TAB_DSC_DEFINES_BUILD_NUMBER : "_BuildNumber",
|
|
TAB_DSC_DEFINES_MAKEFILE_NAME : "_MakefileName",
|
|
TAB_DSC_DEFINES_BS_BASE_ADDRESS : "_BsBaseAddress",
|
|
TAB_DSC_DEFINES_RT_BASE_ADDRESS : "_RtBaseAddress",
|
|
# TAB_DSC_DEFINES_RFC_LANGUAGES : "_RFCLanguages",
|
|
# TAB_DSC_DEFINES_ISO_LANGUAGES : "_ISOLanguages",
|
|
}
|
|
|
|
# used to compose dummy library class name for those forced library instances
|
|
_NullLibraryNumber = 0
|
|
|
|
## Constructor of DscBuildData
|
|
#
|
|
# Initialize object of DscBuildData
|
|
#
|
|
# @param FilePath The path of platform description file
|
|
# @param RawData The raw data of DSC file
|
|
# @param BuildDataBase Database used to retrieve module/package information
|
|
# @param Arch The target architecture
|
|
# @param Platform (not used for DscBuildData)
|
|
# @param Macros Macros used for replacement in DSC file
|
|
#
|
|
def __init__(self, FilePath, RawData, BuildDataBase, Arch='COMMON', Target=None, Toolchain=None):
|
|
self.MetaFile = FilePath
|
|
self._RawData = RawData
|
|
self._Bdb = BuildDataBase
|
|
self._Arch = Arch
|
|
self._Target = Target
|
|
self._Toolchain = Toolchain
|
|
self._Clear()
|
|
self._HandleOverridePath()
|
|
if os.getenv("WORKSPACE"):
|
|
self.OutputPath = os.path.join(os.getenv("WORKSPACE"), 'Build', PcdValueInitName)
|
|
else:
|
|
self.OutputPath = os.path.dirname(self.DscFile)
|
|
self.DefaultStores = None
|
|
self.SkuIdMgr = SkuClass(self.SkuIdentifier, self.SkuIds)
|
|
arraystr = self.SkuIdMgr.DumpSkuIdArrary()
|
|
|
|
## XXX[key] = value
|
|
def __setitem__(self, key, value):
|
|
self.__dict__[self._PROPERTY_[key]] = value
|
|
|
|
## value = XXX[key]
|
|
def __getitem__(self, key):
|
|
return self.__dict__[self._PROPERTY_[key]]
|
|
|
|
## "in" test support
|
|
def __contains__(self, key):
|
|
return key in self._PROPERTY_
|
|
|
|
## Set all internal used members of DscBuildData to None
|
|
def _Clear(self):
|
|
self._Header = None
|
|
self._PlatformName = None
|
|
self._Guid = None
|
|
self._Version = None
|
|
self._DscSpecification = None
|
|
self._OutputDirectory = None
|
|
self._SupArchList = None
|
|
self._BuildTargets = None
|
|
self._SkuName = None
|
|
self._SkuIdentifier = None
|
|
self._AvilableSkuIds = None
|
|
self._PcdInfoFlag = None
|
|
self._VarCheckFlag = None
|
|
self._FlashDefinition = None
|
|
self._Prebuild = None
|
|
self._Postbuild = None
|
|
self._BuildNumber = None
|
|
self._MakefileName = None
|
|
self._BsBaseAddress = None
|
|
self._RtBaseAddress = None
|
|
self._SkuIds = None
|
|
self._Modules = None
|
|
self._LibraryInstances = None
|
|
self._LibraryClasses = None
|
|
self._Pcds = None
|
|
self._DecPcds = None
|
|
self._BuildOptions = None
|
|
self._ModuleTypeOptions = None
|
|
self._LoadFixAddress = None
|
|
self._RFCLanguages = None
|
|
self._ISOLanguages = None
|
|
self._VpdToolGuid = None
|
|
self.__Macros = None
|
|
self.DefaultStores = None
|
|
|
|
|
|
## handle Override Path of Module
|
|
def _HandleOverridePath(self):
|
|
RecordList = self._RawData[MODEL_META_DATA_COMPONENT, self._Arch]
|
|
Macros = self._Macros
|
|
Macros["EDK_SOURCE"] = GlobalData.gEcpSource
|
|
for Record in RecordList:
|
|
ModuleId = Record[6]
|
|
LineNo = Record[7]
|
|
ModuleFile = PathClass(NormPath(Record[0]), GlobalData.gWorkspace, Arch=self._Arch)
|
|
RecordList = self._RawData[MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH, self._Arch, None, ModuleId]
|
|
if RecordList != []:
|
|
SourceOverridePath = mws.join(GlobalData.gWorkspace, NormPath(RecordList[0][0]))
|
|
|
|
# Check if the source override path exists
|
|
if not os.path.isdir(SourceOverridePath):
|
|
EdkLogger.error('build', FILE_NOT_FOUND, Message='Source override path does not exist:', File=self.MetaFile, ExtraData=SourceOverridePath, Line=LineNo)
|
|
|
|
# Add to GlobalData Variables
|
|
GlobalData.gOverrideDir[ModuleFile.Key] = SourceOverridePath
|
|
|
|
## Get current effective macros
|
|
def _GetMacros(self):
|
|
if self.__Macros == None:
|
|
self.__Macros = {}
|
|
self.__Macros.update(GlobalData.gPlatformDefines)
|
|
self.__Macros.update(GlobalData.gGlobalDefines)
|
|
self.__Macros.update(GlobalData.gCommandLineDefines)
|
|
return self.__Macros
|
|
|
|
## Get architecture
|
|
def _GetArch(self):
|
|
return self._Arch
|
|
|
|
## Set architecture
|
|
#
|
|
# Changing the default ARCH to another may affect all other information
|
|
# because all information in a platform may be ARCH-related. That's
|
|
# why we need to clear all internal used members, in order to cause all
|
|
# information to be re-retrieved.
|
|
#
|
|
# @param Value The value of ARCH
|
|
#
|
|
def _SetArch(self, Value):
|
|
if self._Arch == Value:
|
|
return
|
|
self._Arch = Value
|
|
self._Clear()
|
|
|
|
## Retrieve all information in [Defines] section
|
|
#
|
|
# (Retriving all [Defines] information in one-shot is just to save time.)
|
|
#
|
|
def _GetHeaderInfo(self):
|
|
RecordList = self._RawData[MODEL_META_DATA_HEADER, self._Arch]
|
|
for Record in RecordList:
|
|
Name = Record[1]
|
|
# items defined _PROPERTY_ don't need additional processing
|
|
|
|
# some special items in [Defines] section need special treatment
|
|
if Name == TAB_DSC_DEFINES_OUTPUT_DIRECTORY:
|
|
self._OutputDirectory = NormPath(Record[2], self._Macros)
|
|
if ' ' in self._OutputDirectory:
|
|
EdkLogger.error("build", FORMAT_NOT_SUPPORTED, "No space is allowed in OUTPUT_DIRECTORY",
|
|
File=self.MetaFile, Line=Record[-1],
|
|
ExtraData=self._OutputDirectory)
|
|
elif Name == TAB_DSC_DEFINES_FLASH_DEFINITION:
|
|
self._FlashDefinition = PathClass(NormPath(Record[2], self._Macros), GlobalData.gWorkspace)
|
|
ErrorCode, ErrorInfo = self._FlashDefinition.Validate('.fdf')
|
|
if ErrorCode != 0:
|
|
EdkLogger.error('build', ErrorCode, File=self.MetaFile, Line=Record[-1],
|
|
ExtraData=ErrorInfo)
|
|
elif Name == TAB_DSC_PREBUILD:
|
|
PrebuildValue = Record[2]
|
|
if Record[2][0] == '"':
|
|
if Record[2][-1] != '"':
|
|
EdkLogger.error('build', FORMAT_INVALID, 'Missing double quotes in the end of %s statement.' % TAB_DSC_PREBUILD,
|
|
File=self.MetaFile, Line=Record[-1])
|
|
PrebuildValue = Record[2][1:-1]
|
|
self._Prebuild = PrebuildValue
|
|
elif Name == TAB_DSC_POSTBUILD:
|
|
PostbuildValue = Record[2]
|
|
if Record[2][0] == '"':
|
|
if Record[2][-1] != '"':
|
|
EdkLogger.error('build', FORMAT_INVALID, 'Missing double quotes in the end of %s statement.' % TAB_DSC_POSTBUILD,
|
|
File=self.MetaFile, Line=Record[-1])
|
|
PostbuildValue = Record[2][1:-1]
|
|
self._Postbuild = PostbuildValue
|
|
elif Name == TAB_DSC_DEFINES_SUPPORTED_ARCHITECTURES:
|
|
self._SupArchList = GetSplitValueList(Record[2], TAB_VALUE_SPLIT)
|
|
elif Name == TAB_DSC_DEFINES_BUILD_TARGETS:
|
|
self._BuildTargets = GetSplitValueList(Record[2])
|
|
elif Name == TAB_DSC_DEFINES_SKUID_IDENTIFIER:
|
|
if self._SkuName == None:
|
|
self._SkuName = Record[2]
|
|
self._SkuIdentifier = Record[2]
|
|
self._AvilableSkuIds = Record[2]
|
|
elif Name == TAB_DSC_DEFINES_PCD_INFO_GENERATION:
|
|
self._PcdInfoFlag = Record[2]
|
|
elif Name == TAB_DSC_DEFINES_PCD_VAR_CHECK_GENERATION:
|
|
self._VarCheckFlag = Record[2]
|
|
elif Name == TAB_FIX_LOAD_TOP_MEMORY_ADDRESS:
|
|
try:
|
|
self._LoadFixAddress = int (Record[2], 0)
|
|
except:
|
|
EdkLogger.error("build", PARAMETER_INVALID, "FIX_LOAD_TOP_MEMORY_ADDRESS %s is not valid dec or hex string" % (Record[2]))
|
|
elif Name == TAB_DSC_DEFINES_RFC_LANGUAGES:
|
|
if not Record[2] or Record[2][0] != '"' or Record[2][-1] != '"' or len(Record[2]) == 1:
|
|
EdkLogger.error('build', FORMAT_NOT_SUPPORTED, 'language code for RFC_LANGUAGES must have double quotes around it, for example: RFC_LANGUAGES = "en-us;zh-hans"',
|
|
File=self.MetaFile, Line=Record[-1])
|
|
LanguageCodes = Record[2][1:-1]
|
|
if not LanguageCodes:
|
|
EdkLogger.error('build', FORMAT_NOT_SUPPORTED, 'one or more RFC4646 format language code must be provided for RFC_LANGUAGES statement',
|
|
File=self.MetaFile, Line=Record[-1])
|
|
LanguageList = GetSplitValueList(LanguageCodes, TAB_SEMI_COLON_SPLIT)
|
|
# check whether there is empty entries in the list
|
|
if None in LanguageList:
|
|
EdkLogger.error('build', FORMAT_NOT_SUPPORTED, 'one or more empty language code is in RFC_LANGUAGES statement',
|
|
File=self.MetaFile, Line=Record[-1])
|
|
self._RFCLanguages = LanguageList
|
|
elif Name == TAB_DSC_DEFINES_ISO_LANGUAGES:
|
|
if not Record[2] or Record[2][0] != '"' or Record[2][-1] != '"' or len(Record[2]) == 1:
|
|
EdkLogger.error('build', FORMAT_NOT_SUPPORTED, 'language code for ISO_LANGUAGES must have double quotes around it, for example: ISO_LANGUAGES = "engchn"',
|
|
File=self.MetaFile, Line=Record[-1])
|
|
LanguageCodes = Record[2][1:-1]
|
|
if not LanguageCodes:
|
|
EdkLogger.error('build', FORMAT_NOT_SUPPORTED, 'one or more ISO639-2 format language code must be provided for ISO_LANGUAGES statement',
|
|
File=self.MetaFile, Line=Record[-1])
|
|
if len(LanguageCodes) % 3:
|
|
EdkLogger.error('build', FORMAT_NOT_SUPPORTED, 'bad ISO639-2 format for ISO_LANGUAGES',
|
|
File=self.MetaFile, Line=Record[-1])
|
|
LanguageList = []
|
|
for i in range(0, len(LanguageCodes), 3):
|
|
LanguageList.append(LanguageCodes[i:i + 3])
|
|
self._ISOLanguages = LanguageList
|
|
elif Name == TAB_DSC_DEFINES_VPD_TOOL_GUID:
|
|
#
|
|
# try to convert GUID to a real UUID value to see whether the GUID is format
|
|
# for VPD_TOOL_GUID is correct.
|
|
#
|
|
try:
|
|
uuid.UUID(Record[2])
|
|
except:
|
|
EdkLogger.error("build", FORMAT_INVALID, "Invalid GUID format for VPD_TOOL_GUID", File=self.MetaFile)
|
|
self._VpdToolGuid = Record[2]
|
|
elif Name in self:
|
|
self[Name] = Record[2]
|
|
# set _Header to non-None in order to avoid database re-querying
|
|
self._Header = 'DUMMY'
|
|
|
|
## Retrieve platform name
|
|
def _GetPlatformName(self):
|
|
if self._PlatformName == None:
|
|
if self._Header == None:
|
|
self._GetHeaderInfo()
|
|
if self._PlatformName == None:
|
|
EdkLogger.error('build', ATTRIBUTE_NOT_AVAILABLE, "No PLATFORM_NAME", File=self.MetaFile)
|
|
return self._PlatformName
|
|
|
|
## Retrieve file guid
|
|
def _GetFileGuid(self):
|
|
if self._Guid == None:
|
|
if self._Header == None:
|
|
self._GetHeaderInfo()
|
|
if self._Guid == None:
|
|
EdkLogger.error('build', ATTRIBUTE_NOT_AVAILABLE, "No PLATFORM_GUID", File=self.MetaFile)
|
|
return self._Guid
|
|
|
|
## Retrieve platform version
|
|
def _GetVersion(self):
|
|
if self._Version == None:
|
|
if self._Header == None:
|
|
self._GetHeaderInfo()
|
|
if self._Version == None:
|
|
EdkLogger.error('build', ATTRIBUTE_NOT_AVAILABLE, "No PLATFORM_VERSION", File=self.MetaFile)
|
|
return self._Version
|
|
|
|
## Retrieve platform description file version
|
|
def _GetDscSpec(self):
|
|
if self._DscSpecification == None:
|
|
if self._Header == None:
|
|
self._GetHeaderInfo()
|
|
if self._DscSpecification == None:
|
|
EdkLogger.error('build', ATTRIBUTE_NOT_AVAILABLE, "No DSC_SPECIFICATION", File=self.MetaFile)
|
|
return self._DscSpecification
|
|
|
|
## Retrieve OUTPUT_DIRECTORY
|
|
def _GetOutpuDir(self):
|
|
if self._OutputDirectory == None:
|
|
if self._Header == None:
|
|
self._GetHeaderInfo()
|
|
if self._OutputDirectory == None:
|
|
self._OutputDirectory = os.path.join("Build", self._PlatformName)
|
|
return self._OutputDirectory
|
|
|
|
## Retrieve SUPPORTED_ARCHITECTURES
|
|
def _GetSupArch(self):
|
|
if self._SupArchList == None:
|
|
if self._Header == None:
|
|
self._GetHeaderInfo()
|
|
if self._SupArchList == None:
|
|
EdkLogger.error('build', ATTRIBUTE_NOT_AVAILABLE, "No SUPPORTED_ARCHITECTURES", File=self.MetaFile)
|
|
return self._SupArchList
|
|
|
|
## Retrieve BUILD_TARGETS
|
|
def _GetBuildTarget(self):
|
|
if self._BuildTargets == None:
|
|
if self._Header == None:
|
|
self._GetHeaderInfo()
|
|
if self._BuildTargets == None:
|
|
EdkLogger.error('build', ATTRIBUTE_NOT_AVAILABLE, "No BUILD_TARGETS", File=self.MetaFile)
|
|
return self._BuildTargets
|
|
|
|
def _GetPcdInfoFlag(self):
|
|
if self._PcdInfoFlag == None or self._PcdInfoFlag.upper() == 'FALSE':
|
|
return False
|
|
elif self._PcdInfoFlag.upper() == 'TRUE':
|
|
return True
|
|
else:
|
|
return False
|
|
def _GetVarCheckFlag(self):
|
|
if self._VarCheckFlag == None or self._VarCheckFlag.upper() == 'FALSE':
|
|
return False
|
|
elif self._VarCheckFlag.upper() == 'TRUE':
|
|
return True
|
|
else:
|
|
return False
|
|
def _GetAviableSkuIds(self):
|
|
if self._AvilableSkuIds:
|
|
return self._AvilableSkuIds
|
|
return self.SkuIdentifier
|
|
def _GetSkuIdentifier(self):
|
|
if self._SkuName:
|
|
return self._SkuName
|
|
if self._SkuIdentifier == None:
|
|
if self._Header == None:
|
|
self._GetHeaderInfo()
|
|
return self._SkuIdentifier
|
|
## Retrieve SKUID_IDENTIFIER
|
|
def _GetSkuName(self):
|
|
if self._SkuName == None:
|
|
if self._Header == None:
|
|
self._GetHeaderInfo()
|
|
if (self._SkuName == None or self._SkuName not in self.SkuIds):
|
|
self._SkuName = 'DEFAULT'
|
|
return self._SkuName
|
|
|
|
## Override SKUID_IDENTIFIER
|
|
def _SetSkuName(self, Value):
|
|
self._SkuName = Value
|
|
self._Pcds = None
|
|
|
|
def _GetFdfFile(self):
|
|
if self._FlashDefinition == None:
|
|
if self._Header == None:
|
|
self._GetHeaderInfo()
|
|
if self._FlashDefinition == None:
|
|
self._FlashDefinition = ''
|
|
return self._FlashDefinition
|
|
|
|
def _GetPrebuild(self):
|
|
if self._Prebuild == None:
|
|
if self._Header == None:
|
|
self._GetHeaderInfo()
|
|
if self._Prebuild == None:
|
|
self._Prebuild = ''
|
|
return self._Prebuild
|
|
|
|
def _GetPostbuild(self):
|
|
if self._Postbuild == None:
|
|
if self._Header == None:
|
|
self._GetHeaderInfo()
|
|
if self._Postbuild == None:
|
|
self._Postbuild = ''
|
|
return self._Postbuild
|
|
|
|
## Retrieve FLASH_DEFINITION
|
|
def _GetBuildNumber(self):
|
|
if self._BuildNumber == None:
|
|
if self._Header == None:
|
|
self._GetHeaderInfo()
|
|
if self._BuildNumber == None:
|
|
self._BuildNumber = ''
|
|
return self._BuildNumber
|
|
|
|
## Retrieve MAKEFILE_NAME
|
|
def _GetMakefileName(self):
|
|
if self._MakefileName == None:
|
|
if self._Header == None:
|
|
self._GetHeaderInfo()
|
|
if self._MakefileName == None:
|
|
self._MakefileName = ''
|
|
return self._MakefileName
|
|
|
|
## Retrieve BsBaseAddress
|
|
def _GetBsBaseAddress(self):
|
|
if self._BsBaseAddress == None:
|
|
if self._Header == None:
|
|
self._GetHeaderInfo()
|
|
if self._BsBaseAddress == None:
|
|
self._BsBaseAddress = ''
|
|
return self._BsBaseAddress
|
|
|
|
## Retrieve RtBaseAddress
|
|
def _GetRtBaseAddress(self):
|
|
if self._RtBaseAddress == None:
|
|
if self._Header == None:
|
|
self._GetHeaderInfo()
|
|
if self._RtBaseAddress == None:
|
|
self._RtBaseAddress = ''
|
|
return self._RtBaseAddress
|
|
|
|
## Retrieve the top address for the load fix address
|
|
def _GetLoadFixAddress(self):
|
|
if self._LoadFixAddress == None:
|
|
if self._Header == None:
|
|
self._GetHeaderInfo()
|
|
|
|
if self._LoadFixAddress == None:
|
|
self._LoadFixAddress = self._Macros.get(TAB_FIX_LOAD_TOP_MEMORY_ADDRESS, '0')
|
|
|
|
try:
|
|
self._LoadFixAddress = int (self._LoadFixAddress, 0)
|
|
except:
|
|
EdkLogger.error("build", PARAMETER_INVALID, "FIX_LOAD_TOP_MEMORY_ADDRESS %s is not valid dec or hex string" % (self._LoadFixAddress))
|
|
|
|
#
|
|
# If command line defined, should override the value in DSC file.
|
|
#
|
|
if 'FIX_LOAD_TOP_MEMORY_ADDRESS' in GlobalData.gCommandLineDefines.keys():
|
|
try:
|
|
self._LoadFixAddress = int(GlobalData.gCommandLineDefines['FIX_LOAD_TOP_MEMORY_ADDRESS'], 0)
|
|
except:
|
|
EdkLogger.error("build", PARAMETER_INVALID, "FIX_LOAD_TOP_MEMORY_ADDRESS %s is not valid dec or hex string" % (GlobalData.gCommandLineDefines['FIX_LOAD_TOP_MEMORY_ADDRESS']))
|
|
|
|
if self._LoadFixAddress < 0:
|
|
EdkLogger.error("build", PARAMETER_INVALID, "FIX_LOAD_TOP_MEMORY_ADDRESS is set to the invalid negative value 0x%x" % (self._LoadFixAddress))
|
|
if self._LoadFixAddress != 0xFFFFFFFFFFFFFFFF and self._LoadFixAddress % 0x1000 != 0:
|
|
EdkLogger.error("build", PARAMETER_INVALID, "FIX_LOAD_TOP_MEMORY_ADDRESS is set to the invalid unaligned 4K value 0x%x" % (self._LoadFixAddress))
|
|
|
|
return self._LoadFixAddress
|
|
|
|
## Retrieve RFCLanguage filter
|
|
def _GetRFCLanguages(self):
|
|
if self._RFCLanguages == None:
|
|
if self._Header == None:
|
|
self._GetHeaderInfo()
|
|
if self._RFCLanguages == None:
|
|
self._RFCLanguages = []
|
|
return self._RFCLanguages
|
|
|
|
## Retrieve ISOLanguage filter
|
|
def _GetISOLanguages(self):
|
|
if self._ISOLanguages == None:
|
|
if self._Header == None:
|
|
self._GetHeaderInfo()
|
|
if self._ISOLanguages == None:
|
|
self._ISOLanguages = []
|
|
return self._ISOLanguages
|
|
## Retrieve the GUID string for VPD tool
|
|
def _GetVpdToolGuid(self):
|
|
if self._VpdToolGuid == None:
|
|
if self._Header == None:
|
|
self._GetHeaderInfo()
|
|
if self._VpdToolGuid == None:
|
|
self._VpdToolGuid = ''
|
|
return self._VpdToolGuid
|
|
|
|
## Retrieve [SkuIds] section information
|
|
def _GetSkuIds(self):
|
|
if self._SkuIds == None:
|
|
self._SkuIds = sdict()
|
|
RecordList = self._RawData[MODEL_EFI_SKU_ID, self._Arch]
|
|
for Record in RecordList:
|
|
if Record[0] in [None, '']:
|
|
EdkLogger.error('build', FORMAT_INVALID, 'No Sku ID number',
|
|
File=self.MetaFile, Line=Record[-1])
|
|
if Record[1] in [None, '']:
|
|
EdkLogger.error('build', FORMAT_INVALID, 'No Sku ID name',
|
|
File=self.MetaFile, Line=Record[-1])
|
|
Pattern = re.compile('^[1-9]\d*|0$')
|
|
if Pattern.match(Record[0]) == None:
|
|
EdkLogger.error('build', FORMAT_INVALID, "The format of the Sku ID number is invalid. The correct format is '{(0-9)} {(1-9)(0-9)+}'",
|
|
File=self.MetaFile, Line=Record[-1])
|
|
if not IsValidWord(Record[1]):
|
|
EdkLogger.error('build', FORMAT_INVALID, "The format of the Sku ID name is invalid. The correct format is '(a-zA-Z0-9_)(a-zA-Z0-9_-.)*'",
|
|
File=self.MetaFile, Line=Record[-1])
|
|
self._SkuIds[Record[1].upper()] = (Record[0], Record[1].upper(), Record[2].upper())
|
|
if 'DEFAULT' not in self._SkuIds:
|
|
self._SkuIds['DEFAULT'] = ("0","DEFAULT","DEFAULT")
|
|
if 'COMMON' not in self._SkuIds:
|
|
self._SkuIds['COMMON'] = ("0","DEFAULT","DEFAULT")
|
|
return self._SkuIds
|
|
def ToInt(self,intstr):
|
|
return int(intstr,16) if intstr.upper().startswith("0X") else int(intstr)
|
|
def _GetDefaultStores(self):
|
|
if self.DefaultStores == None:
|
|
self.DefaultStores = sdict()
|
|
RecordList = self._RawData[MODEL_EFI_DEFAULT_STORES, self._Arch]
|
|
for Record in RecordList:
|
|
if Record[0] in [None, '']:
|
|
EdkLogger.error('build', FORMAT_INVALID, 'No DefaultStores ID number',
|
|
File=self.MetaFile, Line=Record[-1])
|
|
if Record[1] in [None, '']:
|
|
EdkLogger.error('build', FORMAT_INVALID, 'No DefaultStores ID name',
|
|
File=self.MetaFile, Line=Record[-1])
|
|
self.DefaultStores[Record[1].upper()] = (self.ToInt(Record[0]),Record[1].upper())
|
|
if TAB_DEFAULT_STORES_DEFAULT not in self.DefaultStores:
|
|
self.DefaultStores[TAB_DEFAULT_STORES_DEFAULT] = (0,TAB_DEFAULT_STORES_DEFAULT)
|
|
return self.DefaultStores
|
|
|
|
## Retrieve [Components] section information
|
|
def _GetModules(self):
|
|
if self._Modules != None:
|
|
return self._Modules
|
|
|
|
self._Modules = sdict()
|
|
RecordList = self._RawData[MODEL_META_DATA_COMPONENT, self._Arch]
|
|
Macros = self._Macros
|
|
Macros["EDK_SOURCE"] = GlobalData.gEcpSource
|
|
for Record in RecordList:
|
|
DuplicatedFile = False
|
|
|
|
ModuleFile = PathClass(NormPath(Record[0], Macros), GlobalData.gWorkspace, Arch=self._Arch)
|
|
ModuleId = Record[6]
|
|
LineNo = Record[7]
|
|
|
|
# check the file validation
|
|
ErrorCode, ErrorInfo = ModuleFile.Validate('.inf')
|
|
if ErrorCode != 0:
|
|
EdkLogger.error('build', ErrorCode, File=self.MetaFile, Line=LineNo,
|
|
ExtraData=ErrorInfo)
|
|
# Check duplication
|
|
# If arch is COMMON, no duplicate module is checked since all modules in all component sections are selected
|
|
if self._Arch != 'COMMON' and ModuleFile in self._Modules:
|
|
DuplicatedFile = True
|
|
|
|
Module = ModuleBuildClassObject()
|
|
Module.MetaFile = ModuleFile
|
|
|
|
# get module private library instance
|
|
RecordList = self._RawData[MODEL_EFI_LIBRARY_CLASS, self._Arch, None, ModuleId]
|
|
for Record in RecordList:
|
|
LibraryClass = Record[0]
|
|
LibraryPath = PathClass(NormPath(Record[1], Macros), GlobalData.gWorkspace, Arch=self._Arch)
|
|
LineNo = Record[-1]
|
|
|
|
# check the file validation
|
|
ErrorCode, ErrorInfo = LibraryPath.Validate('.inf')
|
|
if ErrorCode != 0:
|
|
EdkLogger.error('build', ErrorCode, File=self.MetaFile, Line=LineNo,
|
|
ExtraData=ErrorInfo)
|
|
|
|
if LibraryClass == '' or LibraryClass == 'NULL':
|
|
self._NullLibraryNumber += 1
|
|
LibraryClass = 'NULL%d' % self._NullLibraryNumber
|
|
EdkLogger.verbose("Found forced library for %s\n\t%s [%s]" % (ModuleFile, LibraryPath, LibraryClass))
|
|
Module.LibraryClasses[LibraryClass] = LibraryPath
|
|
if LibraryPath not in self.LibraryInstances:
|
|
self.LibraryInstances.append(LibraryPath)
|
|
|
|
# get module private PCD setting
|
|
for Type in [MODEL_PCD_FIXED_AT_BUILD, MODEL_PCD_PATCHABLE_IN_MODULE, \
|
|
MODEL_PCD_FEATURE_FLAG, MODEL_PCD_DYNAMIC, MODEL_PCD_DYNAMIC_EX]:
|
|
RecordList = self._RawData[Type, self._Arch, None, ModuleId]
|
|
for TokenSpaceGuid, PcdCName, Setting, Dummy1, Dummy2, Dummy3, Dummy4,Dummy5 in RecordList:
|
|
TokenList = GetSplitValueList(Setting)
|
|
DefaultValue = TokenList[0]
|
|
if len(TokenList) > 1:
|
|
MaxDatumSize = TokenList[1]
|
|
else:
|
|
MaxDatumSize = ''
|
|
TypeString = self._PCD_TYPE_STRING_[Type]
|
|
Pcd = PcdClassObject(
|
|
PcdCName,
|
|
TokenSpaceGuid,
|
|
TypeString,
|
|
'',
|
|
DefaultValue,
|
|
'',
|
|
MaxDatumSize,
|
|
{},
|
|
False,
|
|
None
|
|
)
|
|
Module.Pcds[PcdCName, TokenSpaceGuid] = Pcd
|
|
|
|
# get module private build options
|
|
RecordList = self._RawData[MODEL_META_DATA_BUILD_OPTION, self._Arch, None, ModuleId]
|
|
for ToolChainFamily, ToolChain, Option, Dummy1, Dummy2, Dummy3, Dummy4,Dummy5 in RecordList:
|
|
if (ToolChainFamily, ToolChain) not in Module.BuildOptions:
|
|
Module.BuildOptions[ToolChainFamily, ToolChain] = Option
|
|
else:
|
|
OptionString = Module.BuildOptions[ToolChainFamily, ToolChain]
|
|
Module.BuildOptions[ToolChainFamily, ToolChain] = OptionString + " " + Option
|
|
|
|
RecordList = self._RawData[MODEL_META_DATA_HEADER, self._Arch, None, ModuleId]
|
|
if DuplicatedFile and not RecordList:
|
|
EdkLogger.error('build', FILE_DUPLICATED, File=self.MetaFile, ExtraData=str(ModuleFile), Line=LineNo)
|
|
if RecordList:
|
|
if len(RecordList) != 1:
|
|
EdkLogger.error('build', OPTION_UNKNOWN, 'Only FILE_GUID can be listed in <Defines> section.',
|
|
File=self.MetaFile, ExtraData=str(ModuleFile), Line=LineNo)
|
|
ModuleFile = ProcessDuplicatedInf(ModuleFile, RecordList[0][2], GlobalData.gWorkspace)
|
|
ModuleFile.Arch = self._Arch
|
|
|
|
self._Modules[ModuleFile] = Module
|
|
return self._Modules
|
|
|
|
## Retrieve all possible library instances used in this platform
|
|
def _GetLibraryInstances(self):
|
|
if self._LibraryInstances == None:
|
|
self._GetLibraryClasses()
|
|
return self._LibraryInstances
|
|
|
|
## Retrieve [LibraryClasses] information
|
|
def _GetLibraryClasses(self):
|
|
if self._LibraryClasses == None:
|
|
self._LibraryInstances = []
|
|
#
|
|
# tdict is a special dict kind of type, used for selecting correct
|
|
# library instance for given library class and module type
|
|
#
|
|
LibraryClassDict = tdict(True, 3)
|
|
# track all library class names
|
|
LibraryClassSet = set()
|
|
RecordList = self._RawData[MODEL_EFI_LIBRARY_CLASS, self._Arch, None, -1]
|
|
Macros = self._Macros
|
|
for Record in RecordList:
|
|
LibraryClass, LibraryInstance, Dummy, Arch, ModuleType, Dummy,Dummy, LineNo = Record
|
|
if LibraryClass == '' or LibraryClass == 'NULL':
|
|
self._NullLibraryNumber += 1
|
|
LibraryClass = 'NULL%d' % self._NullLibraryNumber
|
|
EdkLogger.verbose("Found forced library for arch=%s\n\t%s [%s]" % (Arch, LibraryInstance, LibraryClass))
|
|
LibraryClassSet.add(LibraryClass)
|
|
LibraryInstance = PathClass(NormPath(LibraryInstance, Macros), GlobalData.gWorkspace, Arch=self._Arch)
|
|
# check the file validation
|
|
ErrorCode, ErrorInfo = LibraryInstance.Validate('.inf')
|
|
if ErrorCode != 0:
|
|
EdkLogger.error('build', ErrorCode, File=self.MetaFile, Line=LineNo,
|
|
ExtraData=ErrorInfo)
|
|
|
|
if ModuleType != 'COMMON' and ModuleType not in SUP_MODULE_LIST:
|
|
EdkLogger.error('build', OPTION_UNKNOWN, "Unknown module type [%s]" % ModuleType,
|
|
File=self.MetaFile, ExtraData=LibraryInstance, Line=LineNo)
|
|
LibraryClassDict[Arch, ModuleType, LibraryClass] = LibraryInstance
|
|
if LibraryInstance not in self._LibraryInstances:
|
|
self._LibraryInstances.append(LibraryInstance)
|
|
|
|
# resolve the specific library instance for each class and each module type
|
|
self._LibraryClasses = tdict(True)
|
|
for LibraryClass in LibraryClassSet:
|
|
# try all possible module types
|
|
for ModuleType in SUP_MODULE_LIST:
|
|
LibraryInstance = LibraryClassDict[self._Arch, ModuleType, LibraryClass]
|
|
if LibraryInstance == None:
|
|
continue
|
|
self._LibraryClasses[LibraryClass, ModuleType] = LibraryInstance
|
|
|
|
# for Edk style library instances, which are listed in different section
|
|
Macros["EDK_SOURCE"] = GlobalData.gEcpSource
|
|
RecordList = self._RawData[MODEL_EFI_LIBRARY_INSTANCE, self._Arch]
|
|
for Record in RecordList:
|
|
File = PathClass(NormPath(Record[0], Macros), GlobalData.gWorkspace, Arch=self._Arch)
|
|
LineNo = Record[-1]
|
|
# check the file validation
|
|
ErrorCode, ErrorInfo = File.Validate('.inf')
|
|
if ErrorCode != 0:
|
|
EdkLogger.error('build', ErrorCode, File=self.MetaFile, Line=LineNo,
|
|
ExtraData=ErrorInfo)
|
|
if File not in self._LibraryInstances:
|
|
self._LibraryInstances.append(File)
|
|
#
|
|
# we need the module name as the library class name, so we have
|
|
# to parse it here. (self._Bdb[] will trigger a file parse if it
|
|
# hasn't been parsed)
|
|
#
|
|
Library = self._Bdb[File, self._Arch, self._Target, self._Toolchain]
|
|
self._LibraryClasses[Library.BaseName, ':dummy:'] = Library
|
|
return self._LibraryClasses
|
|
|
|
def _ValidatePcd(self, PcdCName, TokenSpaceGuid, Setting, PcdType, LineNo):
|
|
if self._DecPcds == None:
|
|
|
|
FdfInfList = []
|
|
if GlobalData.gFdfParser:
|
|
FdfInfList = GlobalData.gFdfParser.Profile.InfList
|
|
|
|
PkgSet = set()
|
|
for Inf in FdfInfList:
|
|
ModuleFile = PathClass(NormPath(Inf), GlobalData.gWorkspace, Arch=self._Arch)
|
|
if ModuleFile in self._Modules:
|
|
continue
|
|
ModuleData = self._Bdb[ModuleFile, self._Arch, self._Target, self._Toolchain]
|
|
PkgSet.update(ModuleData.Packages)
|
|
|
|
self._DecPcds = GetDeclaredPcd(self, self._Bdb, self._Arch, self._Target, self._Toolchain,PkgSet)
|
|
|
|
|
|
if (PcdCName, TokenSpaceGuid) not in self._DecPcds:
|
|
EdkLogger.error('build', PARSER_ERROR,
|
|
"Pcd (%s.%s) defined in DSC is not declared in DEC files. Arch: ['%s']" % (TokenSpaceGuid, PcdCName, self._Arch),
|
|
File=self.MetaFile, Line=LineNo)
|
|
ValueList, IsValid, Index = AnalyzeDscPcd(Setting, PcdType, self._DecPcds[PcdCName, TokenSpaceGuid].DatumType)
|
|
if not IsValid and PcdType not in [MODEL_PCD_FEATURE_FLAG, MODEL_PCD_FIXED_AT_BUILD]:
|
|
EdkLogger.error('build', FORMAT_INVALID, "Pcd format incorrect.", File=self.MetaFile, Line=LineNo,
|
|
ExtraData="%s.%s|%s" % (TokenSpaceGuid, PcdCName, Setting))
|
|
if ValueList[Index] and PcdType not in [MODEL_PCD_FEATURE_FLAG, MODEL_PCD_FIXED_AT_BUILD]:
|
|
try:
|
|
ValueList[Index] = ValueExpression(ValueList[Index], GlobalData.gPlatformPcds)(True)
|
|
except WrnExpression, Value:
|
|
ValueList[Index] = Value.result
|
|
except EvaluationException, Excpt:
|
|
if hasattr(Excpt, 'Pcd'):
|
|
if Excpt.Pcd in GlobalData.gPlatformOtherPcds:
|
|
EdkLogger.error('Parser', FORMAT_INVALID, "Cannot use this PCD (%s) in an expression as"
|
|
" it must be defined in a [PcdsFixedAtBuild] or [PcdsFeatureFlag] section"
|
|
" of the DSC file" % Excpt.Pcd,
|
|
File=self.MetaFile, Line=LineNo)
|
|
else:
|
|
EdkLogger.error('Parser', FORMAT_INVALID, "PCD (%s) is not defined in DSC file" % Excpt.Pcd,
|
|
File=self.MetaFile, Line=LineNo)
|
|
else:
|
|
EdkLogger.error('Parser', FORMAT_INVALID, "Invalid expression: %s" % str(Excpt),
|
|
File=self.MetaFile, Line=LineNo)
|
|
if ValueList[Index] == 'True':
|
|
ValueList[Index] = '1'
|
|
elif ValueList[Index] == 'False':
|
|
ValueList[Index] = '0'
|
|
if ValueList[Index]:
|
|
Valid, ErrStr = CheckPcdDatum(self._DecPcds[PcdCName, TokenSpaceGuid].DatumType, ValueList[Index])
|
|
if not Valid:
|
|
EdkLogger.error('build', FORMAT_INVALID, ErrStr, File=self.MetaFile, Line=LineNo,
|
|
ExtraData="%s.%s" % (TokenSpaceGuid, PcdCName))
|
|
return ValueList
|
|
|
|
def _FilterPcdBySkuUsage(self,Pcds):
|
|
available_sku = self.SkuIdMgr.AvailableSkuIdSet
|
|
sku_usage = self.SkuIdMgr.SkuUsageType
|
|
if sku_usage == SkuClass.SINGLE:
|
|
for pcdname in Pcds:
|
|
pcd = Pcds[pcdname]
|
|
Pcds[pcdname].SkuInfoList = {"DEFAULT":pcd.SkuInfoList[skuid] for skuid in pcd.SkuInfoList if skuid in available_sku}
|
|
else:
|
|
for pcdname in Pcds:
|
|
pcd = Pcds[pcdname]
|
|
Pcds[pcdname].SkuInfoList = {skuid:pcd.SkuInfoList[skuid] for skuid in pcd.SkuInfoList if skuid in available_sku}
|
|
return Pcds
|
|
def CompleteHiiPcdsDefaultStores(self,Pcds):
|
|
HiiPcd = [Pcds[pcd] for pcd in Pcds if Pcds[pcd].Type in [self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_HII], self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_HII]]]
|
|
DefaultStoreMgr = DefaultStore(self.DefaultStores)
|
|
for pcd in HiiPcd:
|
|
for skuid in pcd.SkuInfoList:
|
|
skuobj = pcd.SkuInfoList.get(skuid)
|
|
if "STANDARD" not in skuobj.DefaultStoreDict:
|
|
PcdDefaultStoreSet = set([defaultstorename for defaultstorename in skuobj.DefaultStoreDict])
|
|
mindefaultstorename = DefaultStoreMgr.GetMin(PcdDefaultStoreSet)
|
|
skuobj.DefaultStoreDict['STANDARD'] = copy.deepcopy(skuobj.DefaultStoreDict[mindefaultstorename])
|
|
return Pcds
|
|
|
|
## Retrieve all PCD settings in platform
|
|
def _GetPcds(self):
|
|
if self._Pcds == None:
|
|
self._Pcds = sdict()
|
|
self._Pcds.update(self._GetPcd(MODEL_PCD_FIXED_AT_BUILD))
|
|
self._Pcds.update(self._GetPcd(MODEL_PCD_PATCHABLE_IN_MODULE))
|
|
self._Pcds.update(self._GetPcd(MODEL_PCD_FEATURE_FLAG))
|
|
self._Pcds.update(self._GetDynamicPcd(MODEL_PCD_DYNAMIC_DEFAULT))
|
|
self._Pcds.update(self._GetDynamicHiiPcd(MODEL_PCD_DYNAMIC_HII))
|
|
self._Pcds.update(self._GetDynamicVpdPcd(MODEL_PCD_DYNAMIC_VPD))
|
|
self._Pcds.update(self._GetDynamicPcd(MODEL_PCD_DYNAMIC_EX_DEFAULT))
|
|
self._Pcds.update(self._GetDynamicHiiPcd(MODEL_PCD_DYNAMIC_EX_HII))
|
|
self._Pcds.update(self._GetDynamicVpdPcd(MODEL_PCD_DYNAMIC_EX_VPD))
|
|
|
|
self._Pcds = self.CompletePcdValues(self._Pcds)
|
|
self._Pcds = self.UpdateStructuredPcds(MODEL_PCD_TYPE_LIST, self._Pcds)
|
|
self._Pcds = self.CompleteHiiPcdsDefaultStores(self._Pcds)
|
|
self._Pcds = self._FilterPcdBySkuUsage(self._Pcds)
|
|
return self._Pcds
|
|
|
|
def _dumpPcdInfo(self,Pcds):
|
|
for pcd in Pcds:
|
|
pcdobj = Pcds[pcd]
|
|
if not pcdobj.TokenCName.startswith("Test"):
|
|
continue
|
|
for skuid in pcdobj.SkuInfoList:
|
|
if pcdobj.Type in (self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_HII],self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_HII]):
|
|
for storename in pcdobj.SkuInfoList[skuid].DefaultStoreDict:
|
|
print "PcdCName: %s, SkuName: %s, StoreName: %s, Value: %s" % (".".join((pcdobj.TokenSpaceGuidCName, pcdobj.TokenCName)), skuid,storename,str(pcdobj.SkuInfoList[skuid].DefaultStoreDict[storename]))
|
|
else:
|
|
print "PcdCName: %s, SkuName: %s, Value: %s" % (".".join((pcdobj.TokenSpaceGuidCName, pcdobj.TokenCName)), skuid,str(pcdobj.SkuInfoList[skuid].DefaultValue))
|
|
## Retrieve [BuildOptions]
|
|
def _GetBuildOptions(self):
|
|
if self._BuildOptions == None:
|
|
self._BuildOptions = sdict()
|
|
#
|
|
# Retrieve build option for EDKII and EDK style module
|
|
#
|
|
for CodeBase in (EDKII_NAME, EDK_NAME):
|
|
RecordList = self._RawData[MODEL_META_DATA_BUILD_OPTION, self._Arch, CodeBase]
|
|
for ToolChainFamily, ToolChain, Option, Dummy1, Dummy2, Dummy3, Dummy4,Dummy5 in RecordList:
|
|
CurKey = (ToolChainFamily, ToolChain, CodeBase)
|
|
#
|
|
# Only flags can be appended
|
|
#
|
|
if CurKey not in self._BuildOptions or not ToolChain.endswith('_FLAGS') or Option.startswith('='):
|
|
self._BuildOptions[CurKey] = Option
|
|
else:
|
|
self._BuildOptions[CurKey] += ' ' + Option
|
|
return self._BuildOptions
|
|
|
|
def GetBuildOptionsByModuleType(self, Edk, ModuleType):
|
|
if self._ModuleTypeOptions == None:
|
|
self._ModuleTypeOptions = sdict()
|
|
if (Edk, ModuleType) not in self._ModuleTypeOptions:
|
|
options = sdict()
|
|
self._ModuleTypeOptions[Edk, ModuleType] = options
|
|
DriverType = '%s.%s' % (Edk, ModuleType)
|
|
CommonDriverType = '%s.%s' % ('COMMON', ModuleType)
|
|
RecordList = self._RawData[MODEL_META_DATA_BUILD_OPTION, self._Arch, DriverType]
|
|
for ToolChainFamily, ToolChain, Option, Arch, Type, Dummy3, Dummy4,Dummy5 in RecordList:
|
|
if Type == DriverType or Type == CommonDriverType:
|
|
Key = (ToolChainFamily, ToolChain, Edk)
|
|
if Key not in options or not ToolChain.endswith('_FLAGS') or Option.startswith('='):
|
|
options[Key] = Option
|
|
else:
|
|
options[Key] += ' ' + Option
|
|
return self._ModuleTypeOptions[Edk, ModuleType]
|
|
|
|
def GetStructurePcdInfo(self, PcdSet):
|
|
structure_pcd_data = {}
|
|
for item in PcdSet:
|
|
if (item[0],item[1]) not in structure_pcd_data:
|
|
structure_pcd_data[(item[0],item[1])] = []
|
|
structure_pcd_data[(item[0],item[1])].append(item)
|
|
|
|
return structure_pcd_data
|
|
|
|
def UpdateStructuredPcds(self, TypeList, AllPcds):
|
|
Pcds = AllPcds
|
|
DefaultStoreMgr = DefaultStore(self.DefaultStores)
|
|
SkuIds = set([skuid for pcdobj in AllPcds.values() for skuid in pcdobj.SkuInfoList.keys()])
|
|
DefaultStores = set([storename for pcdobj in AllPcds.values() for skuobj in pcdobj.SkuInfoList.values() for storename in skuobj.DefaultStoreDict.keys()])
|
|
|
|
S_PcdSet = []
|
|
# Find out all possible PCD candidates for self._Arch
|
|
RecordList = []
|
|
|
|
for Type in TypeList:
|
|
RecordList.extend(self._RawData[Type, self._Arch])
|
|
|
|
for TokenSpaceGuid, PcdCName, Setting, Arch, SkuName, default_store, Dummy4,Dummy5 in RecordList:
|
|
SkuName = SkuName.upper()
|
|
default_store = default_store.upper()
|
|
SkuName = 'DEFAULT' if SkuName == 'COMMON' else SkuName
|
|
if SkuName not in SkuIds:
|
|
continue
|
|
|
|
if SkuName in SkuIds and "." in TokenSpaceGuid:
|
|
S_PcdSet.append(( TokenSpaceGuid.split(".")[0],TokenSpaceGuid.split(".")[1], PcdCName,SkuName, default_store,Dummy5, AnalyzePcdExpression(Setting)[0]))
|
|
|
|
# handle pcd value override
|
|
StrPcdSet = self.GetStructurePcdInfo(S_PcdSet)
|
|
S_pcd_set = {}
|
|
for str_pcd in StrPcdSet:
|
|
str_pcd_obj = Pcds.get((str_pcd[1], str_pcd[0]), None)
|
|
str_pcd_dec = self._DecPcds.get((str_pcd[1], str_pcd[0]), None)
|
|
if str_pcd_dec:
|
|
str_pcd_obj_str = StructurePcd()
|
|
str_pcd_obj_str.copy(str_pcd_dec)
|
|
if str_pcd_obj:
|
|
str_pcd_obj_str.copy(str_pcd_obj)
|
|
if str_pcd_obj.DefaultValue:
|
|
str_pcd_obj_str.DefaultFromDSC = str_pcd_obj.DefaultValue
|
|
for str_pcd_data in StrPcdSet[str_pcd]:
|
|
if str_pcd_data[3] in SkuIds:
|
|
str_pcd_obj_str.AddOverrideValue(str_pcd_data[2], str(str_pcd_data[6]), 'DEFAULT' if str_pcd_data[3] == 'COMMON' else str_pcd_data[3],'STANDARD' if str_pcd_data[4] == 'COMMON' else str_pcd_data[4], self.MetaFile.File,LineNo=str_pcd_data[5])
|
|
S_pcd_set[str_pcd[1], str_pcd[0]] = str_pcd_obj_str
|
|
else:
|
|
EdkLogger.error('build', PARSER_ERROR,
|
|
"Pcd (%s.%s) defined in DSC is not declared in DEC files. Arch: ['%s']" % (str_pcd[0], str_pcd[1], self._Arch),
|
|
File=self.MetaFile,Line = StrPcdSet[str_pcd][0][5])
|
|
# Add the Structure PCD that only defined in DEC, don't have override in DSC file
|
|
for Pcd in self._DecPcds:
|
|
if type (self._DecPcds[Pcd]) is StructurePcd:
|
|
if Pcd not in S_pcd_set:
|
|
str_pcd_obj_str = StructurePcd()
|
|
str_pcd_obj_str.copy(self._DecPcds[Pcd])
|
|
str_pcd_obj = Pcds.get(Pcd, None)
|
|
if str_pcd_obj:
|
|
str_pcd_obj_str.copy(str_pcd_obj)
|
|
if str_pcd_obj.DefaultValue:
|
|
str_pcd_obj_str.DefaultFromDSC = str_pcd_obj.DefaultValue
|
|
S_pcd_set[Pcd] = str_pcd_obj_str
|
|
if S_pcd_set:
|
|
GlobalData.gStructurePcd[self.Arch] = S_pcd_set
|
|
for stru_pcd in S_pcd_set.values():
|
|
if stru_pcd.Type not in [self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_DEFAULT],
|
|
self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_HII],
|
|
self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_VPD],
|
|
self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_DEFAULT],
|
|
self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_HII],
|
|
self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_VPD]]:
|
|
continue
|
|
if stru_pcd.Type in [self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_HII], self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_HII]]:
|
|
for skuid in SkuIds:
|
|
nextskuid = skuid
|
|
NoDefault = False
|
|
if skuid not in stru_pcd.SkuOverrideValues:
|
|
while nextskuid not in stru_pcd.SkuOverrideValues:
|
|
if nextskuid == "DEFAULT":
|
|
NoDefault = True
|
|
break
|
|
nextskuid = self.SkuIdMgr.GetNextSkuId(nextskuid)
|
|
stru_pcd.SkuOverrideValues[skuid] = {}
|
|
if NoDefault:
|
|
continue
|
|
PcdDefaultStoreSet = set([defaultstorename for defaultstorename in stru_pcd.SkuOverrideValues[nextskuid]])
|
|
mindefaultstorename = DefaultStoreMgr.GetMin(PcdDefaultStoreSet)
|
|
|
|
for defaultstoreid in DefaultStores:
|
|
if defaultstoreid not in stru_pcd.SkuOverrideValues[skuid]:
|
|
stru_pcd.SkuOverrideValues[skuid][defaultstoreid] = copy.deepcopy(stru_pcd.SkuOverrideValues[nextskuid][mindefaultstorename])
|
|
for skuid in SkuIds:
|
|
if skuid in stru_pcd.SkuOverrideValues:
|
|
continue
|
|
nextskuid = self.SkuIdMgr.GetNextSkuId(skuid)
|
|
NoDefault = False
|
|
while nextskuid not in stru_pcd.SkuOverrideValues:
|
|
if nextskuid == "DEFAULT":
|
|
NoDefault = True
|
|
break
|
|
nextskuid = self.SkuIdMgr.GetNextSkuId(nextskuid)
|
|
stru_pcd.SkuOverrideValues[skuid] = copy.deepcopy(stru_pcd.SkuOverrideValues[nextskuid]) if not NoDefault else copy.deepcopy({defaultstorename: stru_pcd.DefaultValues for defaultstorename in DefaultStores})
|
|
Str_Pcd_Values = self.GenerateByteArrayValue(S_pcd_set)
|
|
if Str_Pcd_Values:
|
|
for (skuname,StoreName,PcdGuid,PcdName,PcdValue) in Str_Pcd_Values:
|
|
str_pcd_obj = S_pcd_set.get((PcdName, PcdGuid))
|
|
if str_pcd_obj is None:
|
|
raise
|
|
if str_pcd_obj.Type in [self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_HII],
|
|
self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_HII]]:
|
|
if skuname not in str_pcd_obj.SkuInfoList:
|
|
str_pcd_obj.SkuInfoList[skuname] = SkuInfoClass(SkuIdName=skuname, SkuId=self.SkuIds[skuname][0], HiiDefaultValue=PcdValue, DefaultStore = {StoreName:PcdValue})
|
|
else:
|
|
str_pcd_obj.SkuInfoList[skuname].HiiDefaultValue = PcdValue
|
|
str_pcd_obj.SkuInfoList[skuname].DefaultStoreDict.update({StoreName:PcdValue})
|
|
elif str_pcd_obj.Type in [self._PCD_TYPE_STRING_[MODEL_PCD_FIXED_AT_BUILD],
|
|
self._PCD_TYPE_STRING_[MODEL_PCD_PATCHABLE_IN_MODULE]]:
|
|
if skuname in (self.SkuIdMgr.SystemSkuId, 'DEFAULT', 'COMMON'):
|
|
str_pcd_obj.DefaultValue = PcdValue
|
|
else:
|
|
if skuname not in str_pcd_obj.SkuInfoList:
|
|
str_pcd_obj.SkuInfoList[skuname] = SkuInfoClass(SkuIdName=skuname, SkuId=self.SkuIds[skuname][0], DefaultValue=PcdValue)
|
|
else:
|
|
str_pcd_obj.SkuInfoList[skuname].DefaultValue = PcdValue
|
|
for str_pcd_obj in S_pcd_set.values():
|
|
if str_pcd_obj.Type not in [self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_HII],
|
|
self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_HII]]:
|
|
continue
|
|
PcdDefaultStoreSet = set([defaultstorename for skuobj in str_pcd_obj.SkuInfoList.values() for defaultstorename in skuobj.DefaultStoreDict])
|
|
DefaultStoreObj = DefaultStore(self._GetDefaultStores())
|
|
mindefaultstorename = DefaultStoreObj.GetMin(PcdDefaultStoreSet)
|
|
str_pcd_obj.SkuInfoList[self.SkuIdMgr.SystemSkuId].HiiDefaultValue = str_pcd_obj.SkuInfoList[self.SkuIdMgr.SystemSkuId].DefaultStoreDict[mindefaultstorename]
|
|
|
|
for str_pcd_obj in S_pcd_set.values():
|
|
|
|
str_pcd_obj.MaxDatumSize = self.GetStructurePcdMaxSize(str_pcd_obj)
|
|
Pcds[str_pcd_obj.TokenCName, str_pcd_obj.TokenSpaceGuidCName] = str_pcd_obj
|
|
|
|
return Pcds
|
|
|
|
## Retrieve non-dynamic PCD settings
|
|
#
|
|
# @param Type PCD type
|
|
#
|
|
# @retval a dict object contains settings of given PCD type
|
|
#
|
|
def _GetPcd(self, Type):
|
|
Pcds = sdict()
|
|
#
|
|
# tdict is a special dict kind of type, used for selecting correct
|
|
# PCD settings for certain ARCH
|
|
#
|
|
AvailableSkuIdSet = copy.copy(self.SkuIds)
|
|
|
|
PcdDict = tdict(True, 3)
|
|
PcdSet = set()
|
|
# Find out all possible PCD candidates for self._Arch
|
|
RecordList = self._RawData[Type, self._Arch]
|
|
PcdValueDict = sdict()
|
|
for TokenSpaceGuid, PcdCName, Setting, Arch, SkuName, Dummy3, Dummy4,Dummy5 in RecordList:
|
|
SkuName = SkuName.upper()
|
|
SkuName = 'DEFAULT' if SkuName == 'COMMON' else SkuName
|
|
if SkuName not in AvailableSkuIdSet:
|
|
EdkLogger.error('build ', PARAMETER_INVALID, 'Sku %s is not defined in [SkuIds] section' % SkuName,
|
|
File=self.MetaFile, Line=Dummy5)
|
|
if SkuName in (self.SkuIdMgr.SystemSkuId, 'DEFAULT', 'COMMON'):
|
|
if "." not in TokenSpaceGuid:
|
|
PcdSet.add((PcdCName, TokenSpaceGuid, SkuName, Dummy4))
|
|
PcdDict[Arch, PcdCName, TokenSpaceGuid, SkuName] = Setting
|
|
|
|
for PcdCName, TokenSpaceGuid, SkuName, Dummy4 in PcdSet:
|
|
Setting = PcdDict[self._Arch, PcdCName, TokenSpaceGuid, SkuName]
|
|
if Setting == None:
|
|
continue
|
|
PcdValue, DatumType, MaxDatumSize = self._ValidatePcd(PcdCName, TokenSpaceGuid, Setting, Type, Dummy4)
|
|
if (PcdCName, TokenSpaceGuid) in PcdValueDict:
|
|
PcdValueDict[PcdCName, TokenSpaceGuid][SkuName] = (PcdValue, DatumType, MaxDatumSize)
|
|
else:
|
|
PcdValueDict[PcdCName, TokenSpaceGuid] = {SkuName:(PcdValue, DatumType, MaxDatumSize)}
|
|
|
|
PcdsKeys = PcdValueDict.keys()
|
|
for PcdCName, TokenSpaceGuid in PcdsKeys:
|
|
|
|
PcdSetting = PcdValueDict[PcdCName, TokenSpaceGuid]
|
|
PcdValue = None
|
|
DatumType = None
|
|
MaxDatumSize = None
|
|
if 'COMMON' in PcdSetting:
|
|
PcdValue, DatumType, MaxDatumSize = PcdSetting['COMMON']
|
|
if 'DEFAULT' in PcdSetting:
|
|
PcdValue, DatumType, MaxDatumSize = PcdSetting['DEFAULT']
|
|
if self.SkuIdMgr.SystemSkuId in PcdSetting:
|
|
PcdValue, DatumType, MaxDatumSize = PcdSetting[self.SkuIdMgr.SystemSkuId]
|
|
|
|
Pcds[PcdCName, TokenSpaceGuid] = PcdClassObject(
|
|
PcdCName,
|
|
TokenSpaceGuid,
|
|
self._PCD_TYPE_STRING_[Type],
|
|
DatumType,
|
|
PcdValue,
|
|
'',
|
|
MaxDatumSize,
|
|
{},
|
|
False,
|
|
None,
|
|
IsDsc=True)
|
|
|
|
|
|
return Pcds
|
|
|
|
def __UNICODE2OCTList(self,Value):
|
|
Value = Value.strip()
|
|
Value = Value[2:-1]
|
|
List = []
|
|
for Item in Value:
|
|
Temp = '%04X' % ord(Item)
|
|
List.append('0x' + Temp[2:4])
|
|
List.append('0x' + Temp[0:2])
|
|
List.append('0x00')
|
|
List.append('0x00')
|
|
return List
|
|
def __STRING2OCTList(self,Value):
|
|
OCTList = []
|
|
Value = Value.strip('"')
|
|
for char in Value:
|
|
Temp = '%02X' % ord(char)
|
|
OCTList.append('0x' + Temp)
|
|
OCTList.append('0x00')
|
|
return OCTList
|
|
|
|
def GetStructurePcdMaxSize(self, str_pcd):
|
|
pcd_default_value = str_pcd.DefaultValue
|
|
sku_values = [skuobj.HiiDefaultValue if str_pcd.Type in [self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_HII], self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_HII]] else skuobj.DefaultValue for skuobj in str_pcd.SkuInfoList.values()]
|
|
sku_values.append(pcd_default_value)
|
|
|
|
def get_length(value):
|
|
Value = value.strip()
|
|
if Value.startswith('GUID') and Value.endswith(')'):
|
|
return 16
|
|
if Value.startswith('L"') and Value.endswith('"'):
|
|
return len(Value[2:-1])
|
|
if Value[0] == '"' and Value[-1] == '"':
|
|
return len(Value) - 2
|
|
if Value[0] == '{' and Value[-1] == '}':
|
|
return len(Value.split(","))
|
|
if Value.startswith("L'") and Value.endswith("'") and len(list(Value[2:-1])) > 1:
|
|
return len(list(Value[2:-1]))
|
|
if Value[0] == "'" and Value[-1] == "'" and len(list(Value[1:-1])) > 1:
|
|
return len(Value) - 2
|
|
return len(Value)
|
|
|
|
return str(max([pcd_size for pcd_size in [get_length(item) for item in sku_values]]))
|
|
|
|
def IsFieldValueAnArray (self, Value):
|
|
Value = Value.strip()
|
|
if Value.startswith('GUID') and Value.endswith(')'):
|
|
return True
|
|
if Value.startswith('L"') and Value.endswith('"') and len(list(Value[2:-1])) > 1:
|
|
return True
|
|
if Value[0] == '"' and Value[-1] == '"' and len(list(Value[1:-1])) > 1:
|
|
return True
|
|
if Value[0] == '{' and Value[-1] == '}':
|
|
return True
|
|
if Value.startswith("L'") and Value.endswith("'") and len(list(Value[2:-1])) > 1:
|
|
print 'foo = ', list(Value[2:-1])
|
|
return True
|
|
if Value[0] == "'" and Value[-1] == "'" and len(list(Value[1:-1])) > 1:
|
|
print 'bar = ', list(Value[1:-1])
|
|
return True
|
|
return False
|
|
|
|
def ExecuteCommand (self, Command):
|
|
try:
|
|
Process = subprocess.Popen(Command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
|
|
except:
|
|
print 'ERROR: Can not execute command:', Command
|
|
sys.exit(1)
|
|
Result = Process.communicate()
|
|
if Process.returncode <> 0:
|
|
print 'ERROR: Can not collect output from command:', Command
|
|
return Result[0], Result[1]
|
|
|
|
def IntToCString(self, Value, ValueSize):
|
|
Result = '"'
|
|
if not isinstance (Value, str):
|
|
for Index in range(0, ValueSize):
|
|
Result = Result + '\\x%02x' % (Value & 0xff)
|
|
Value = Value >> 8
|
|
Result = Result + '"'
|
|
return Result
|
|
|
|
def GenerateInitializeFunc(self, SkuName, DefaultStoreName, Pcd, InitByteValue, CApp):
|
|
OverrideValues = {DefaultStoreName:""}
|
|
if Pcd.SkuOverrideValues:
|
|
OverrideValues = Pcd.SkuOverrideValues[SkuName]
|
|
for DefaultStoreName in OverrideValues.keys():
|
|
CApp = CApp + 'void\n'
|
|
CApp = CApp + 'Initialize_%s_%s_%s_%s(\n' % (SkuName, DefaultStoreName, Pcd.TokenSpaceGuidCName, Pcd.TokenCName)
|
|
CApp = CApp + ' void\n'
|
|
CApp = CApp + ' )\n'
|
|
CApp = CApp + '{\n'
|
|
CApp = CApp + ' UINT32 Size;\n'
|
|
CApp = CApp + ' UINT32 FieldSize;\n'
|
|
CApp = CApp + ' UINT8 *Value;\n'
|
|
CApp = CApp + ' UINT32 OriginalSize;\n'
|
|
CApp = CApp + ' VOID *OriginalPcd;\n'
|
|
CApp = CApp + ' %s *Pcd;\n' % (Pcd.DatumType)
|
|
CApp = CApp + '\n'
|
|
Pcd.DefaultValue = Pcd.DefaultValue.strip()
|
|
if Pcd.DefaultValue.startswith('L"') and Pcd.DefaultValue.endswith('"'):
|
|
PcdDefaultValue = "{" + ",".join(self.__UNICODE2OCTList(Pcd.DefaultValue)) + "}"
|
|
elif Pcd.DefaultValue.startswith('"') and Pcd.DefaultValue.endswith('"'):
|
|
PcdDefaultValue = "{" + ",".join(self.__STRING2OCTList(Pcd.DefaultValue)) + "}"
|
|
else:
|
|
PcdDefaultValue = Pcd.DefaultValue
|
|
InitByteValue += '%s.%s.%s.%s|%s|%s\n' % (SkuName, DefaultStoreName, Pcd.TokenSpaceGuidCName, Pcd.TokenCName, Pcd.DatumType, PcdDefaultValue)
|
|
|
|
#
|
|
# Get current PCD value and size
|
|
#
|
|
CApp = CApp + ' OriginalPcd = PcdGetPtr (%s, %s, %s, %s, &OriginalSize);\n' % (SkuName, DefaultStoreName, Pcd.TokenSpaceGuidCName, Pcd.TokenCName)
|
|
|
|
#
|
|
# Determine the size of the PCD. For simple structures, sizeof(TYPE) provides
|
|
# the correct value. For structures with a flexible array member, the flexible
|
|
# array member is detected, and the size is based on the highest index used with
|
|
# the flexible array member. The flexible array member must be the last field
|
|
# in a structure. The size formula for this case is:
|
|
# OFFSET_OF(FlexbleArrayField) + sizeof(FlexibleArray[0]) * (HighestIndex + 1)
|
|
#
|
|
CApp = CApp + ' Size = sizeof(%s);\n' % (Pcd.DatumType)
|
|
for FieldList in [Pcd.DefaultValues, OverrideValues.get(DefaultStoreName)]:
|
|
if not FieldList:
|
|
continue
|
|
for FieldName in FieldList:
|
|
FieldName = "." + FieldName
|
|
IsArray = self.IsFieldValueAnArray(FieldList[FieldName.strip(".")][0])
|
|
if IsArray:
|
|
Value, ValueSize = ParseFieldValue (FieldList[FieldName.strip(".")][0])
|
|
CApp = CApp + ' __FLEXIBLE_SIZE(Size, %s, %s, %d / __ARRAY_ELEMENT_SIZE(%s, %s));\n' % (Pcd.DatumType, FieldName.strip("."), ValueSize, Pcd.DatumType, FieldName.strip("."));
|
|
else:
|
|
NewFieldName = ''
|
|
while '[' in FieldName:
|
|
NewFieldName = NewFieldName + FieldName.split('[', 1)[0] + '[0]'
|
|
ArrayIndex = int(FieldName.split('[', 1)[1].split(']', 1)[0])
|
|
FieldName = FieldName.split(']', 1)[1]
|
|
FieldName = NewFieldName + FieldName
|
|
while '[' in FieldName:
|
|
FieldName = FieldName.rsplit('[', 1)[0]
|
|
CApp = CApp + ' __FLEXIBLE_SIZE(Size, %s, %s, %d);\n' % (Pcd.DatumType, FieldName.strip("."), ArrayIndex + 1)
|
|
|
|
#
|
|
# Allocate and zero buffer for the PCD
|
|
# Must handle cases where current value is smaller, larger, or same size
|
|
# Always keep that larger one as the current size
|
|
#
|
|
CApp = CApp + ' Size = (OriginalSize > Size ? OriginalSize : Size);\n'
|
|
CApp = CApp + ' Pcd = (%s *)malloc (Size);\n' % (Pcd.DatumType)
|
|
CApp = CApp + ' memset (Pcd, 0, Size);\n'
|
|
|
|
#
|
|
# Copy current PCD value into allocated buffer.
|
|
#
|
|
CApp = CApp + ' memcpy (Pcd, OriginalPcd, OriginalSize);\n'
|
|
|
|
#
|
|
# Assign field values in PCD
|
|
#
|
|
for FieldList in [Pcd.DefaultValues, Pcd.DefaultFromDSC,OverrideValues.get(DefaultStoreName)]:
|
|
if not FieldList:
|
|
continue
|
|
if Pcd.DefaultFromDSC and FieldList == Pcd.DefaultFromDSC:
|
|
IsArray = self.IsFieldValueAnArray(FieldList)
|
|
Value, ValueSize = ParseFieldValue (FieldList)
|
|
if isinstance(Value, str):
|
|
CApp = CApp + ' Pcd = %s; // From DSC Default Value %s\n' % (Value, Pcd.DefaultFromDSC)
|
|
elif IsArray:
|
|
#
|
|
# Use memcpy() to copy value into field
|
|
#
|
|
CApp = CApp + ' Value = %s; // From DSC Default Value %s\n' % (self.IntToCString(Value, ValueSize), Pcd.DefaultFromDSC)
|
|
CApp = CApp + ' memcpy (Pcd, Value, %d);\n' % (ValueSize)
|
|
continue
|
|
|
|
for FieldName in FieldList:
|
|
IsArray = self.IsFieldValueAnArray(FieldList[FieldName][0])
|
|
try:
|
|
Value, ValueSize = ParseFieldValue (FieldList[FieldName][0])
|
|
except Exception:
|
|
print FieldList[FieldName][0]
|
|
if isinstance(Value, str):
|
|
CApp = CApp + ' Pcd->%s = %s; // From %s Line %d Value %s\n' % (FieldName, Value, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
|
|
elif IsArray:
|
|
#
|
|
# Use memcpy() to copy value into field
|
|
#
|
|
CApp = CApp + ' FieldSize = __FIELD_SIZE(%s, %s);\n' % (Pcd.DatumType, FieldName)
|
|
CApp = CApp + ' Value = %s; // From %s Line %d Value %s\n' % (self.IntToCString(Value, ValueSize), FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
|
|
CApp = CApp + ' memcpy (&Pcd->%s[0], Value, (FieldSize > 0 && FieldSize < %d) ? FieldSize : %d);\n' % (FieldName, ValueSize, ValueSize)
|
|
else:
|
|
if ValueSize > 4:
|
|
CApp = CApp + ' Pcd->%s = %dULL; // From %s Line %d Value %s\n' % (FieldName, Value, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
|
|
else:
|
|
CApp = CApp + ' Pcd->%s = %d; // From %s Line %d Value %s\n' % (FieldName, Value, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
|
|
|
|
#
|
|
# Set new PCD value and size
|
|
#
|
|
CApp = CApp + ' PcdSetPtr (%s, %s, %s, %s, Size, (UINT8 *)Pcd);\n' % (SkuName, DefaultStoreName, Pcd.TokenSpaceGuidCName, Pcd.TokenCName)
|
|
|
|
#
|
|
# Free PCD
|
|
#
|
|
CApp = CApp + ' free (Pcd);\n'
|
|
CApp = CApp + '}\n'
|
|
CApp = CApp + '\n'
|
|
return InitByteValue, CApp
|
|
|
|
def GenerateByteArrayValue (self, StructuredPcds):
|
|
#
|
|
# Generate/Compile/Run C application to determine if there are any flexible array members
|
|
#
|
|
if not StructuredPcds:
|
|
return
|
|
|
|
InitByteValue = ""
|
|
CApp = PcdMainCHeader
|
|
|
|
Includes = {}
|
|
for PcdName in StructuredPcds:
|
|
Pcd = StructuredPcds[PcdName]
|
|
IncludeFile = Pcd.StructuredPcdIncludeFile
|
|
if IncludeFile not in Includes:
|
|
Includes[IncludeFile] = True
|
|
CApp = CApp + '#include <%s>\n' % (IncludeFile)
|
|
CApp = CApp + '\n'
|
|
|
|
for PcdName in StructuredPcds:
|
|
Pcd = StructuredPcds[PcdName]
|
|
if not Pcd.SkuOverrideValues:
|
|
InitByteValue, CApp = self.GenerateInitializeFunc(self.SkuIdMgr.SystemSkuId, 'STANDARD', Pcd, InitByteValue, CApp)
|
|
else:
|
|
for SkuName in Pcd.SkuOverrideValues:
|
|
for DefaultStoreName in Pcd.DefaultStoreName:
|
|
Pcd = StructuredPcds[PcdName]
|
|
InitByteValue, CApp = self.GenerateInitializeFunc(SkuName, DefaultStoreName, Pcd, InitByteValue, CApp)
|
|
|
|
CApp = CApp + 'VOID\n'
|
|
CApp = CApp + 'PcdEntryPoint(\n'
|
|
CApp = CApp + ' VOID\n'
|
|
CApp = CApp + ' )\n'
|
|
CApp = CApp + '{\n'
|
|
for Pcd in StructuredPcds.values():
|
|
if not Pcd.SkuOverrideValues:
|
|
CApp = CApp + ' Initialize_%s_%s_%s_%s();\n' % (self.SkuIdMgr.SystemSkuId, 'STANDARD', Pcd.TokenSpaceGuidCName, Pcd.TokenCName)
|
|
else:
|
|
for SkuName in Pcd.SkuOverrideValues:
|
|
for DefaultStoreName in Pcd.SkuOverrideValues[SkuName]:
|
|
CApp = CApp + ' Initialize_%s_%s_%s_%s();\n' % (SkuName, DefaultStoreName, Pcd.TokenSpaceGuidCName, Pcd.TokenCName)
|
|
CApp = CApp + '}\n'
|
|
|
|
CApp = CApp + PcdMainCEntry + '\n'
|
|
|
|
if not os.path.exists(self.OutputPath):
|
|
os.makedirs(self.OutputPath)
|
|
CAppBaseFileName = os.path.join(self.OutputPath, PcdValueInitName)
|
|
File = open (CAppBaseFileName + '.c', 'w')
|
|
File.write(CApp)
|
|
File.close()
|
|
|
|
MakeApp = PcdMakefileHeader
|
|
if sys.platform == "win32":
|
|
MakeApp = MakeApp + 'ARCH = IA32\nAPPNAME = %s\n' % (PcdValueInitName) + 'OBJECTS = %s\%s.obj\n' % (self.OutputPath, PcdValueInitName) + 'INC = '
|
|
else:
|
|
MakeApp = MakeApp + PcdGccMakefile
|
|
MakeApp = MakeApp + 'APPNAME = %s\n' % (PcdValueInitName) + 'OBJECTS = %s/%s.o\n' % (self.OutputPath, PcdValueInitName) + \
|
|
'include $(MAKEROOT)/Makefiles/app.makefile\n' + 'BUILD_CFLAGS += -Wno-error\n' + 'INCLUDE +='
|
|
|
|
PlatformInc = {}
|
|
for Cache in self._Bdb._CACHE_.values():
|
|
if Cache.MetaFile.Ext.lower() != '.dec':
|
|
continue
|
|
if Cache.Includes:
|
|
if str(Cache.MetaFile.Path) not in PlatformInc:
|
|
PlatformInc[str(Cache.MetaFile.Path)] = Cache.Includes
|
|
|
|
PcdDependDEC = []
|
|
for Pcd in StructuredPcds.values():
|
|
for PackageDec in Pcd.PackageDecs:
|
|
Package = os.path.normpath(mws.join(GlobalData.gWorkspace, PackageDec))
|
|
if not os.path.exists(Package):
|
|
EdkLogger.error('Build', RESOURCE_NOT_AVAILABLE, "The dependent Package %s of PCD %s.%s is not exist." % (PackageDec, Pcd.TokenSpaceGuidCName, Pcd.TokenCName))
|
|
if Package not in PcdDependDEC:
|
|
PcdDependDEC.append(Package)
|
|
|
|
if PlatformInc and PcdDependDEC:
|
|
for pkg in PcdDependDEC:
|
|
if pkg in PlatformInc:
|
|
for inc in PlatformInc[pkg]:
|
|
MakeApp += '-I' + str(inc) + ' '
|
|
MakeApp = MakeApp + '\n'
|
|
if sys.platform == "win32":
|
|
MakeApp = MakeApp + PcdMakefileEnd
|
|
MakeFileName = os.path.join(self.OutputPath, 'Makefile')
|
|
File = open (MakeFileName, 'w')
|
|
File.write(MakeApp)
|
|
File.close()
|
|
|
|
InputValueFile = os.path.join(self.OutputPath, 'Input.txt')
|
|
OutputValueFile = os.path.join(self.OutputPath, 'Output.txt')
|
|
File = open (InputValueFile, 'w')
|
|
File.write(InitByteValue)
|
|
File.close()
|
|
|
|
if sys.platform == "win32":
|
|
StdOut, StdErr = self.ExecuteCommand ('nmake clean & nmake -f %s' % (MakeFileName))
|
|
else:
|
|
StdOut, StdErr = self.ExecuteCommand ('make clean & make -f %s' % (MakeFileName))
|
|
Messages = StdOut.split('\r')
|
|
for Message in Messages:
|
|
if " error " in Message:
|
|
FileInfo = Message.strip().split('(')
|
|
if len (FileInfo) > 0:
|
|
FileName = FileInfo [0]
|
|
FileLine = FileInfo [1].split (')')[0]
|
|
else:
|
|
FileInfo = Message.strip().split(':')
|
|
FileName = FileInfo [0]
|
|
FileLine = FileInfo [1]
|
|
|
|
File = open (FileName, 'r')
|
|
FileData = File.readlines()
|
|
File.close()
|
|
error_line = FileData[int (FileLine) - 1]
|
|
if r"//" in error_line:
|
|
c_line,dsc_line = error_line.split(r"//")
|
|
else:
|
|
dsc_line = error_line
|
|
|
|
message_itmes = Message.split(":")
|
|
for item in message_itmes:
|
|
if "PcdValueInit.c" in item:
|
|
message_itmes[message_itmes.index(item)] = dsc_line.strip()
|
|
|
|
EdkLogger.error("build", PCD_STRUCTURE_PCD_ERROR, ":".join(message_itmes[1:]))
|
|
|
|
PcdValueInitExe = PcdValueInitName
|
|
if not sys.platform == "win32":
|
|
PcdValueInitExe = os.path.join(os.getenv("EDK_TOOLS_PATH"), 'Source', 'C', 'bin', PcdValueInitName)
|
|
|
|
StdOut, StdErr = self.ExecuteCommand (PcdValueInitExe + ' -i %s -o %s' % (InputValueFile, OutputValueFile))
|
|
File = open (OutputValueFile, 'r')
|
|
FileBuffer = File.readlines()
|
|
File.close()
|
|
|
|
StructurePcdSet = []
|
|
for Pcd in FileBuffer:
|
|
PcdValue = Pcd.split ('|')
|
|
PcdInfo = PcdValue[0].split ('.')
|
|
StructurePcdSet.append((PcdInfo[0],PcdInfo[1], PcdInfo[2], PcdInfo[3], PcdValue[2].strip()))
|
|
return StructurePcdSet
|
|
|
|
## Retrieve dynamic PCD settings
|
|
#
|
|
# @param Type PCD type
|
|
#
|
|
# @retval a dict object contains settings of given PCD type
|
|
#
|
|
def _GetDynamicPcd(self, Type):
|
|
|
|
|
|
Pcds = sdict()
|
|
#
|
|
# tdict is a special dict kind of type, used for selecting correct
|
|
# PCD settings for certain ARCH and SKU
|
|
#
|
|
PcdDict = tdict(True, 4)
|
|
PcdList = []
|
|
# Find out all possible PCD candidates for self._Arch
|
|
RecordList = self._RawData[Type, self._Arch]
|
|
AvailableSkuIdSet = copy.copy(self.SkuIds)
|
|
|
|
|
|
for TokenSpaceGuid, PcdCName, Setting, Arch, SkuName, Dummy3, Dummy4,Dummy5 in RecordList:
|
|
SkuName = SkuName.upper()
|
|
SkuName = 'DEFAULT' if SkuName == 'COMMON' else SkuName
|
|
if SkuName not in AvailableSkuIdSet:
|
|
EdkLogger.error('build', PARAMETER_INVALID, 'Sku %s is not defined in [SkuIds] section' % SkuName,
|
|
File=self.MetaFile, Line=Dummy5)
|
|
if "." not in TokenSpaceGuid:
|
|
PcdList.append((PcdCName, TokenSpaceGuid, SkuName, Dummy4))
|
|
PcdDict[Arch, SkuName, PcdCName, TokenSpaceGuid] = Setting
|
|
|
|
# Remove redundant PCD candidates, per the ARCH and SKU
|
|
for PcdCName, TokenSpaceGuid, SkuName, Dummy4 in PcdList:
|
|
|
|
Setting = PcdDict[self._Arch, SkuName, PcdCName, TokenSpaceGuid]
|
|
if Setting == None:
|
|
continue
|
|
|
|
PcdValue, DatumType, MaxDatumSize = self._ValidatePcd(PcdCName, TokenSpaceGuid, Setting, Type, Dummy4)
|
|
SkuInfo = SkuInfoClass(SkuName, self.SkuIds[SkuName][0], '', '', '', '', '', PcdValue)
|
|
if (PcdCName, TokenSpaceGuid) in Pcds.keys():
|
|
pcdObject = Pcds[PcdCName, TokenSpaceGuid]
|
|
pcdObject.SkuInfoList[SkuName] = SkuInfo
|
|
if MaxDatumSize.strip():
|
|
CurrentMaxSize = int(MaxDatumSize.strip(), 0)
|
|
else:
|
|
CurrentMaxSize = 0
|
|
if pcdObject.MaxDatumSize:
|
|
PcdMaxSize = int(pcdObject.MaxDatumSize, 0)
|
|
else:
|
|
PcdMaxSize = 0
|
|
if CurrentMaxSize > PcdMaxSize:
|
|
pcdObject.MaxDatumSize = str(CurrentMaxSize)
|
|
else:
|
|
Pcds[PcdCName, TokenSpaceGuid] = PcdClassObject(
|
|
PcdCName,
|
|
TokenSpaceGuid,
|
|
self._PCD_TYPE_STRING_[Type],
|
|
DatumType,
|
|
PcdValue,
|
|
'',
|
|
MaxDatumSize,
|
|
{SkuName : SkuInfo},
|
|
False,
|
|
None,
|
|
IsDsc=True)
|
|
|
|
for pcd in Pcds.values():
|
|
pcdDecObject = self._DecPcds[pcd.TokenCName, pcd.TokenSpaceGuidCName]
|
|
if 'DEFAULT' not in pcd.SkuInfoList.keys() and 'COMMON' not in pcd.SkuInfoList.keys():
|
|
valuefromDec = pcdDecObject.DefaultValue
|
|
SkuInfo = SkuInfoClass('DEFAULT', '0', '', '', '', '', '', valuefromDec)
|
|
pcd.SkuInfoList['DEFAULT'] = SkuInfo
|
|
elif 'DEFAULT' not in pcd.SkuInfoList.keys() and 'COMMON' in pcd.SkuInfoList.keys():
|
|
pcd.SkuInfoList['DEFAULT'] = pcd.SkuInfoList['COMMON']
|
|
del(pcd.SkuInfoList['COMMON'])
|
|
elif 'DEFAULT' in pcd.SkuInfoList.keys() and 'COMMON' in pcd.SkuInfoList.keys():
|
|
del(pcd.SkuInfoList['COMMON'])
|
|
if self.SkuIdMgr.SkuUsageType == self.SkuIdMgr.SINGLE:
|
|
if 'DEFAULT' in pcd.SkuInfoList.keys() and self.SkuIdMgr.SystemSkuId not in pcd.SkuInfoList.keys():
|
|
pcd.SkuInfoList[self.SkuIdMgr.SystemSkuId] = pcd.SkuInfoList['DEFAULT']
|
|
del(pcd.SkuInfoList['DEFAULT'])
|
|
|
|
return Pcds
|
|
|
|
def CompareVarAttr(self, Attr1, Attr2):
|
|
if not Attr1 or not Attr2: # for empty string
|
|
return True
|
|
Attr1s = [attr.strip() for attr in Attr1.split(",")]
|
|
Attr1Set = set(Attr1s)
|
|
Attr2s = [attr.strip() for attr in Attr2.split(",")]
|
|
Attr2Set = set(Attr2s)
|
|
if Attr2Set == Attr1Set:
|
|
return True
|
|
else:
|
|
return False
|
|
def CompletePcdValues(self,PcdSet):
|
|
Pcds = {}
|
|
DefaultStoreObj = DefaultStore(self._GetDefaultStores())
|
|
SkuIds = set([(skuid,skuobj.SkuId) for pcdobj in PcdSet.values() for skuid,skuobj in pcdobj.SkuInfoList.items()])
|
|
DefaultStores = set([storename for pcdobj in PcdSet.values() for skuobj in pcdobj.SkuInfoList.values() for storename in skuobj.DefaultStoreDict.keys()])
|
|
for PcdCName, TokenSpaceGuid in PcdSet:
|
|
PcdObj = PcdSet[(PcdCName, TokenSpaceGuid)]
|
|
if PcdObj.Type not in [self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_DEFAULT],
|
|
self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_HII],
|
|
self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_VPD],
|
|
self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_DEFAULT],
|
|
self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_HII],
|
|
self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_VPD]]:
|
|
Pcds[PcdCName, TokenSpaceGuid]= PcdObj
|
|
continue
|
|
PcdType = PcdObj.Type
|
|
if PcdType in [self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_HII], self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_HII]]:
|
|
for skuid in PcdObj.SkuInfoList:
|
|
skuobj = PcdObj.SkuInfoList[skuid]
|
|
mindefaultstorename = DefaultStoreObj.GetMin(set([defaultstorename for defaultstorename in skuobj.DefaultStoreDict]))
|
|
for defaultstorename in DefaultStores:
|
|
if defaultstorename not in skuobj.DefaultStoreDict:
|
|
skuobj.DefaultStoreDict[defaultstorename] = copy.deepcopy(skuobj.DefaultStoreDict[mindefaultstorename])
|
|
skuobj.HiiDefaultValue = skuobj.DefaultStoreDict[mindefaultstorename]
|
|
for skuname,skuid in SkuIds:
|
|
if skuname not in PcdObj.SkuInfoList:
|
|
nextskuid = self.SkuIdMgr.GetNextSkuId(skuname)
|
|
while nextskuid not in PcdObj.SkuInfoList:
|
|
nextskuid = self.SkuIdMgr.GetNextSkuId(nextskuid)
|
|
PcdObj.SkuInfoList[skuname] = copy.deepcopy(PcdObj.SkuInfoList[nextskuid])
|
|
PcdObj.SkuInfoList[skuname].SkuId = skuid
|
|
PcdObj.SkuInfoList[skuname].SkuIdName = skuname
|
|
if PcdType in [self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_HII], self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_HII]]:
|
|
PcdObj.DefaultValue = PcdObj.SkuInfoList.values()[0].HiiDefaultValue if self.SkuIdMgr.SkuUsageType == self.SkuIdMgr.SINGLE else PcdObj.SkuInfoList["DEFAULT"].HiiDefaultValue
|
|
Pcds[PcdCName, TokenSpaceGuid]= PcdObj
|
|
return Pcds
|
|
## Retrieve dynamic HII PCD settings
|
|
#
|
|
# @param Type PCD type
|
|
#
|
|
# @retval a dict object contains settings of given PCD type
|
|
#
|
|
def _GetDynamicHiiPcd(self, Type):
|
|
|
|
VariableAttrs = {}
|
|
|
|
Pcds = sdict()
|
|
#
|
|
# tdict is a special dict kind of type, used for selecting correct
|
|
# PCD settings for certain ARCH and SKU
|
|
#
|
|
PcdDict = tdict(True, 5)
|
|
PcdSet = set()
|
|
RecordList = self._RawData[Type, self._Arch]
|
|
# Find out all possible PCD candidates for self._Arch
|
|
AvailableSkuIdSet = copy.copy(self.SkuIds)
|
|
DefaultStoresDefine = self._GetDefaultStores()
|
|
|
|
for TokenSpaceGuid, PcdCName, Setting, Arch, SkuName, DefaultStore, Dummy4,Dummy5 in RecordList:
|
|
SkuName = SkuName.upper()
|
|
SkuName = 'DEFAULT' if SkuName == 'COMMON' else SkuName
|
|
DefaultStore = DefaultStore.upper()
|
|
if DefaultStore == "COMMON":
|
|
DefaultStore = "STANDARD"
|
|
if SkuName not in AvailableSkuIdSet:
|
|
EdkLogger.error('build', PARAMETER_INVALID, 'Sku %s is not defined in [SkuIds] section' % SkuName,
|
|
File=self.MetaFile, Line=Dummy5)
|
|
if DefaultStore not in DefaultStoresDefine:
|
|
EdkLogger.error('build', PARAMETER_INVALID, 'DefaultStores %s is not defined in [DefaultStores] section' % DefaultStore,
|
|
File=self.MetaFile, Line=Dummy5)
|
|
if "." not in TokenSpaceGuid:
|
|
PcdSet.add((PcdCName, TokenSpaceGuid, SkuName,DefaultStore, Dummy4))
|
|
PcdDict[Arch, SkuName, PcdCName, TokenSpaceGuid,DefaultStore] = Setting
|
|
|
|
|
|
# Remove redundant PCD candidates, per the ARCH and SKU
|
|
for PcdCName, TokenSpaceGuid, SkuName,DefaultStore, Dummy4 in PcdSet:
|
|
|
|
Setting = PcdDict[self._Arch, SkuName, PcdCName, TokenSpaceGuid,DefaultStore]
|
|
if Setting == None:
|
|
continue
|
|
VariableName, VariableGuid, VariableOffset, DefaultValue, VarAttribute = self._ValidatePcd(PcdCName, TokenSpaceGuid, Setting, Type, Dummy4)
|
|
|
|
rt, Msg = VariableAttributes.ValidateVarAttributes(VarAttribute)
|
|
if not rt:
|
|
EdkLogger.error("build", PCD_VARIABLE_ATTRIBUTES_ERROR, "Variable attributes settings for %s is incorrect.\n %s" % (".".join((TokenSpaceGuid, PcdCName)), Msg),
|
|
ExtraData="[%s]" % VarAttribute)
|
|
ExceedMax = False
|
|
FormatCorrect = True
|
|
if VariableOffset.isdigit():
|
|
if int(VariableOffset, 10) > 0xFFFF:
|
|
ExceedMax = True
|
|
elif re.match(r'[\t\s]*0[xX][a-fA-F0-9]+$', VariableOffset):
|
|
if int(VariableOffset, 16) > 0xFFFF:
|
|
ExceedMax = True
|
|
# For Offset written in "A.B"
|
|
elif VariableOffset.find('.') > -1:
|
|
VariableOffsetList = VariableOffset.split(".")
|
|
if not (len(VariableOffsetList) == 2
|
|
and IsValidWord(VariableOffsetList[0])
|
|
and IsValidWord(VariableOffsetList[1])):
|
|
FormatCorrect = False
|
|
else:
|
|
FormatCorrect = False
|
|
if not FormatCorrect:
|
|
EdkLogger.error('Build', FORMAT_INVALID, "Invalid syntax or format of the variable offset value is incorrect for %s." % ".".join((TokenSpaceGuid, PcdCName)))
|
|
|
|
if ExceedMax:
|
|
EdkLogger.error('Build', OPTION_VALUE_INVALID, "The variable offset value must not exceed the maximum value of 0xFFFF (UINT16) for %s." % ".".join((TokenSpaceGuid, PcdCName)))
|
|
if (VariableName, VariableGuid) not in VariableAttrs:
|
|
VariableAttrs[(VariableName, VariableGuid)] = VarAttribute
|
|
else:
|
|
if not self.CompareVarAttr(VariableAttrs[(VariableName, VariableGuid)], VarAttribute):
|
|
EdkLogger.error('Build', PCD_VARIABLE_ATTRIBUTES_CONFLICT_ERROR, "The variable %s.%s for DynamicHii PCDs has conflicting attributes [%s] and [%s] " % (VariableGuid, VariableName, VarAttribute, VariableAttrs[(VariableName, VariableGuid)]))
|
|
|
|
pcdDecObject = self._DecPcds[PcdCName, TokenSpaceGuid]
|
|
if (PcdCName, TokenSpaceGuid) in Pcds.keys():
|
|
pcdObject = Pcds[PcdCName, TokenSpaceGuid]
|
|
if SkuName in pcdObject.SkuInfoList:
|
|
Skuitem = pcdObject.SkuInfoList[SkuName]
|
|
Skuitem.DefaultStoreDict.update({DefaultStore:DefaultValue})
|
|
else:
|
|
SkuInfo = SkuInfoClass(SkuName, self.SkuIds[SkuName][0], VariableName, VariableGuid, VariableOffset, DefaultValue, VariableAttribute=VarAttribute,DefaultStore={DefaultStore:DefaultValue})
|
|
pcdObject.SkuInfoList[SkuName] = SkuInfo
|
|
else:
|
|
SkuInfo = SkuInfoClass(SkuName, self.SkuIds[SkuName][0], VariableName, VariableGuid, VariableOffset, DefaultValue, VariableAttribute=VarAttribute,DefaultStore={DefaultStore:DefaultValue})
|
|
Pcds[PcdCName, TokenSpaceGuid] = PcdClassObject(
|
|
PcdCName,
|
|
TokenSpaceGuid,
|
|
self._PCD_TYPE_STRING_[Type],
|
|
'',
|
|
DefaultValue,
|
|
'',
|
|
'',
|
|
{SkuName : SkuInfo},
|
|
False,
|
|
None,
|
|
pcdDecObject.validateranges,
|
|
pcdDecObject.validlists,
|
|
pcdDecObject.expressions,
|
|
IsDsc=True)
|
|
|
|
|
|
for pcd in Pcds.values():
|
|
SkuInfoObj = pcd.SkuInfoList.values()[0]
|
|
pcdDecObject = self._DecPcds[pcd.TokenCName, pcd.TokenSpaceGuidCName]
|
|
# Only fix the value while no value provided in DSC file.
|
|
for sku in pcd.SkuInfoList.values():
|
|
if (sku.HiiDefaultValue == "" or sku.HiiDefaultValue == None):
|
|
sku.HiiDefaultValue = pcdDecObject.DefaultValue
|
|
if 'DEFAULT' not in pcd.SkuInfoList.keys() and 'COMMON' not in pcd.SkuInfoList.keys():
|
|
valuefromDec = pcdDecObject.DefaultValue
|
|
SkuInfo = SkuInfoClass('DEFAULT', '0', SkuInfoObj.VariableName, SkuInfoObj.VariableGuid, SkuInfoObj.VariableOffset, valuefromDec,VariableAttribute=SkuInfoObj.VariableAttribute,DefaultStore={DefaultStore:valuefromDec})
|
|
pcd.SkuInfoList['DEFAULT'] = SkuInfo
|
|
elif 'DEFAULT' not in pcd.SkuInfoList.keys() and 'COMMON' in pcd.SkuInfoList.keys():
|
|
pcd.SkuInfoList['DEFAULT'] = pcd.SkuInfoList['COMMON']
|
|
del(pcd.SkuInfoList['COMMON'])
|
|
elif 'DEFAULT' in pcd.SkuInfoList.keys() and 'COMMON' in pcd.SkuInfoList.keys():
|
|
del(pcd.SkuInfoList['COMMON'])
|
|
|
|
if self.SkuIdMgr.SkuUsageType == self.SkuIdMgr.SINGLE:
|
|
if 'DEFAULT' in pcd.SkuInfoList.keys() and self.SkuIdMgr.SystemSkuId not in pcd.SkuInfoList.keys():
|
|
pcd.SkuInfoList[self.SkuIdMgr.SystemSkuId] = pcd.SkuInfoList['DEFAULT']
|
|
del(pcd.SkuInfoList['DEFAULT'])
|
|
|
|
if pcd.MaxDatumSize.strip():
|
|
MaxSize = int(pcd.MaxDatumSize, 0)
|
|
else:
|
|
MaxSize = 0
|
|
if pcdDecObject.DatumType == 'VOID*':
|
|
for (_, skuobj) in pcd.SkuInfoList.items():
|
|
datalen = 0
|
|
if skuobj.HiiDefaultValue.startswith("L"):
|
|
datalen = (len(skuobj.HiiDefaultValue) - 3 + 1) * 2
|
|
elif skuobj.HiiDefaultValue.startswith("{"):
|
|
datalen = len(skuobj.HiiDefaultValue.split(","))
|
|
else:
|
|
datalen = len(skuobj.HiiDefaultValue) - 2 + 1
|
|
if datalen > MaxSize:
|
|
MaxSize = datalen
|
|
pcd.MaxDatumSize = str(MaxSize)
|
|
rt, invalidhii = self.CheckVariableNameAssignment(Pcds)
|
|
if not rt:
|
|
invalidpcd = ",".join(invalidhii)
|
|
EdkLogger.error('build', PCD_VARIABLE_INFO_ERROR, Message='The same HII PCD must map to the same EFI variable for all SKUs', File=self.MetaFile, ExtraData=invalidpcd)
|
|
return Pcds
|
|
|
|
def CheckVariableNameAssignment(self,Pcds):
|
|
invalidhii = []
|
|
for pcdname in Pcds:
|
|
pcd = Pcds[pcdname]
|
|
varnameset = set([sku.VariableName for (skuid,sku) in pcd.SkuInfoList.items()])
|
|
if len(varnameset) > 1:
|
|
invalidhii.append(".".join((pcdname[1],pcdname[0])))
|
|
if len(invalidhii):
|
|
return False,invalidhii
|
|
else:
|
|
return True, []
|
|
## Retrieve dynamic VPD PCD settings
|
|
#
|
|
# @param Type PCD type
|
|
#
|
|
# @retval a dict object contains settings of given PCD type
|
|
#
|
|
def _GetDynamicVpdPcd(self, Type):
|
|
|
|
|
|
Pcds = sdict()
|
|
#
|
|
# tdict is a special dict kind of type, used for selecting correct
|
|
# PCD settings for certain ARCH and SKU
|
|
#
|
|
PcdDict = tdict(True, 4)
|
|
PcdList = []
|
|
|
|
# Find out all possible PCD candidates for self._Arch
|
|
RecordList = self._RawData[Type, self._Arch]
|
|
AvailableSkuIdSet = copy.copy(self.SkuIds)
|
|
|
|
for TokenSpaceGuid, PcdCName, Setting, Arch, SkuName, Dummy3, Dummy4,Dummy5 in RecordList:
|
|
SkuName = SkuName.upper()
|
|
SkuName = 'DEFAULT' if SkuName == 'COMMON' else SkuName
|
|
if SkuName not in AvailableSkuIdSet:
|
|
EdkLogger.error('build', PARAMETER_INVALID, 'Sku %s is not defined in [SkuIds] section' % SkuName,
|
|
File=self.MetaFile, Line=Dummy5)
|
|
if "." not in TokenSpaceGuid:
|
|
PcdList.append((PcdCName, TokenSpaceGuid, SkuName, Dummy4))
|
|
PcdDict[Arch, SkuName, PcdCName, TokenSpaceGuid] = Setting
|
|
|
|
# Remove redundant PCD candidates, per the ARCH and SKU
|
|
for PcdCName, TokenSpaceGuid, SkuName, Dummy4 in PcdList:
|
|
Setting = PcdDict[self._Arch, SkuName, PcdCName, TokenSpaceGuid]
|
|
if Setting == None:
|
|
continue
|
|
#
|
|
# For the VOID* type, it can have optional data of MaxDatumSize and InitialValue
|
|
# For the Integer & Boolean type, the optional data can only be InitialValue.
|
|
# At this point, we put all the data into the PcdClssObject for we don't know the PCD's datumtype
|
|
# until the DEC parser has been called.
|
|
#
|
|
VpdOffset, MaxDatumSize, InitialValue = self._ValidatePcd(PcdCName, TokenSpaceGuid, Setting, Type, Dummy4)
|
|
SkuInfo = SkuInfoClass(SkuName, self.SkuIds[SkuName][0], '', '', '', '', VpdOffset, InitialValue)
|
|
if (PcdCName, TokenSpaceGuid) in Pcds.keys():
|
|
pcdObject = Pcds[PcdCName, TokenSpaceGuid]
|
|
pcdObject.SkuInfoList[SkuName] = SkuInfo
|
|
if MaxDatumSize.strip():
|
|
CurrentMaxSize = int(MaxDatumSize.strip(), 0)
|
|
else:
|
|
CurrentMaxSize = 0
|
|
if pcdObject.MaxDatumSize:
|
|
PcdMaxSize = int(pcdObject.MaxDatumSize, 0)
|
|
else:
|
|
PcdMaxSize = 0
|
|
if CurrentMaxSize > PcdMaxSize:
|
|
pcdObject.MaxDatumSize = str(CurrentMaxSize)
|
|
else:
|
|
Pcds[PcdCName, TokenSpaceGuid] = PcdClassObject(
|
|
PcdCName,
|
|
TokenSpaceGuid,
|
|
self._PCD_TYPE_STRING_[Type],
|
|
'',
|
|
InitialValue,
|
|
'',
|
|
MaxDatumSize,
|
|
{SkuName : SkuInfo},
|
|
False,
|
|
None,
|
|
IsDsc=True)
|
|
for pcd in Pcds.values():
|
|
SkuInfoObj = pcd.SkuInfoList.values()[0]
|
|
pcdDecObject = self._DecPcds[pcd.TokenCName, pcd.TokenSpaceGuidCName]
|
|
if 'DEFAULT' not in pcd.SkuInfoList.keys() and 'COMMON' not in pcd.SkuInfoList.keys():
|
|
valuefromDec = pcdDecObject.DefaultValue
|
|
SkuInfo = SkuInfoClass('DEFAULT', '0', '', '', '', '', SkuInfoObj.VpdOffset, valuefromDec)
|
|
pcd.SkuInfoList['DEFAULT'] = SkuInfo
|
|
elif 'DEFAULT' not in pcd.SkuInfoList.keys() and 'COMMON' in pcd.SkuInfoList.keys():
|
|
pcd.SkuInfoList['DEFAULT'] = pcd.SkuInfoList['COMMON']
|
|
del(pcd.SkuInfoList['COMMON'])
|
|
elif 'DEFAULT' in pcd.SkuInfoList.keys() and 'COMMON' in pcd.SkuInfoList.keys():
|
|
del(pcd.SkuInfoList['COMMON'])
|
|
if self.SkuIdMgr.SkuUsageType == self.SkuIdMgr.SINGLE:
|
|
if 'DEFAULT' in pcd.SkuInfoList.keys() and self.SkuIdMgr.SystemSkuId not in pcd.SkuInfoList.keys():
|
|
pcd.SkuInfoList[self.SkuIdMgr.SystemSkuId] = pcd.SkuInfoList['DEFAULT']
|
|
del(pcd.SkuInfoList['DEFAULT'])
|
|
|
|
return Pcds
|
|
|
|
## Add external modules
|
|
#
|
|
# The external modules are mostly those listed in FDF file, which don't
|
|
# need "build".
|
|
#
|
|
# @param FilePath The path of module description file
|
|
#
|
|
def AddModule(self, FilePath):
|
|
FilePath = NormPath(FilePath)
|
|
if FilePath not in self.Modules:
|
|
Module = ModuleBuildClassObject()
|
|
Module.MetaFile = FilePath
|
|
self.Modules.append(Module)
|
|
|
|
## Add external PCDs
|
|
#
|
|
# The external PCDs are mostly those listed in FDF file to specify address
|
|
# or offset information.
|
|
#
|
|
# @param Name Name of the PCD
|
|
# @param Guid Token space guid of the PCD
|
|
# @param Value Value of the PCD
|
|
#
|
|
def AddPcd(self, Name, Guid, Value):
|
|
if (Name, Guid) not in self.Pcds:
|
|
self.Pcds[Name, Guid] = PcdClassObject(Name, Guid, '', '', '', '', '', {}, False, None)
|
|
self.Pcds[Name, Guid].DefaultValue = Value
|
|
|
|
_Macros = property(_GetMacros)
|
|
Arch = property(_GetArch, _SetArch)
|
|
Platform = property(_GetPlatformName)
|
|
PlatformName = property(_GetPlatformName)
|
|
Guid = property(_GetFileGuid)
|
|
Version = property(_GetVersion)
|
|
DscSpecification = property(_GetDscSpec)
|
|
OutputDirectory = property(_GetOutpuDir)
|
|
SupArchList = property(_GetSupArch)
|
|
BuildTargets = property(_GetBuildTarget)
|
|
SkuName = property(_GetSkuName, _SetSkuName)
|
|
SkuIdentifier = property(_GetSkuIdentifier)
|
|
AvilableSkuIds = property(_GetAviableSkuIds)
|
|
PcdInfoFlag = property(_GetPcdInfoFlag)
|
|
VarCheckFlag = property(_GetVarCheckFlag)
|
|
FlashDefinition = property(_GetFdfFile)
|
|
Prebuild = property(_GetPrebuild)
|
|
Postbuild = property(_GetPostbuild)
|
|
BuildNumber = property(_GetBuildNumber)
|
|
MakefileName = property(_GetMakefileName)
|
|
BsBaseAddress = property(_GetBsBaseAddress)
|
|
RtBaseAddress = property(_GetRtBaseAddress)
|
|
LoadFixAddress = property(_GetLoadFixAddress)
|
|
RFCLanguages = property(_GetRFCLanguages)
|
|
ISOLanguages = property(_GetISOLanguages)
|
|
VpdToolGuid = property(_GetVpdToolGuid)
|
|
SkuIds = property(_GetSkuIds)
|
|
Modules = property(_GetModules)
|
|
LibraryInstances = property(_GetLibraryInstances)
|
|
LibraryClasses = property(_GetLibraryClasses)
|
|
Pcds = property(_GetPcds)
|
|
BuildOptions = property(_GetBuildOptions)
|