## @file\r
# This file is used to parse meta files\r
#\r
-# Copyright (c) 2008 - 2014, Intel Corporation. All rights reserved.<BR>\r
+# Copyright (c) 2008 - 2016, Intel Corporation. All rights reserved.<BR>\r
+# (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP<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
from CommonDataClass.DataClass import *\r
from Common.DataType import *\r
from Common.String import *\r
-from Common.Misc import GuidStructureStringToGuidString, CheckPcdDatum, PathClass, AnalyzePcdData, AnalyzeDscPcd\r
+from Common.Misc import GuidStructureStringToGuidString, CheckPcdDatum, PathClass, AnalyzePcdData, AnalyzeDscPcd, AnalyzePcdExpression\r
from Common.Expression import *\r
from CommonDataClass.Exceptions import *\r
from Common.LongFilePathSupport import OpenLongFilePath as open\r
#\r
# @param FilePath The path of platform description file\r
# @param FileType The raw data of DSC file\r
+ # @param Arch Default Arch value for filtering sections\r
# @param Table Database used to retrieve module/package information\r
- # @param Macros Macros used for replacement in file\r
# @param Owner Owner ID (for sub-section parsing)\r
# @param From ID from which the data comes (for !INCLUDE directive)\r
#\r
- def __init__(self, FilePath, FileType, Table, Owner= -1, From= -1):\r
+ def __init__(self, FilePath, FileType, Arch, Table, Owner= -1, From= -1):\r
self._Table = Table\r
self._RawTable = Table\r
+ self._Arch = Arch\r
self._FileType = FileType\r
self.MetaFile = FilePath\r
self._FileDir = self.MetaFile.Dir\r
def _SetFinished(self, Value):\r
self._Finished = Value\r
\r
+ ## Remove records that do not match given Filter Arch\r
+ def _FilterRecordList(self, RecordList, FilterArch):\r
+ NewRecordList = []\r
+ for Record in RecordList:\r
+ Arch = Record[3]\r
+ if Arch == 'COMMON' or Arch == FilterArch:\r
+ NewRecordList.append(Record)\r
+ return NewRecordList\r
+\r
## Use [] style to query data in table, just for readability\r
#\r
# DataInfo = [data_type, scope1(arch), scope2(platform/moduletype)]\r
\r
# No specific ARCH or Platform given, use raw data\r
if self._RawTable and (len(DataInfo) == 1 or DataInfo[1] == None):\r
- return self._RawTable.Query(*DataInfo)\r
+ return self._FilterRecordList(self._RawTable.Query(*DataInfo), self._Arch)\r
\r
# Do post-process if necessary\r
if not self._PostProcessed:\r
self._PostProcess()\r
\r
- return self._Table.Query(*DataInfo)\r
+ return self._FilterRecordList(self._Table.Query(*DataInfo), DataInfo[1])\r
\r
## Data parser for the common format in different type of file\r
#\r
Name, Value = self._ValueList[1], self._ValueList[2]\r
# Sometimes, we need to make differences between EDK and EDK2 modules \r
if Name == 'INF_VERSION':\r
- try:\r
- self._Version = int(Value, 0)\r
- except:\r
+ if re.match(r'0[xX][\da-f-A-F]{5,8}', Value):\r
+ self._Version = int(Value, 0) \r
+ elif re.match(r'\d+\.\d+', Value):\r
+ ValueList = Value.split('.')\r
+ Major = '%04o' % int(ValueList[0], 0)\r
+ Minor = '%04o' % int(ValueList[1], 0)\r
+ self._Version = int('0x' + Major + Minor, 0)\r
+ else:\r
EdkLogger.error('Parser', FORMAT_INVALID, "Invalid version number",\r
ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
\r
File=self.MetaFile,\r
Line=self._LineIndex + 1\r
)\r
-\r
+ def GetValidExpression(self, TokenSpaceGuid, PcdCName):\r
+ return self._Table.GetValidExpression(TokenSpaceGuid, PcdCName)\r
def _GetMacros(self):\r
Macros = {}\r
Macros.update(self._FileLocalMacros)\r
#\r
# @param FilePath The path of module description file\r
# @param FileType The raw data of DSC file\r
+ # @param Arch Default Arch value for filtering sections\r
# @param Table Database used to retrieve module/package information\r
- # @param Macros Macros used for replacement in file\r
#\r
- def __init__(self, FilePath, FileType, Table):\r
+ def __init__(self, FilePath, FileType, Arch, Table):\r
# prevent re-initialization\r
if hasattr(self, "_Table"):\r
return\r
- MetaFileParser.__init__(self, FilePath, FileType, Table)\r
+ MetaFileParser.__init__(self, FilePath, FileType, Arch, Table)\r
self.PcdsDict = {}\r
\r
## Parser starter\r
"PLATFORM_VERSION",\r
"SKUID_IDENTIFIER",\r
"PCD_INFO_GENERATION",\r
+ "PCD_VAR_CHECK_GENERATION",\r
"SUPPORTED_ARCHITECTURES",\r
"BUILD_TARGETS",\r
"OUTPUT_DIRECTORY",\r
"ISO_LANGUAGES",\r
"TIME_STAMP_FILE",\r
"VPD_TOOL_GUID",\r
- "FIX_LOAD_TOP_MEMORY_ADDRESS"\r
+ "FIX_LOAD_TOP_MEMORY_ADDRESS",\r
+ "PREBUILD",\r
+ "POSTBUILD"\r
]\r
\r
SubSectionDefineKeywords = [\r
#\r
# @param FilePath The path of platform description file\r
# @param FileType The raw data of DSC file\r
+ # @param Arch Default Arch value for filtering sections\r
# @param Table Database used to retrieve module/package information\r
- # @param Macros Macros used for replacement in file\r
# @param Owner Owner ID (for sub-section parsing)\r
# @param From ID from which the data comes (for !INCLUDE directive)\r
#\r
- def __init__(self, FilePath, FileType, Table, Owner= -1, From= -1):\r
+ def __init__(self, FilePath, FileType, Arch, Table, Owner= -1, From= -1):\r
# prevent re-initialization\r
if hasattr(self, "_Table"):\r
return\r
- MetaFileParser.__init__(self, FilePath, FileType, Table, Owner, From)\r
+ MetaFileParser.__init__(self, FilePath, FileType, Arch, Table, Owner, From)\r
self._Version = 0x00010005 # Only EDK2 dsc file is supported\r
# to store conditional directive evaluation result\r
self._DirectiveStack = []\r
elif Line[0] == '!':\r
self._DirectiveParser()\r
continue\r
+ if Line[0] == TAB_OPTION_START and not self._InSubsection:\r
+ EdkLogger.error("Parser", FILE_READ_FAILURE, "Missing the '{' before %s in Line %s" % (Line, Index+1),ExtraData=self.MetaFile)\r
\r
if self._InSubsection:\r
SectionType = self._SubsectionType\r
File=self.MetaFile, Line=self._LineIndex + 1,\r
ExtraData=self._CurrentLine)\r
self._DirectiveStack.append((ItemType, self._LineIndex + 1, self._CurrentLine))\r
- elif self._From > 0:\r
- EdkLogger.error('Parser', FORMAT_INVALID,\r
- "No '!include' allowed in included file",\r
- ExtraData=self._CurrentLine, File=self.MetaFile,\r
- Line=self._LineIndex + 1)\r
\r
#\r
# Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,\r
self._SubsectionType = MODEL_UNKNOWN\r
\r
def __RetrievePcdValue(self):\r
- Records = self._RawTable.Query(MODEL_PCD_FEATURE_FLAG, BelongsToItem= -1.0)\r
- for TokenSpaceGuid, PcdName, Value, Dummy2, Dummy3, ID, Line in Records:\r
- Name = TokenSpaceGuid + '.' + PcdName\r
- ValList, Valid, Index = AnalyzeDscPcd(Value, MODEL_PCD_FEATURE_FLAG)\r
- self._Symbols[Name] = ValList[Index]\r
-\r
- Records = self._RawTable.Query(MODEL_PCD_FIXED_AT_BUILD, BelongsToItem= -1.0)\r
- for TokenSpaceGuid, PcdName, Value, Dummy2, Dummy3, ID, Line in Records:\r
- Name = TokenSpaceGuid + '.' + PcdName\r
- ValList, Valid, Index = AnalyzeDscPcd(Value, MODEL_PCD_FIXED_AT_BUILD)\r
- self._Symbols[Name] = ValList[Index]\r
-\r
Content = open(str(self.MetaFile), 'r').readlines()\r
GlobalData.gPlatformOtherPcds['DSCFILE'] = str(self.MetaFile)\r
for PcdType in (MODEL_PCD_PATCHABLE_IN_MODULE, MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_HII,\r
\r
IncludedFileTable = MetaFileStorage(self._Table.Cur, IncludedFile1, MODEL_FILE_DSC, False)\r
Owner = self._Content[self._ContentIndex - 1][0]\r
- Parser = DscParser(IncludedFile1, self._FileType, IncludedFileTable,\r
+ Parser = DscParser(IncludedFile1, self._FileType, self._Arch, IncludedFileTable,\r
Owner=Owner, From=Owner)\r
\r
+ # Does not allow lower level included file to include upper level included file\r
+ if Parser._From != Owner and int(Owner) > int (Parser._From):\r
+ EdkLogger.error('parser', FILE_ALREADY_EXIST, File=self._FileWithError,\r
+ Line=self._LineIndex + 1, ExtraData="{0} is already included at a higher level.".format(IncludedFile1))\r
+\r
+\r
# set the parser status with current status\r
Parser._SectionName = self._SectionName\r
Parser._SectionType = self._SectionType\r
\r
ValList, Valid, Index = AnalyzeDscPcd(self._ValueList[2], self._ItemType)\r
if not Valid:\r
- EdkLogger.error('build', FORMAT_INVALID, "Pcd format incorrect.", File=self._FileWithError, Line=self._LineIndex+1,\r
+ EdkLogger.error('build', FORMAT_INVALID, "Pcd format incorrect.", File=self._FileWithError, Line=self._LineIndex + 1,\r
ExtraData="%s.%s|%s" % (self._ValueList[0], self._ValueList[1], self._ValueList[2]))\r
PcdValue = ValList[Index]\r
if PcdValue:\r
if ValList[Index] == 'False':\r
ValList[Index] = '0'\r
\r
- GlobalData.gPlatformPcds[TAB_SPLIT.join(self._ValueList[0:2])] = PcdValue\r
+ if (not self._DirectiveEvalStack) or (False not in self._DirectiveEvalStack):\r
+ GlobalData.gPlatformPcds[TAB_SPLIT.join(self._ValueList[0:2])] = PcdValue\r
+ self._Symbols[TAB_SPLIT.join(self._ValueList[0:2])] = PcdValue\r
self._ValueList[2] = '|'.join(ValList)\r
\r
def __ProcessComponent(self):\r
#\r
# @param FilePath The path of platform description file\r
# @param FileType The raw data of DSC file\r
+ # @param Arch Default Arch value for filtering sections\r
# @param Table Database used to retrieve module/package information\r
- # @param Macros Macros used for replacement in file\r
#\r
- def __init__(self, FilePath, FileType, Table):\r
+ def __init__(self, FilePath, FileType, Arch, Table):\r
# prevent re-initialization\r
if hasattr(self, "_Table"):\r
return\r
- MetaFileParser.__init__(self, FilePath, FileType, Table, -1)\r
+ MetaFileParser.__init__(self, FilePath, FileType, Arch, Table, -1)\r
self._Comments = []\r
self._Version = 0x00010005 # Only EDK2 dec file is supported\r
self._AllPCDs = [] # Only for check duplicate PCD\r
+ self._AllPcdDict = {}\r
\r
## Parser starter\r
def Start(self):\r
self._SectionName = ''\r
self._SectionType = []\r
ArchList = set()\r
+ PrivateList = set()\r
Line = self._CurrentLine.replace("%s%s" % (TAB_COMMA_SPLIT, TAB_SPACE_SPLIT), TAB_COMMA_SPLIT)\r
for Item in Line[1:-1].split(TAB_COMMA_SPLIT):\r
if Item == '':\r
# S2 may be Platform or ModuleType\r
if len(ItemList) > 2:\r
S2 = ItemList[2].upper()\r
+ # only Includes, GUIDs, PPIs, Protocols section have Private tag\r
+ if self._SectionName in [TAB_INCLUDES.upper(), TAB_GUIDS.upper(), TAB_PROTOCOLS.upper(), TAB_PPIS.upper()]:\r
+ if S2 != 'PRIVATE':\r
+ EdkLogger.error("Parser", FORMAT_INVALID, 'Please use keyword "Private" as section tag modifier.',\r
+ File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)\r
else:\r
S2 = 'COMMON'\r
+ PrivateList.add(S2)\r
if [S1, S2, self.DataType[self._SectionName]] not in self._Scope:\r
self._Scope.append([S1, S2, self.DataType[self._SectionName]])\r
\r
EdkLogger.error('Parser', FORMAT_INVALID, "'common' ARCH must not be used with specific ARCHs",\r
File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)\r
\r
+ # It is not permissible to mix section tags without the Private attribute with section tags with the Private attribute\r
+ if 'COMMON' in PrivateList and len(PrivateList) > 1:\r
+ EdkLogger.error('Parser', FORMAT_INVALID, "Can't mix section tags without the Private attribute with section tags with the Private attribute",\r
+ File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)\r
+\r
## [guids], [ppis] and [protocols] section parser\r
@ParseMacro\r
def _GuidParser(self):\r
# Has VOID* type string, may contain "|" character in the string. \r
if len(PtrValue) != 0:\r
ptrValueList = re.sub(ValueRe, '', TokenList[1])\r
- ValueList = GetSplitValueList(ptrValueList)\r
+ ValueList = AnalyzePcdExpression(ptrValueList)\r
ValueList[0] = PtrValue[0]\r
else:\r
- ValueList = GetSplitValueList(TokenList[1])\r
+ ValueList = AnalyzePcdExpression(TokenList[1])\r
\r
\r
# check if there's enough datum information given\r
ExtraData=self._CurrentLine + \\r
" (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
File=self.MetaFile, Line=self._LineIndex + 1)\r
+\r
+ PcdValue = ValueList[0]\r
+ if PcdValue:\r
+ try:\r
+ ValueList[0] = ValueExpression(PcdValue, self._AllPcdDict)(True)\r
+ except WrnExpression, Value:\r
+ ValueList[0] = Value.result\r
+\r
+ if ValueList[0] == 'True':\r
+ ValueList[0] = '1'\r
+ if ValueList[0] == 'False':\r
+ ValueList[0] = '0'\r
+\r
# check format of default value against the datum type\r
IsValid, Cause = CheckPcdDatum(ValueList[1], ValueList[0])\r
if not IsValid:\r
ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
else:\r
self._AllPCDs.append((self._Scope[0], self._ValueList[0], self._ValueList[1]))\r
+ self._AllPcdDict[TAB_SPLIT.join(self._ValueList[0:2])] = ValueList[0]\r
\r
self._ValueList[2] = ValueList[0].strip() + '|' + ValueList[1].strip() + '|' + ValueList[2].strip()\r
\r