## @file\r
# This file is used to create a database used by build tool\r
#\r
-# Copyright (c) 2008 - 2014, Intel Corporation. All rights reserved.<BR>\r
+# Copyright (c) 2008 - 2015, Intel Corporation. All rights reserved.<BR>\r
# This program and the accompanying materials\r
# are licensed and made available under the terms and conditions of the BSD License\r
# which accompanies this distribution. The full text of the license may be found at\r
# Import Modules\r
#\r
import sqlite3\r
-import os\r
-import os.path\r
+import Common.LongFilePathOs as os\r
import pickle\r
import uuid\r
\r
from BuildClassObject import *\r
from WorkspaceCommon import GetDeclaredPcd\r
from Common.Misc import AnalyzeDscPcd\r
+from Common.Misc import ProcessDuplicatedInf\r
import re\r
+from Common.Parsing import IsValidWord\r
+from Common.VariableAttributes import VariableAttributes\r
+import Common.GlobalData as GlobalData\r
\r
## Platform build information from DSC file\r
#\r
self._Target = Target\r
self._Toolchain = Toolchain\r
self._Clear()\r
+ self._HandleOverridePath()\r
\r
## XXX[key] = value\r
def __setitem__(self, key, value):\r
self._BuildTargets = None\r
self._SkuName = None\r
self._SkuIdentifier = None\r
+ self._AvilableSkuIds = None\r
self._PcdInfoFlag = None\r
+ self._VarCheckFlag = None\r
self._FlashDefinition = None\r
self._BuildNumber = None\r
self._MakefileName = None\r
self._VpdToolGuid = None\r
self.__Macros = None\r
\r
+\r
+ ## handle Override Path of Module\r
+ def _HandleOverridePath(self):\r
+ RecordList = self._RawData[MODEL_META_DATA_COMPONENT, self._Arch]\r
+ Macros = self._Macros\r
+ Macros["EDK_SOURCE"] = GlobalData.gEcpSource\r
+ for Record in RecordList:\r
+ ModuleId = Record[5]\r
+ LineNo = Record[6]\r
+ ModuleFile = PathClass(NormPath(Record[0]), GlobalData.gWorkspace, Arch=self._Arch)\r
+ RecordList = self._RawData[MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH, self._Arch, None, ModuleId]\r
+ if RecordList != []:\r
+ SourceOverridePath = os.path.join(GlobalData.gWorkspace, NormPath(RecordList[0][0]))\r
+\r
+ # Check if the source override path exists\r
+ if not os.path.isdir(SourceOverridePath):\r
+ EdkLogger.error('build', FILE_NOT_FOUND, Message='Source override path does not exist:', File=self.MetaFile, ExtraData=SourceOverridePath, Line=LineNo)\r
+\r
+ #Add to GlobalData Variables\r
+ GlobalData.gOverrideDir[ModuleFile.Key] = SourceOverridePath\r
+\r
## Get current effective macros\r
def _GetMacros(self):\r
if self.__Macros == None:\r
if self._SkuName == None:\r
self._SkuName = Record[2]\r
self._SkuIdentifier = Record[2]\r
+ self._AvilableSkuIds = Record[2]\r
elif Name == TAB_DSC_DEFINES_PCD_INFO_GENERATION:\r
self._PcdInfoFlag = Record[2]\r
+ elif Name == TAB_DSC_DEFINES_PCD_VAR_CHECK_GENERATION:\r
+ self._VarCheckFlag = Record[2]\r
elif Name == TAB_FIX_LOAD_TOP_MEMORY_ADDRESS:\r
try:\r
self._LoadFixAddress = int (Record[2], 0)\r
return True\r
else:\r
return False\r
- \r
+ def _GetVarCheckFlag(self): \r
+ if self._VarCheckFlag == None or self._VarCheckFlag.upper() == 'FALSE':\r
+ return False\r
+ elif self._VarCheckFlag.upper() == 'TRUE':\r
+ return True\r
+ else:\r
+ return False\r
+ def _GetAviableSkuIds(self):\r
+ if self._AvilableSkuIds:\r
+ return self._AvilableSkuIds\r
+ return self.SkuIdentifier\r
def _GetSkuIdentifier(self):\r
if self._SkuName:\r
return self._SkuName\r
Macros = self._Macros\r
Macros["EDK_SOURCE"] = GlobalData.gEcpSource\r
for Record in RecordList:\r
+ DuplicatedFile = False\r
ModuleFile = PathClass(NormPath(Record[0], Macros), GlobalData.gWorkspace, Arch=self._Arch)\r
ModuleId = Record[5]\r
LineNo = Record[6]\r
# Check duplication\r
# If arch is COMMON, no duplicate module is checked since all modules in all component sections are selected\r
if self._Arch != 'COMMON' and ModuleFile in self._Modules:\r
- EdkLogger.error('build', FILE_DUPLICATED, File=self.MetaFile, ExtraData=str(ModuleFile), Line=LineNo)\r
+ DuplicatedFile = True\r
\r
Module = ModuleBuildClassObject()\r
Module.MetaFile = ModuleFile\r
\r
- # get module override path\r
- RecordList = self._RawData[MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH, self._Arch, None, ModuleId]\r
- if RecordList != []:\r
- Module.SourceOverridePath = os.path.join(GlobalData.gWorkspace, NormPath(RecordList[0][0], Macros))\r
-\r
- # Check if the source override path exists\r
- if not os.path.isdir(Module.SourceOverridePath):\r
- EdkLogger.error('build', FILE_NOT_FOUND, Message = 'Source override path does not exist:', File=self.MetaFile, ExtraData=Module.SourceOverridePath, Line=LineNo)\r
- \r
- #Add to GlobalData Variables\r
- GlobalData.gOverrideDir[ModuleFile.Key] = Module.SourceOverridePath\r
-\r
# get module private library instance\r
RecordList = self._RawData[MODEL_EFI_LIBRARY_CLASS, self._Arch, None, ModuleId]\r
for Record in RecordList:\r
OptionString = Module.BuildOptions[ToolChainFamily, ToolChain]\r
Module.BuildOptions[ToolChainFamily, ToolChain] = OptionString + " " + Option\r
\r
+ RecordList = self._RawData[MODEL_META_DATA_HEADER, self._Arch, None, ModuleId]\r
+ if DuplicatedFile and not RecordList:\r
+ EdkLogger.error('build', FILE_DUPLICATED, File=self.MetaFile, ExtraData=str(ModuleFile), Line=LineNo)\r
+ if RecordList:\r
+ if len(RecordList) != 1:\r
+ EdkLogger.error('build', OPTION_UNKNOWN, 'Only FILE_GUID can be listed in <Defines> section.',\r
+ File=self.MetaFile, ExtraData=str(ModuleFile), Line=LineNo)\r
+ ModuleFile = ProcessDuplicatedInf(ModuleFile, RecordList[0][2], GlobalData.gWorkspace)\r
+ ModuleFile.Arch = self._Arch\r
+\r
self._Modules[ModuleFile] = Module\r
return self._Modules\r
\r
def _ValidatePcd(self, PcdCName, TokenSpaceGuid, Setting, PcdType, LineNo):\r
if self._DecPcds == None:\r
self._DecPcds = GetDeclaredPcd(self, self._Bdb, self._Arch, self._Target, self._Toolchain)\r
+ FdfInfList = []\r
+ if GlobalData.gFdfParser:\r
+ FdfInfList = GlobalData.gFdfParser.Profile.InfList\r
+\r
+ PkgSet = set()\r
+ for Inf in FdfInfList:\r
+ ModuleFile = PathClass(NormPath(Inf), GlobalData.gWorkspace, Arch=self._Arch)\r
+ if ModuleFile in self._Modules:\r
+ continue\r
+ ModuleData = self._Bdb[ModuleFile, self._Arch, self._Target, self._Toolchain]\r
+ PkgSet.update(ModuleData.Packages)\r
+ DecPcds = {}\r
+ for Pkg in PkgSet:\r
+ for Pcd in Pkg.Pcds:\r
+ DecPcds[Pcd[0], Pcd[1]] = Pkg.Pcds[Pcd]\r
+ self._DecPcds.update(DecPcds)\r
+\r
if (PcdCName, TokenSpaceGuid) not in self._DecPcds:\r
EdkLogger.error('build', PARSER_ERROR,\r
- "Pcd (%s.%s) defined in DSC is not declared in DEC files." % (TokenSpaceGuid, PcdCName),\r
+ "Pcd (%s.%s) defined in DSC is not declared in DEC files. Arch: ['%s']" % (TokenSpaceGuid, PcdCName, self._Arch),\r
File=self.MetaFile, Line=LineNo)\r
ValueList, IsValid, Index = AnalyzeDscPcd(Setting, PcdType, self._DecPcds[PcdCName, TokenSpaceGuid].DatumType)\r
if not IsValid and PcdType not in [MODEL_PCD_FEATURE_FLAG, MODEL_PCD_FIXED_AT_BUILD]:\r
\r
return Pcds\r
\r
+ def CompareVarAttr(self, Attr1, Attr2):\r
+ if not Attr1 or not Attr2: # for empty string\r
+ return True\r
+ Attr1s = [attr.strip() for attr in Attr1.split(",")]\r
+ Attr1Set = set(Attr1s)\r
+ Attr2s = [attr.strip() for attr in Attr2.split(",")]\r
+ Attr2Set = set(Attr2s)\r
+ if Attr2Set == Attr1Set:\r
+ return True\r
+ else:\r
+ return False\r
## Retrieve dynamic HII PCD settings\r
#\r
# @param Type PCD type\r
def _GetDynamicHiiPcd(self, Type):\r
\r
SkuObj = SkuClass(self.SkuIdentifier,self.SkuIds)\r
+ VariableAttrs = {}\r
\r
Pcds = sdict()\r
#\r
Setting = PcdDict[self._Arch, SkuName, PcdCName, TokenSpaceGuid]\r
if Setting == None:\r
continue\r
- VariableName, VariableGuid, VariableOffset, DefaultValue = self._ValidatePcd(PcdCName, TokenSpaceGuid, Setting, Type, Dummy4)\r
+ VariableName, VariableGuid, VariableOffset, DefaultValue, VarAttribute = self._ValidatePcd(PcdCName, TokenSpaceGuid, Setting, Type, Dummy4)\r
\r
+ rt, Msg = VariableAttributes.ValidateVarAttributes(VarAttribute)\r
+ if not rt:\r
+ EdkLogger.error("build", PCD_VARIABLE_ATTRIBUTES_ERROR, "Variable attributes settings for %s is incorrect.\n %s" % (".".join((TokenSpaceGuid, PcdCName)), Msg),\r
+ ExtraData = "[%s]" % VarAttribute)\r
ExceedMax = False\r
+ FormatCorrect = True\r
if VariableOffset.isdigit():\r
if int(VariableOffset,10) > 0xFFFF:\r
ExceedMax = True\r
elif re.match(r'[\t\s]*0[xX][a-fA-F0-9]+$',VariableOffset):\r
if int(VariableOffset,16) > 0xFFFF:\r
ExceedMax = True\r
+ # For Offset written in "A.B"\r
+ elif VariableOffset.find('.') > -1:\r
+ VariableOffsetList = VariableOffset.split(".")\r
+ if not (len(VariableOffsetList) == 2\r
+ and IsValidWord(VariableOffsetList[0])\r
+ and IsValidWord(VariableOffsetList[1])):\r
+ FormatCorrect = False\r
else:\r
+ FormatCorrect = False\r
+ if not FormatCorrect:\r
EdkLogger.error('Build', FORMAT_INVALID, "Invalid syntax or format of the variable offset value is incorrect for %s." % ".".join((TokenSpaceGuid,PcdCName)))\r
\r
if ExceedMax:\r
EdkLogger.error('Build', OPTION_VALUE_INVALID, "The variable offset value must not exceed the maximum value of 0xFFFF (UINT16) for %s." % ".".join((TokenSpaceGuid,PcdCName)))\r
+ if (VariableName, VariableGuid) not in VariableAttrs:\r
+ VariableAttrs[(VariableName, VariableGuid)] = VarAttribute\r
+ else:\r
+ if not self.CompareVarAttr(VariableAttrs[(VariableName, VariableGuid)], VarAttribute):\r
+ 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)]))\r
\r
- SkuInfo = SkuInfoClass(SkuName, self.SkuIds[SkuName], VariableName, VariableGuid, VariableOffset, DefaultValue)\r
+ SkuInfo = SkuInfoClass(SkuName, self.SkuIds[SkuName], VariableName, VariableGuid, VariableOffset, DefaultValue, VariableAttribute = VarAttribute)\r
+ pcdDecObject = self._DecPcds[PcdCName, TokenSpaceGuid]\r
if (PcdCName,TokenSpaceGuid) in Pcds.keys(): \r
pcdObject = Pcds[PcdCName,TokenSpaceGuid]\r
pcdObject.SkuInfoList[SkuName] = SkuInfo\r
'',\r
{SkuName : SkuInfo},\r
False,\r
- None\r
+ None,\r
+ pcdDecObject.validateranges,\r
+ pcdDecObject.validlists,\r
+ pcdDecObject.expressions\r
)\r
\r
\r
BuildTargets = property(_GetBuildTarget)\r
SkuName = property(_GetSkuName, _SetSkuName)\r
SkuIdentifier = property(_GetSkuIdentifier)\r
+ AvilableSkuIds = property(_GetAviableSkuIds)\r
PcdInfoFlag = property(_GetPcdInfoFlag)\r
+ VarCheckFlag = property(_GetVarCheckFlag)\r
FlashDefinition = property(_GetFdfFile)\r
BuildNumber = property(_GetBuildNumber)\r
MakefileName = property(_GetMakefileName)\r
\r
DefaultValue, DatumType, TokenNumber = AnalyzePcdData(Setting)\r
\r
+ validateranges, validlists, expressions = self._RawData.GetValidExpression(TokenSpaceGuid, PcdCName) \r
Pcds[PcdCName, TokenSpaceGuid, self._PCD_TYPE_STRING_[Type]] = PcdClassObject(\r
PcdCName,\r
TokenSpaceGuid,\r
'',\r
{},\r
False,\r
- None\r
+ None,\r
+ list(validateranges),\r
+ list(validlists),\r
+ list(expressions)\r
)\r
return Pcds\r
\r
# items defined _PROPERTY_ don't need additional processing\r
if Name in self:\r
self[Name] = Value\r
+ if self._Defs == None:\r
+ self._Defs = sdict()\r
+ self._Defs[Name] = Value\r
# some special items in [Defines] section need special treatment\r
elif Name in ('EFI_SPECIFICATION_VERSION', 'UEFI_SPECIFICATION_VERSION', 'EDK_RELEASE_VERSION', 'PI_SPECIFICATION_VERSION'):\r
if Name in ('EFI_SPECIFICATION_VERSION', 'UEFI_SPECIFICATION_VERSION'):\r
return self._Defs\r
\r
## Retrieve binary files\r
- def _GetBinaryFiles(self):\r
+ def _GetBinaries(self):\r
if self._Binaries == None:\r
self._Binaries = []\r
RecordList = self._RawData[MODEL_EFI_BINARY_FILE, self._Arch, self._Platform]\r
self._Binaries.append(File)\r
return self._Binaries\r
\r
+ ## Retrieve binary files with error check.\r
+ def _GetBinaryFiles(self):\r
+ Binaries = self._GetBinaries()\r
+ if GlobalData.gIgnoreSource and Binaries == []:\r
+ ErrorInfo = "The INF file does not contain any Binaries to use in creating the image\n"\r
+ EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, ExtraData=ErrorInfo, File=self.MetaFile)\r
+\r
+ return Binaries\r
+ ## Check whether it exists the binaries with current ARCH in AsBuild INF\r
+ def _IsSupportedArch(self):\r
+ if self._GetBinaries() and not self._GetSourceFiles():\r
+ return True\r
+ else:\r
+ return False\r
## Retrieve source files\r
def _GetSourceFiles(self):\r
+ #Ignore all source files in a binary build mode\r
+ if GlobalData.gIgnoreSource:\r
+ self._Sources = []\r
+ return self._Sources\r
+\r
if self._Sources == None:\r
self._Sources = []\r
RecordList = self._RawData[MODEL_EFI_SOURCE_FILE, self._Arch, self._Platform]\r
EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "No [Depex] section or no valid expression in [Depex] section for [%s] module" \\r
% self.ModuleType, File=self.MetaFile)\r
\r
+ if len(RecordList) != 0 and self.ModuleType == 'USER_DEFINED':\r
+ for Record in RecordList:\r
+ if Record[4] not in ['PEIM', 'DXE_DRIVER', 'DXE_SMM_DRIVER']:\r
+ EdkLogger.error('build', FORMAT_INVALID,\r
+ "'%s' module must specify the type of [Depex] section" % self.ModuleType,\r
+ File=self.MetaFile)\r
+\r
Depex = sdict()\r
for Record in RecordList:\r
DepexStr = ReplaceMacro(Record[0], self._Macros, False)\r
Depex = property(_GetDepex)\r
DepexExpression = property(_GetDepexExpression)\r
IsBinaryModule = property(_IsBinaryModule)\r
+ IsSupportedArch = property(_IsSupportedArch)\r
\r
## Database\r
#\r
#\r
class WorkspaceDatabase(object):\r
\r
- # default database file path\r
- _DB_PATH_ = "Conf/.cache/build.db"\r
\r
#\r
# internal class used for call corresponding file parser and caching the result\r
def __init__(self, DbPath, RenewDb=False):\r
self._DbClosedFlag = False\r
if not DbPath:\r
- DbPath = os.path.normpath(os.path.join(GlobalData.gWorkspace, self._DB_PATH_))\r
+ DbPath = os.path.normpath(os.path.join(GlobalData.gWorkspace, 'Conf', GlobalData.gDatabasePath))\r
\r
# don't create necessary path for db in memory\r
if DbPath != ':memory:':\r