IntelFsp2Pkg/GenCfgOpt.py: Support UPD offset auto assignment

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1211

For reducing maintenance effort, the UPD offset can be
automatic assigned by GenCfgOpt.py following by alignment
requirements.

The usage model as below:
. If UPD offset in DSC file are all '*', GenCfgOpt.py will
  assign offset for all UPD automatically. In this case no
  need to manually hardcode offset to all UPD in DSC.

. If UPD offset in DSC file are all not '*', GenCfgOpt.py
  will use hardcoded offset directly (original usage model)

. Tool does not support mixing scenario so UPD offset in DSC
  should be all '*' or all hardcoded but not mixed.

In auto mode UPD offset will be assigned following natural
alignment (size aligned) rule and the whole structure size
will align to either 32bits or 64bits depends on maximal UPD
size in the structure.

Test: Verified by both UPD offset hardcoded or '*' in DSC and
      generated UPD header files are correct.

Cc: Jiewen Yao <Jiewen.yao@intel.com>
Cc: Gao Liming <liming.gao@intel.com>
Cc: Zhu Yonghong <yonghong.zhu@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Chasel Chiu <chasel.chiu@intel.com>
Reviewed-by: Jiewen Yao <Jiewen.yao@intel.com>
This commit is contained in:
Chasel, Chiu 2018-09-26 19:21:11 +08:00
parent ccacc4d273
commit 1d7eed4182
1 changed files with 64 additions and 2 deletions

View File

@ -418,6 +418,8 @@ EndList
return "" return ""
def ParseDscFile (self, DscFile, FvDir): def ParseDscFile (self, DscFile, FvDir):
Hardcode = False
AutoAlign = False
self._CfgItemList = [] self._CfgItemList = []
self._CfgPageDict = {} self._CfgPageDict = {}
self._CfgBlkDict = {} self._CfgBlkDict = {}
@ -438,6 +440,8 @@ EndList
DscLines = DscFd.readlines() DscLines = DscFd.readlines()
DscFd.close() DscFd.close()
MaxAlign = 32 #Default align to 32, but if there are 64 bit unit, align to 64
SizeAlign = 0 #record the struct max align
while len(DscLines): while len(DscLines):
DscLine = DscLines.pop(0).strip() DscLine = DscLines.pop(0).strip()
Handle = False Handle = False
@ -464,6 +468,7 @@ EndList
ConfigDict['comment'] = '' ConfigDict['comment'] = ''
ConfigDict['subreg'] = [] ConfigDict['subreg'] = []
IsUpdSect = True IsUpdSect = True
Offset = 0
else: else:
if IsDefSect or IsPcdSect or IsUpdSect or IsVpdSect: if IsDefSect or IsPcdSect or IsUpdSect or IsVpdSect:
if re.match("^!else($|\s+#.+)", DscLine): if re.match("^!else($|\s+#.+)", DscLine):
@ -530,6 +535,7 @@ EndList
NewDscLines = IncludeDsc.readlines() NewDscLines = IncludeDsc.readlines()
IncludeDsc.close() IncludeDsc.close()
DscLines = NewDscLines + DscLines DscLines = NewDscLines + DscLines
Offset = 0
else: else:
if DscLine.startswith('!'): if DscLine.startswith('!'):
print("ERROR: Unrecoginized directive for line '%s'" % DscLine) print("ERROR: Unrecoginized directive for line '%s'" % DscLine)
@ -620,13 +626,22 @@ EndList
# Check VPD/UPD # Check VPD/UPD
if IsUpdSect: if IsUpdSect:
Match = re.match("^([_a-zA-Z0-9]+).([_a-zA-Z0-9]+)\s*\|\s*(0x[0-9A-F]+)\s*\|\s*(\d+|0x[0-9a-fA-F]+)\s*\|\s*(.+)",DscLine) Match = re.match("^([_a-zA-Z0-9]+).([_a-zA-Z0-9]+)\s*\|\s*(0x[0-9A-F]+|\*)\s*\|\s*(\d+|0x[0-9a-fA-F]+)\s*\|\s*(.+)",DscLine)
else: else:
Match = re.match("^([_a-zA-Z0-9]+).([_a-zA-Z0-9]+)\s*\|\s*(0x[0-9A-F]+)(?:\s*\|\s*(.+))?", DscLine) Match = re.match("^([_a-zA-Z0-9]+).([_a-zA-Z0-9]+)\s*\|\s*(0x[0-9A-F]+)(?:\s*\|\s*(.+))?", DscLine)
if Match: if Match:
ConfigDict['space'] = Match.group(1) ConfigDict['space'] = Match.group(1)
ConfigDict['cname'] = Match.group(2) ConfigDict['cname'] = Match.group(2)
ConfigDict['offset'] = int (Match.group(3), 16) if Match.group(3) != '*':
Hardcode = True
Offset = int (Match.group(3), 16)
else:
AutoAlign = True
if Hardcode and AutoAlign:
print("Hardcode and auto-align mixed mode is not supported by GenCfgOpt")
raise SystemExit
ConfigDict['offset'] = Offset
if ConfigDict['order'] == -1: if ConfigDict['order'] == -1:
ConfigDict['order'] = ConfigDict['offset'] << 8 ConfigDict['order'] = ConfigDict['offset'] << 8
else: else:
@ -638,6 +653,7 @@ EndList
Length = int (Match.group(4), 16) Length = int (Match.group(4), 16)
else : else :
Length = int (Match.group(4)) Length = int (Match.group(4))
Offset += Length
else: else:
Value = Match.group(4) Value = Match.group(4)
if Value is None: if Value is None:
@ -665,6 +681,52 @@ EndList
ConfigDict['help'] = '' ConfigDict['help'] = ''
ConfigDict['type'] = '' ConfigDict['type'] = ''
ConfigDict['option'] = '' ConfigDict['option'] = ''
if IsUpdSect and AutoAlign:
ItemLength = int(ConfigDict['length'])
ItemOffset = int(ConfigDict['offset'])
ItemStruct = ConfigDict['struct']
Unit = 1
if ItemLength in [1, 2, 4, 8] and not ConfigDict['value'].startswith('{'):
Unit = ItemLength
# If there are 64 bit unit, align to 64
if Unit == 8:
MaxAlign = 64
SizeAlign = 8
if ItemStruct != '':
UnitDict = {'UINT8':1, 'UINT16':2, 'UINT32':4, 'UINT64':8}
if ItemStruct in ['UINT8', 'UINT16', 'UINT32', 'UINT64']:
Unit = UnitDict[ItemStruct]
# If there are 64 bit unit, align to 64
if Unit == 8:
MaxAlign = 64
SizeAlign = max(SizeAlign, Unit)
if (ConfigDict['embed'].find(':START') != -1):
Base = ItemOffset
SubOffset = ItemOffset - Base
SubRemainder = SubOffset % Unit
if SubRemainder:
Diff = Unit - SubRemainder
Offset = Offset + Diff
ItemOffset = ItemOffset + Diff
if (ConfigDict['embed'].find(':END') != -1):
Remainder = Offset % (MaxAlign/8) # MaxAlign is either 32 or 64
if Remainder:
Diff = (MaxAlign/8) - Remainder
Offset = Offset + Diff
ItemOffset = ItemOffset + Diff
MaxAlign = 32 # Reset to default 32 align when struct end
if (ConfigDict['cname'] == 'UpdTerminator'):
# ItemLength is the size of UpdTerminator
# Itemlength might be 16, 32, or 64
# Struct align to 64 if UpdTerminator
# or struct size is 64 bit, else align to 32
Remainder = Offset % max(ItemLength/8, 4, SizeAlign)
Offset = Offset + ItemLength
if Remainder:
Diff = max(ItemLength/8, 4, SizeAlign) - Remainder
ItemOffset = ItemOffset + Diff
ConfigDict['offset'] = ItemOffset
self._CfgItemList.append(ConfigDict.copy()) self._CfgItemList.append(ConfigDict.copy())
ConfigDict['name'] = '' ConfigDict['name'] = ''