diff options
author | Ma, Maurice <maurice.ma@intel.com> | 2015-03-04 01:03:20 +0000 |
---|---|---|
committer | jyao1 <jyao1@Edk2> | 2015-03-04 01:03:20 +0000 |
commit | 4c9ed23eb6051ea2cd80cb5c8d9a935964b06b1f (patch) | |
tree | 092d4882734fbd6a9b41c95d2d777adda81ecf88 /IntelFspPkg/Tools | |
parent | 48b3ff047929aa5bd4f94128c9a3ac04d6b3b31b (diff) | |
download | edk2-4c9ed23eb6051ea2cd80cb5c8d9a935964b06b1f.tar.gz edk2-4c9ed23eb6051ea2cd80cb5c8d9a935964b06b1f.tar.bz2 edk2-4c9ed23eb6051ea2cd80cb5c8d9a935964b06b1f.zip |
Add UINT16/32/64 array and DSC include support.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: "Ma, Maurice" <maurice.ma@intel.com>
Reviewed-by: "Yao, Jiewen" <jiewen.yao@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17003 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'IntelFspPkg/Tools')
-rw-r--r-- | IntelFspPkg/Tools/GenCfgOpt.py | 402 |
1 files changed, 338 insertions, 64 deletions
diff --git a/IntelFspPkg/Tools/GenCfgOpt.py b/IntelFspPkg/Tools/GenCfgOpt.py index 7e59801879..6b850f6601 100644 --- a/IntelFspPkg/Tools/GenCfgOpt.py +++ b/IntelFspPkg/Tools/GenCfgOpt.py @@ -88,8 +88,206 @@ are permitted provided that the following conditions are met: **/
"""
+class CLogicalExpression:
+ def __init__(self):
+ self.index = 0
+ self.string = ''
+
+ def errExit(self, err = ''):
+ print "ERROR: Express parsing for:"
+ print " %s" % self.string
+ print " %s^" % (' ' * self.index)
+ if err:
+ print "INFO : %s" % err
+ raise SystemExit
+
+ def getNonNumber (self, n1, n2):
+ if not n1.isdigit():
+ return n1
+ if not n2.isdigit():
+ return n2
+ return None
+
+ def getCurr(self, lens = 1):
+ try:
+ if lens == -1:
+ return self.string[self.index :]
+ else:
+ if self.index + lens > len(self.string):
+ lens = len(self.string) - self.index
+ return self.string[self.index : self.index + lens]
+ except Exception:
+ return ''
+
+ def isLast(self):
+ return self.index == len(self.string)
+
+ def moveNext(self, len = 1):
+ self.index += len
+
+ def skipSpace(self):
+ while not self.isLast():
+ if self.getCurr() in ' \t':
+ self.moveNext()
+ else:
+ return
+
+ def normNumber (self, val):
+ return True if val else False
+
+ def getNumber(self, var):
+ var = var.strip()
+ if re.match('^0x[a-fA-F0-9]+$', var):
+ value = int(var, 16)
+ elif re.match('^[+-]?\d+$', var):
+ value = int(var, 10)
+ else:
+ value = None
+ return value
+
+ def parseValue(self):
+ self.skipSpace()
+ var = ''
+ while not self.isLast():
+ char = self.getCurr()
+ if re.match('^[\w.]', char):
+ var += char
+ self.moveNext()
+ else:
+ break
+ val = self.getNumber(var)
+ if val is None:
+ value = var
+ else:
+ value = "%d" % val
+ return value
+
+ def parseSingleOp(self):
+ self.skipSpace()
+ if re.match('^NOT\W', self.getCurr(-1)):
+ self.moveNext(3)
+ op = self.parseBrace()
+ val = self.getNumber (op)
+ if val is None:
+ self.errExit ("'%s' is not a number" % op)
+ return "%d" % (not self.normNumber(int(op)))
+ else:
+ return self.parseValue()
+
+ def parseBrace(self):
+ self.skipSpace()
+ char = self.getCurr()
+ if char == '(':
+ self.moveNext()
+ value = self.parseExpr()
+ self.skipSpace()
+ if self.getCurr() != ')':
+ self.errExit ("Expecting closing brace or operator")
+ self.moveNext()
+ return value
+ else:
+ value = self.parseSingleOp()
+ return value
+
+ def parseCompare(self):
+ value = self.parseBrace()
+ while True:
+ self.skipSpace()
+ char = self.getCurr()
+ if char in ['<', '>']:
+ self.moveNext()
+ next = self.getCurr()
+ if next == '=':
+ op = char + next
+ self.moveNext()
+ else:
+ op = char
+ result = self.parseBrace()
+ test = self.getNonNumber(result, value)
+ if test is None:
+ value = "%d" % self.normNumber(eval (value + op + result))
+ else:
+ self.errExit ("'%s' is not a valid number for comparision" % test)
+ elif char in ['=', '!']:
+ op = self.getCurr(2)
+ if op in ['==', '!=']:
+ self.moveNext(2)
+ result = self.parseBrace()
+ test = self.getNonNumber(result, value)
+ if test is None:
+ value = "%d" % self.normNumber((eval (value + op + result)))
+ else:
+ value = "%d" % self.normNumber(eval ("'" + value + "'" + op + "'" + result + "'"))
+ else:
+ break
+ else:
+ break
+ return value
+
+ def parseAnd(self):
+ value = self.parseCompare()
+ while True:
+ self.skipSpace()
+ if re.match('^AND\W', self.getCurr(-1)):
+ self.moveNext(3)
+ result = self.parseCompare()
+ test = self.getNonNumber(result, value)
+ if test is None:
+ value = "%d" % self.normNumber(int(value) & int(result))
+ else:
+ self.errExit ("'%s' is not a valid op number for AND" % test)
+ else:
+ break
+ return value
+
+ def parseOrXor(self):
+ value = self.parseAnd()
+ op = None
+ while True:
+ self.skipSpace()
+ op = None
+ if re.match('^XOR\W', self.getCurr(-1)):
+ self.moveNext(3)
+ op = '^'
+ elif re.match('^OR\W', self.getCurr(-1)):
+ self.moveNext(2)
+ op = '|'
+ else:
+ break
+ if op:
+ result = self.parseAnd()
+ test = self.getNonNumber(result, value)
+ if test is None:
+ value = "%d" % self.normNumber(eval (value + op + result))
+ else:
+ self.errExit ("'%s' is not a valid op number for XOR/OR" % test)
+ return value
+
+ def parseExpr(self):
+ return self.parseOrXor()
+
+ def getResult(self):
+ value = self.parseExpr()
+ self.skipSpace()
+ if not self.isLast():
+ self.errExit ("Unexpected character found '%s'" % self.getCurr())
+ test = self.getNumber(value)
+ if test is None:
+ self.errExit ("Result '%s' is not a number" % value)
+ return int(value)
+
+ def evaluateExpress (self, Expr):
+ self.index = 0
+ self.string = Expr
+ if self.getResult():
+ Result = True
+ else:
+ Result = False
+ return Result
+
class CGenCfgOpt:
def __init__(self):
+ self.Debug = False
self.Error = ''
self._GlobalDataDef = """
@@ -139,12 +337,71 @@ EndList if Match:
self._MacroDict[Match.group(1)] = ''
if len(self._MacroDict) == 0:
- self.Error = "Invalid MACRO arguments"
Error = 1
else:
Error = 0
+ if self.Debug:
+ print "INFO : Macro dictionary:"
+ for Each in self._MacroDict:
+ print " $(%s) = [ %s ]" % (Each , self._MacroDict[Each])
return Error
+ def EvaulateIfdef (self, Macro):
+ Result = Macro in self._MacroDict
+ if self.Debug:
+ print "INFO : Eval Ifdef [%s] : %s" % (Macro, Result)
+ return Result
+
+ def ExpandMacros (self, Input):
+ Line = Input
+ Match = re.findall("\$\(\w+\)", Input)
+ if Match:
+ for Each in Match:
+ Variable = Each[2:-1]
+ if Variable in self._MacroDict:
+ Line = Line.replace(Each, self._MacroDict[Variable])
+ else:
+ if self.Debug:
+ print "WARN : %s is not defined" % Each
+ Line = Line.replace(Each, Each[2:-1])
+ return Line
+
+ def EvaluateExpress (self, Expr):
+ ExpExpr = self.ExpandMacros(Expr)
+ LogExpr = CLogicalExpression()
+ Result = LogExpr.evaluateExpress (ExpExpr)
+ if self.Debug:
+ print "INFO : Eval Express [%s] : %s" % (Expr, Result)
+ return Result
+
+ def FormatListValue(self, ConfigDict):
+ Struct = ConfigDict['struct']
+ if Struct not in ['UINT8','UINT16','UINT32','UINT64']:
+ return
+
+ dataarray = []
+ binlist = ConfigDict['value'][1:-1].split(',')
+ for each in binlist:
+ each = each.strip()
+ if each.startswith('0x'):
+ value = int(each, 16)
+ else:
+ value = int(each)
+ dataarray.append(value)
+
+ unit = int(Struct[4:]) / 8
+ if int(ConfigDict['length']) != unit * len(dataarray):
+ raise Exception("Array size is not proper for '%s' !" % ConfigDict['cname'])
+
+ bytearray = []
+ for each in dataarray:
+ value = each
+ for loop in xrange(unit):
+ bytearray.append("0x%02X" % (value & 0xFF))
+ value = value >> 8
+ newvalue = '{' + ','.join(bytearray) + '}'
+ ConfigDict['value'] = newvalue
+ return ""
def ParseDscFile (self, DscFile, FvDir):
self._CfgItemList = []
@@ -158,20 +415,19 @@ EndList IsVpdSect = False
Found = False
- IfStack = [True]
+ IfStack = []
ElifStack = []
Error = 0
+ ConfigDict = {}
DscFd = open(DscFile, "r")
DscLines = DscFd.readlines()
DscFd.close()
- ConfigDict = {}
-
- for DscLine in DscLines:
- Handle = False
- DscLine = DscLine.strip()
- Match = re.match("^\[(.+)\]", DscLine)
+ while len(DscLines):
+ DscLine = DscLines.pop(0).strip()
+ Handle = False
+ Match = re.match("^\[(.+)\]", DscLine)
if Match is not None:
if Match.group(1).lower() == "Defines".lower():
IsDefSect = True
@@ -210,66 +466,78 @@ EndList IsVpdSect = False
else:
if IsDefSect or IsUpdSect or IsVpdSect:
- if DscLine == "!else":
- IfStack[-1] = not IfStack[-1]
- elif DscLine == "!endif":
- IfStack.pop()
- Level = ElifStack.pop()
- while Level > 0:
+ if re.match("^!else($|\s+#.+)", DscLine):
+ if IfStack:
+ IfStack[-1] = not IfStack[-1]
+ else:
+ print("ERROR: No paired '!if' found for '!else' for line '%s'" % DscLine)
+ raise SystemExit
+ elif re.match("^!endif($|\s+#.+)", DscLine):
+ if IfStack:
IfStack.pop()
- Level = Level - 1
+ Level = ElifStack.pop()
+ if Level > 0:
+ del IfStack[-Level:]
+ else:
+ print("ERROR: No paired '!if' found for '!endif' for line '%s'" % DscLine)
+ raise SystemExit
else:
Result = False
- Match = re.match("!(ifdef|ifndef)\s+\$\((\w+)\)", DscLine)
- if Match is not None:
- if Match.group(2) in self._MacroDict:
- if Match.group(1) == 'ifdef':
- Result = True
- else:
- if Match.group(1) == 'ifndef':
- Result = True
- ElifStack.append(0)
+ Match = re.match("!(ifdef|ifndef)\s+(.+)", DscLine)
+ if Match:
+ Result = self.EvaulateIfdef (Match.group(2))
+ if Match.group(1) == 'ifndef':
+ Result = not Result
IfStack.append(Result)
+ ElifStack.append(0)
else:
- Match = re.match("!(if|elseif)\s+\$\\((\w+)\)\s*==\s*(\w+|\$\(\w+\))", DscLine)
- if Match is not None:
- if Match.group(2) in self._MacroDict:
- MacroName = self._MacroDict[Match.group(2)]
- else:
- MacroName = ''
- Value = Match.group(3)
- if Value.startswith('$'):
- if Value[2:-1] in self._MacroDict:
- Value = self._MacroDict[Value[2:-1]]
- else:
- Value = ''
- if MacroName == Value:
- Result = True
+ Match = re.match("!(if|elseif)\s+(.+)", DscLine)
+ if Match:
+ Result = self.EvaluateExpress(Match.group(2))
if Match.group(1) == "if":
ElifStack.append(0)
IfStack.append(Result)
else: #elseif
- IfStack[-1] = not IfStack[-1]
- IfStack.append(Result)
- ElifStack[-1] = ElifStack[-1] + 1
+ if IfStack:
+ IfStack[-1] = not IfStack[-1]
+ IfStack.append(Result)
+ ElifStack[-1] = ElifStack[-1] + 1
+ else:
+ print("ERROR: No paired '!if' found for '!elif' for line '%s'" % DscLine)
+ raise SystemExit
else:
- if len(DscLine) > 0 and DscLine[0] == '!':
- #
- # Current it can only handle build switch.
- # It does not support INF file in included dsc.
- #
+ if IfStack:
+ Handle = reduce(lambda x,y: x and y, IfStack)
else:
- if reduce(lambda x,y: x and y, IfStack):
- Handle = True
-
+ Handle = True
+ if Handle:
+ Match = re.match("!include\s+(.+)", DscLine)
+ if Match:
+ IncludeFilePath = Match.group(1)
+ IncludeFilePath = self.ExpandMacros(IncludeFilePath)
+ try:
+ IncludeDsc = open(IncludeFilePath, "r")
+ except:
+ print("ERROR: Cannot open file '%s'" % IncludeFilePath)
+ raise SystemExit
+ NewDscLines = IncludeDsc.readlines()
+ IncludeDsc.close()
+ DscLines = NewDscLines + DscLines
+ else:
+ if DscLine.startswith('!'):
+ print("ERROR: Unrecoginized directive for line '%s'" % DscLine)
+ raise SystemExit
+
if not Handle:
continue
if IsDefSect:
#DEFINE UPD_TOOL_GUID = 8C3D856A-9BE6-468E-850A-24F7A8D38E09
- Match = re.match("^\s*(?:DEFINE\s+)*(\w+)\s*=\s*([-\w]+)", DscLine)
+ Match = re.match("^\s*(?:DEFINE\s+)*(\w+)\s*=\s*([-.\w]+)", DscLine)
if Match:
self._MacroDict[Match.group(1)] = Match.group(2)
+ if self.Debug:
+ print "INFO : DEFINE %s = [ %s ]" % (Match.group(1), Match.group(2))
else:
Match = re.match("^\s*#\s+!(BSF|HDR)\s+(.+)", DscLine)
if Match:
@@ -338,7 +606,11 @@ EndList if Match:
if Match.group(1) in self._MacroDict:
Value = self._MacroDict[Match.group(1)]
+
ConfigDict['value'] = Value
+ if (len(Value) > 0) and (Value[0] == '{'):
+ Value = self.FormatListValue(ConfigDict)
+
if ConfigDict['name'] == '':
# Clear BSF specific items
ConfigDict['help'] = ''
@@ -502,26 +774,29 @@ EndList TxtFd.close()
return 0
- def CreateField (self, Name, Length, Offset, Struct):
+ def CreateField (self, Item, Name, Length, Offset, Struct):
PosName = 28
PosComment = 30
IsArray = False
- if Length == 1:
- Type = "UINT8"
- elif Length == 2:
- Type = "UINT16"
- elif Length == 4:
- Type = "UINT32"
- elif Length == 8:
- Type = "UINT64"
+ if Length in [1,2,4,8]:
+ Type = "UINT%d" % (Length * 8)
else:
+ IsArray = True
+ Type = "UINT8"
+
+ if Item['value'].startswith('{'):
Type = "UINT8"
IsArray = True
if Struct != '':
- IsArray = False
Type = Struct
+ if Struct in ['UINT8','UINT16','UINT32','UINT64']:
+ IsArray = True
+ Unit = int(Type[4:]) / 8
+ Length = Length / Unit
+ else:
+ IsArray = False
if IsArray:
Name = Name + '[%d]' % Length
@@ -644,12 +919,12 @@ EndList NextVisible = True
Name = "Reserved" + Region[0] + "pdSpace%d" % ResvIdx
ResvIdx = ResvIdx + 1
- HeaderFd.write(self.CreateField (Name, Item["offset"] - ResvOffset, ResvOffset, ''))
+ HeaderFd.write(self.CreateField (Item, Name, Item["offset"] - ResvOffset, ResvOffset, ''))
if Offset < Item["offset"]:
if IsInternal or LastVisible:
Name = "Unused" + Region[0] + "pdSpace%d" % SpaceIdx
- LineBuffer.append(self.CreateField (Name, Item["offset"] - Offset, Offset, ''))
+ LineBuffer.append(self.CreateField (Item, Name, Item["offset"] - Offset, Offset, ''))
SpaceIdx = SpaceIdx + 1
Offset = Item["offset"]
@@ -665,7 +940,7 @@ EndList for Each in LineBuffer:
HeaderFd.write (Each)
LineBuffer = []
- HeaderFd.write(self.CreateField (Item["cname"], Item["length"], Item["offset"], Item['struct']))
+ HeaderFd.write(self.CreateField (Item, Item["cname"], Item["length"], Item["offset"], Item['struct']))
HeaderFd.write("} " + Region[0] + "PD_DATA_REGION;\n\n")
HeaderFd.write("#pragma pack()\n\n")
@@ -846,7 +1121,6 @@ def Main(): print "ERROR: %s !" % GenCfgOpt.Error
return 5
-
if GenCfgOpt.UpdateVpdSizeField() != 0:
print "ERROR: %s !" % GenCfgOpt.Error
return 6
|