]>
git.proxmox.com Git - mirror_edk2.git/blob - IntelFsp2Pkg/Tools/FspGenCfgData.py
3 # Copyright (c) 2014 - 2021, Intel Corporation. All rights reserved.<BR>
4 # SPDX-License-Identifier: BSD-2-Clause-Patent
12 from functools
import reduce
13 from datetime
import date
15 # Generated file copyright header
17 __copyright_tmp__
= """/** @file
19 Configuration %s File.
21 Copyright (c) %4d, Intel Corporation. All rights reserved.<BR>
22 SPDX-License-Identifier: BSD-2-Clause-Patent
24 This file is automatically generated. Please do NOT modify !!!
29 __copyright_dsc__
= """## @file
31 # Copyright (c) %04d, Intel Corporation. All rights reserved.<BR>
32 # SPDX-License-Identifier: BSD-2-Clause-Patent
38 # Global definitions in BSF
39 # !BSF BLOCK:{NAME:"FSP UPD Configuration", VER:"0.1"}
46 return reduce(lambda x
, y
: (x
<< 8) | y
, Bytes
[::-1])
50 return '{ %s }' % (', '.join('0x%02X' % i
for i
in Bytes
))
53 def Str2Bytes(Value
, Blen
):
54 Result
= bytearray(Value
[1:-1], 'utf-8') # Excluding quotes
55 if len(Result
) < Blen
:
56 Result
.extend(b
'\x00' * (Blen
- len(Result
)))
60 def Val2Bytes(Value
, Blen
):
61 return [(Value
>> (i
* 8) & 0xff) for i
in range(Blen
)]
64 def Array2Val(ValStr
):
65 ValStr
= ValStr
.strip()
66 if ValStr
.startswith('{'):
68 if ValStr
.endswith('}'):
70 if ValStr
.startswith("'"):
72 if ValStr
.endswith("'"):
75 for Each
in ValStr
.split(',')[::-1]:
77 if Each
.startswith('0x'):
81 Value
= (Value
<< 8) |
int(Each
, Base
)
85 def GetCopyrightHeader(FileType
, AllowModify
=False):
87 'bsf': 'Boot Setting',
90 'inc': 'C Binary Blob',
91 'h': 'C Struct Header'
93 if FileType
in ['bsf', 'dsc', 'dlt']:
97 Lines
= __copyright_tmp__
.split('\n')
100 Lines
= [Line
for Line
in Lines
if 'Please do NOT modify' not in Line
]
102 CopyrightHdr
= '\n'.join('%s%s' % (
103 CommentChar
, Line
) for Line
in Lines
)[:-1] + '\n'
105 return CopyrightHdr
% (FileDescription
[FileType
], date
.today().year
)
108 class CLogicalExpression
:
113 def errExit(self
, err
=''):
114 print("ERROR: Express parsing for:")
115 print(" %s" % self
.string
)
116 print(" %s^" % (' ' * self
.index
))
118 print("INFO : %s" % err
)
121 def getNonNumber(self
, n1
, n2
):
128 def getCurr(self
, lens
=1):
131 return self
.string
[self
.index
:]
133 if self
.index
+ lens
> len(self
.string
):
134 lens
= len(self
.string
) - self
.index
135 return self
.string
[self
.index
: self
.index
+ lens
]
140 return self
.index
== len(self
.string
)
142 def moveNext(self
, len=1):
146 while not self
.isLast():
147 if self
.getCurr() in ' \t':
152 def normNumber(self
, val
):
153 return True if val
else False
155 def getNumber(self
, var
):
157 if re
.match('^0x[a-fA-F0-9]+$', var
):
159 elif re
.match('^[+-]?\\d+$', var
):
165 def parseValue(self
):
168 while not self
.isLast():
169 char
= self
.getCurr()
170 if re
.match('^[\\w.]', char
):
175 val
= self
.getNumber(var
)
182 def parseSingleOp(self
):
184 if re
.match('^NOT\\W', self
.getCurr(-1)):
186 op
= self
.parseBrace()
187 val
= self
.getNumber(op
)
189 self
.errExit("'%s' is not a number" % op
)
190 return "%d" % (not self
.normNumber(int(op
)))
192 return self
.parseValue()
194 def parseBrace(self
):
196 char
= self
.getCurr()
199 value
= self
.parseExpr()
201 if self
.getCurr() != ')':
202 self
.errExit("Expecting closing brace or operator")
206 value
= self
.parseSingleOp()
209 def parseCompare(self
):
210 value
= self
.parseBrace()
213 char
= self
.getCurr()
214 if char
in ['<', '>']:
216 next
= self
.getCurr()
222 result
= self
.parseBrace()
223 test
= self
.getNonNumber(result
, value
)
225 value
= "%d" % self
.normNumber(eval(value
+ op
+ result
))
227 self
.errExit("'%s' is not a valid number for comparision"
229 elif char
in ['=', '!']:
231 if op
in ['==', '!=']:
233 result
= self
.parseBrace()
234 test
= self
.getNonNumber(result
, value
)
236 value
= "%d" % self
.normNumber((eval(value
+ op
239 value
= "%d" % self
.normNumber(eval("'" + value
+
249 value
= self
.parseCompare()
252 if re
.match('^AND\\W', self
.getCurr(-1)):
254 result
= self
.parseCompare()
255 test
= self
.getNonNumber(result
, value
)
257 value
= "%d" % self
.normNumber(int(value
) & int(result
))
259 self
.errExit("'%s' is not a valid op number for AND" %
265 def parseOrXor(self
):
266 value
= self
.parseAnd()
271 if re
.match('^XOR\\W', self
.getCurr(-1)):
274 elif re
.match('^OR\\W', self
.getCurr(-1)):
280 result
= self
.parseAnd()
281 test
= self
.getNonNumber(result
, value
)
283 value
= "%d" % self
.normNumber(eval(value
+ op
+ result
))
285 self
.errExit("'%s' is not a valid op number for XOR/OR" %
290 return self
.parseOrXor()
293 value
= self
.parseExpr()
295 if not self
.isLast():
296 self
.errExit("Unexpected character found '%s'" % self
.getCurr())
297 test
= self
.getNumber(value
)
299 self
.errExit("Result '%s' is not a number" % value
)
302 def evaluateExpress(self
, Expr
):
314 def __init__(self
, bsf_file
):
315 self
.cfg_list
= CFspBsf2Dsc
.parse_bsf(bsf_file
)
317 def get_dsc_lines(self
):
318 return CFspBsf2Dsc
.generate_dsc(self
.cfg_list
)
320 def save_dsc(self
, dsc_file
):
321 return CFspBsf2Dsc
.generate_dsc(self
.cfg_list
, dsc_file
)
324 def parse_bsf(bsf_file
):
326 fd
= open(bsf_file
, 'r')
331 regex
= re
.compile(r
'\s+Find\s+"(.*?)"(.*?)^\s+(\$(.*?)|Skip)\s+',
333 for match
in regex
.finditer(bsf_txt
):
334 find
= match
.group(1)
335 name
= match
.group(3)
336 line
= bsf_txt
[:match
.end()].count("\n")
337 find_list
.append((name
, find
, line
))
344 cfg_temp
= {'find': '', 'cname': '', 'length': 0, 'value': '0',
345 'type': 'Reserved', 'isbit': False,
346 'embed': '', 'page': '', 'option': '', 'instance': 0}
348 r
'^\s+(\$(.*?)|Skip)\s+(\d+)\s+(bits|bytes)(\s+\$_DEFAULT_\s'
349 r
'+=\s+(.+?))?$', re
.S |
352 for match
in regex
.finditer(bsf_txt
):
353 dlen
= int(match
.group(3))
354 if match
.group(1) == 'Skip':
355 key
= 'gPlatformFspPkgTokenSpaceGuid_BsfSkip%d' % idx
356 val
= ', '.join(['%02X' % ord(i
) for i
in '\x00' * dlen
])
363 is_bit
= True if match
.group(4) == 'bits' else False
365 cfg_item
= dict(cfg_temp
)
366 line
= bsf_txt
[:match
.end()].count("\n")
367 finds
= [i
for i
in find_list
if line
>= i
[2]]
370 cfg_item
['embed'] = '%s:TAG_%03X:START' % \
371 (prefix
, ord(prefix
[-1]))
372 cfg_item
['find'] = prefix
373 cfg_item
['cname'] = 'Signature'
374 cfg_item
['length'] = len(finds
[0][1])
375 str2byte
= Str2Bytes("'" + finds
[0][1] + "'",
377 cfg_item
['value'] = '0x%X' % Bytes2Val(str2byte
)
379 cfg_list
.append(dict(cfg_item
))
380 cfg_item
= dict(cfg_temp
)
384 cfg_item
['cname'] = key
385 cfg_item
['length'] = dlen
386 cfg_item
['value'] = val
387 cfg_item
['option'] = option
388 cfg_item
['isbit'] = is_bit
390 if key
not in chk_dict
.keys():
394 cfg_item
['instance'] = chk_dict
[key
]
396 cfg_list
.append(cfg_item
)
400 cfg_item
= dict(cfg_temp
)
401 cfg_item
['cname'] = 'Dummy'
402 cfg_item
['embed'] = '%s:%03X:END' % (prefix
, ord(prefix
[-1]))
403 cfg_list
.append(cfg_item
)
407 r
'\s+Selection\s*(.+?)\s*,\s*"(.*?)"$', re
.S |
410 r
'^List\s&(.+?)$(.+?)^EndList$', re
.S | re
.MULTILINE
)
411 for match
in regex
.finditer(bsf_txt
):
413 option_dict
[key
] = []
414 for select
in selreg
.finditer(match
.group(2)):
415 option_dict
[key
].append(
416 (int(select
.group(1), 0), select
.group(2)))
419 pagereg
= re
.compile(
420 r
'^Page\s"(.*?)"$(.+?)^EndPage$', re
.S | re
.MULTILINE
)
421 for match
in pagereg
.finditer(bsf_txt
):
422 page
= match
.group(1)
423 for line
in match
.group(2).splitlines():
425 r
'\s+(Combo|EditNum)\s\$(.+?),\s"(.*?)",\s(.+?),$', line
)
427 cname
= match
.group(2)
428 if cname
not in chk_dict
.keys():
432 instance
= chk_dict
[cname
]
433 cfg_idxs
= [i
for i
, j
in enumerate(cfg_list
)
434 if j
['cname'] == cname
and
435 j
['instance'] == instance
]
436 if len(cfg_idxs
) != 1:
438 "Multiple CFG item '%s' found !" % cname
)
439 cfg_item
= cfg_list
[cfg_idxs
[0]]
440 cfg_item
['page'] = page
441 cfg_item
['type'] = match
.group(1)
442 cfg_item
['prompt'] = match
.group(3)
443 cfg_item
['range'] = None
444 if cfg_item
['type'] == 'Combo':
445 cfg_item
['option'] = option_dict
[match
.group(4)[1:]]
446 elif cfg_item
['type'] == 'EditNum':
447 cfg_item
['option'] = match
.group(4)
448 match
= re
.match(r
'\s+ Help\s"(.*?)"$', line
)
450 cfg_item
['help'] = match
.group(1)
452 match
= re
.match(r
'\s+"Valid\srange:\s(.*)"$', line
)
454 parts
= match
.group(1).split()
455 cfg_item
['option'] = (
456 (int(parts
[0], 0), int(parts
[2], 0),
462 def generate_dsc(option_list
, dsc_file
=None):
464 header
= '%s' % (__copyright_dsc__
% date
.today().year
)
465 dsc_lines
.extend(header
.splitlines())
468 for cfg_item
in option_list
:
469 if cfg_item
['page'] and (cfg_item
['page'] not in pages
):
470 pages
.append(cfg_item
['page'])
474 dsc_lines
.append(' # !BSF PAGES:{PG%02X::"%s"}' % (page_id
, page
))
484 for idx
, option
in enumerate(option_list
):
485 if not is_bit
and option
['isbit']:
490 if is_bit
and not option
['isbit']:
493 raise Exception("Bit fields are not aligned at "
495 bit_fields
.append((idxs
, idx
, dlen
, dval
))
497 blen
= option
['length']
498 bval
= int(option
['value'], 0)
499 dval
= dval
+ ((bval
& ((1 << blen
) - 1)) << dlen
)
500 print(dlen
, blen
, bval
, hex(dval
))
504 for idx
, option
in enumerate(option_list
):
506 default
= option
['value']
507 pos
= option
['cname'].find('_')
508 name
= option
['cname'][pos
+ 1:]
510 for start_idx
, end_idx
, bits_len
, bits_val
in bit_fields
:
512 val_str
= Bytes2Str(Val2Bytes(bits_val
, bits_len
// 8))
513 dsc_lines
.append(' # !HDR STRUCT:{BIT_FIELD_DATA_%d}'
515 dsc_lines
.append(' # !BSF NAME:{BIT_FIELD_STRUCT}')
516 dsc_lines
.append(' gCfgData.BitFiledStruct%d '
517 ' | * | 0x%04X | %s' %
518 (struct_idx
, bits_len
// 8, val_str
))
523 dsc_lines
.append(' # !BSF FIND:{%s}' % option
['find'])
526 if option
['instance'] > 0:
527 name
= name
+ '_%s' % option
['instance']
530 dsc_lines
.append(' # !HDR EMBED:{%s}' % option
['embed'])
532 if option
['type'] == 'Reserved':
533 dsc_lines
.append(' # !BSF NAME:{Reserved} TYPE:{Reserved}')
534 if option
['option'] == '$SKIP':
535 dsc_lines
.append(' # !BSF OPTION:{$SKIP}')
537 prompt
= option
['prompt']
539 if last_page
!= option
['page']:
540 last_page
= option
['page']
541 dsc_lines
.append(' # !BSF PAGE:{PG%02X}' %
542 (pages
.index(option
['page'])))
544 if option
['type'] == 'Combo':
545 dsc_lines
.append(' # !BSF NAME:{%s} TYPE:{%s}' %
546 (prompt
, option
['type']))
548 for val
, text
in option
['option']:
549 ops
.append('0x%x:%s' % (val
, text
))
550 dsc_lines
.append(' # !BSF OPTION:{%s}' % (', '.join(ops
)))
551 elif option
['type'] == 'EditNum':
552 cfg_len
= option
['length']
553 if ',' in default
and cfg_len
> 8:
554 dsc_lines
.append(' # !BSF NAME:{%s} TYPE:{Table}' %
559 for i
in range(cfg_len
):
560 ops
.append('%X:1:HEX' % i
)
561 dsc_lines
.append(' # !BSF OPTION:{%s}' %
565 ' # !BSF NAME:{%s} TYPE:{%s, %s, (0x%X, 0x%X)}' %
566 (prompt
, option
['type'], option
['option'][2],
567 option
['option'][0], option
['option'][1]))
568 dsc_lines
.append(' # !BSF HELP:{%s}' % option
['help'])
571 default
= '{%s}' % default
574 dsc_lines
.append(' # !BSF FIELD:{%s:%db}'
575 % (name
, option
['length']))
577 dsc_lines
.append(' gCfgData.%-30s | * | 0x%04X | %s' %
578 (name
, option
['length'], default
))
581 fd
= open(dsc_file
, 'w')
582 fd
.write('\n'.join(dsc_lines
))
589 def __init__(self
, Mode
=''):
592 self
.ReleaseMode
= True
594 self
._GlobalDataDef
= """
600 self
._BuidinOptionTxt
= """
602 Selection 0x1 , "Enabled"
603 Selection 0x0 , "Disabled"
607 self
._StructType
= ['UINT8', 'UINT16', 'UINT32', 'UINT64']
608 self
._BsfKeyList
= ['FIND', 'NAME', 'HELP', 'TYPE', 'PAGE', 'PAGES',
609 'BLOCK', 'OPTION', 'CONDITION', 'ORDER', 'MARKER',
611 self
._HdrKeyList
= ['HEADER', 'STRUCT', 'EMBED', 'COMMENT']
612 self
._BuidinOption
= {'$EN_DIS': 'EN_DIS'}
617 self
._CfgBlkDict
= {}
618 self
._CfgPageDict
= {}
619 self
._CfgOptsDict
= {}
620 self
._BsfTempDict
= {}
621 self
._CfgItemList
= []
624 self
._CfgPageTree
= {}
627 self
._MinCfgTagId
= 0x100
629 def ParseMacros(self
, MacroDefStr
):
630 # ['-DABC=1', '-D', 'CFG_DEBUG=1', '-D', 'CFG_OUTDIR=Build']
633 for Macro
in MacroDefStr
:
634 if Macro
.startswith('-D'):
642 Match
= re
.match("(\\w+)=(.+)", Macro
)
644 self
._MacroDict
[Match
.group(1)] = Match
.group(2)
646 Match
= re
.match("(\\w+)", Macro
)
648 self
._MacroDict
[Match
.group(1)] = ''
649 if len(self
._MacroDict
) == 0:
654 print("INFO : Macro dictionary:")
655 for Each
in self
._MacroDict
:
656 print(" $(%s) = [ %s ]" % (Each
,
657 self
._MacroDict
[Each
]))
660 def EvaulateIfdef(self
, Macro
):
661 Result
= Macro
in self
._MacroDict
663 print("INFO : Eval Ifdef [%s] : %s" % (Macro
, Result
))
666 def ExpandMacros(self
, Input
, Preserve
=False):
668 Match
= re
.findall("\\$\\(\\w+\\)", Input
)
671 Variable
= Each
[2:-1]
672 if Variable
in self
._MacroDict
:
673 Line
= Line
.replace(Each
, self
._MacroDict
[Variable
])
676 print("WARN : %s is not defined" % Each
)
678 Line
= Line
.replace(Each
, Each
[2:-1])
681 def ExpandPcds(self
, Input
):
683 Match
= re
.findall("(\\w+\\.\\w+)", Input
)
685 for PcdName
in Match
:
686 if PcdName
in self
._PcdsDict
:
687 Line
= Line
.replace(PcdName
, self
._PcdsDict
[PcdName
])
690 print("WARN : %s is not defined" % PcdName
)
693 def EvaluateExpress(self
, Expr
):
694 ExpExpr
= self
.ExpandPcds(Expr
)
695 ExpExpr
= self
.ExpandMacros(ExpExpr
)
696 LogExpr
= CLogicalExpression()
697 Result
= LogExpr
.evaluateExpress(ExpExpr
)
699 print("INFO : Eval Express [%s] : %s" % (Expr
, Result
))
702 def ValueToByteArray(self
, ValueStr
, Length
):
703 Match
= re
.match("\\{\\s*FILE:(.+)\\}", ValueStr
)
705 FileList
= Match
.group(1).split(',')
707 for File
in FileList
:
709 BinPath
= os
.path
.join(os
.path
.dirname(self
._DscFile
), File
)
710 Result
.extend(bytearray(open(BinPath
, 'rb').read()))
713 Result
= bytearray(self
.ValueToList(ValueStr
, Length
))
715 raise Exception("Bytes in '%s' must be in range 0~255 !" %
717 if len(Result
) < Length
:
718 Result
.extend(b
'\x00' * (Length
- len(Result
)))
719 elif len(Result
) > Length
:
720 raise Exception("Value '%s' is too big to fit into %d bytes !" %
723 return Result
[:Length
]
725 def ValueToList(self
, ValueStr
, Length
):
726 if ValueStr
[0] == '{':
728 BinList
= ValueStr
[1:-1].split(',')
730 LastInBitField
= False
733 for Element
in BinList
:
735 Each
= Element
.strip()
739 if Each
[0] in ['"', "'"]:
740 Result
.extend(list(bytearray(Each
[1:-1], 'utf-8')))
742 Match
= re
.match("(.+):(\\d+)b", Each
)
744 raise Exception("Invald value list format '%s' !"
747 CurrentBitLen
= int(Match
.group(2))
748 CurrentValue
= ((self
.EvaluateExpress(Match
.group(1))
749 & (1 << CurrentBitLen
) - 1)) << BitLen
751 Result
.append(self
.EvaluateExpress(Each
.strip()))
753 Value
+= CurrentValue
754 BitLen
+= CurrentBitLen
755 if LastInBitField
and ((not InBitField
) or (Element
==
758 raise Exception("Invald bit field length!")
759 Result
.extend(Val2Bytes(Value
, BitLen
// 8))
762 LastInBitField
= InBitField
763 elif ValueStr
.startswith("'") and ValueStr
.endswith("'"):
764 Result
= Str2Bytes(ValueStr
, Length
)
765 elif ValueStr
.startswith('"') and ValueStr
.endswith('"'):
766 Result
= Str2Bytes(ValueStr
, Length
)
768 Result
= Val2Bytes(self
.EvaluateExpress(ValueStr
), Length
)
771 def FormatDeltaValue(self
, ConfigDict
):
772 ValStr
= ConfigDict
['value']
774 # Remove padding \x00 in the value string
775 ValStr
= "'%s'" % ValStr
[1:-1].rstrip('\x00')
777 Struct
= ConfigDict
['struct']
778 if Struct
in self
._StructType
:
779 # Format the array using its struct type
780 Unit
= int(Struct
[4:]) // 8
781 Value
= Array2Val(ConfigDict
['value'])
782 Loop
= ConfigDict
['length'] // Unit
784 for Each
in range(Loop
):
785 Values
.append(Value
& ((1 << (Unit
* 8)) - 1))
786 Value
= Value
>> (Unit
* 8)
787 ValStr
= '{ ' + ', '.join([('0x%%0%dX' % (Unit
* 2)) %
788 x
for x
in Values
]) + ' }'
792 def FormatListValue(self
, ConfigDict
):
793 Struct
= ConfigDict
['struct']
794 if Struct
not in self
._StructType
:
797 DataList
= self
.ValueToList(ConfigDict
['value'], ConfigDict
['length'])
798 Unit
= int(Struct
[4:]) // 8
799 if int(ConfigDict
['length']) != Unit
* len(DataList
):
800 # Fallback to byte array
802 if int(ConfigDict
['length']) != len(DataList
):
803 raise Exception("Array size is not proper for '%s' !" %
807 for Value
in DataList
:
808 for Loop
in range(Unit
):
809 ByteArray
.append("0x%02X" % (Value
& 0xFF))
811 NewValue
= '{' + ','.join(ByteArray
) + '}'
812 ConfigDict
['value'] = NewValue
816 def GetOrderNumber(self
, Offset
, Order
, BitOff
=0):
817 if isinstance(Order
, int):
821 (Major
, Minor
) = Order
.split('.')
822 Order
= (int(Major
, 16) << 16) + ((int(Minor
, 16) & 0xFF) << 8)
823 return Order
+ (BitOff
& 0xFF)
825 def SubtituteLine(self
, Line
, Args
):
827 Vars
= Args
.split(':')
828 Line
= self
.ExpandMacros(Line
, True)
829 for Idx
in range(len(Vars
)-1, 0, -1):
830 Line
= Line
.replace('$(%d)' % Idx
, Vars
[Idx
].strip())
833 def CfgDuplicationCheck(self
, CfgDict
, Name
):
840 if Name
not in CfgDict
:
843 print("WARNING: Duplicated item found '%s' !" %
846 def AddBsfChildPage(self
, Child
, Parent
='root'):
847 def AddBsfChildPageRecursive(PageTree
, Parent
, Child
):
848 Key
= next(iter(PageTree
))
850 PageTree
[Key
].append({Child
: []})
854 for Each
in PageTree
[Key
]:
855 if AddBsfChildPageRecursive(Each
, Parent
, Child
):
860 return AddBsfChildPageRecursive(self
._CfgPageTree
, Parent
, Child
)
862 def ParseDscFile(self
, DscFile
):
864 self
._CfgItemList
= []
865 self
._CfgPageDict
= {}
866 self
._CfgBlkDict
= {}
867 self
._BsfTempDict
= {}
868 self
._CfgPageTree
= {'root': []}
872 SectionNameList
= ["Defines".lower(), "PcdsFeatureFlag".lower(),
873 "PcdsDynamicVpd.Tmp".lower(),
874 "PcdsDynamicVpd.Upd".lower()]
888 if type(DscFile
) is list:
889 # it is DSC lines already
893 DscFd
= open(DscFile
, "r")
894 DscLines
= DscFd
.readlines()
896 self
._DscFile
= DscFile
898 BsfRegExp
= re
.compile("(%s):{(.+?)}(?:$|\\s+)" % '|'.
899 join(self
._BsfKeyList
))
900 HdrRegExp
= re
.compile("(%s):{(.+?)}" % '|'.join(self
._HdrKeyList
))
901 CfgRegExp
= re
.compile("^([_a-zA-Z0-9]+)\\s*\\|\\s*\
902 (0x[0-9A-F]+|\\*)\\s*\\|\\s*(\\d+|0x[0-9a-fA-F]+)\\s*\\|\\s*(.+)")
903 TksRegExp
= re
.compile("^(g[_a-zA-Z0-9]+\\.)(.+)")
906 DscLine
= DscLines
.pop(0).strip()
908 self
._DscLines
.append(DscLine
)
910 SkipLines
= SkipLines
- 1
911 if len(DscLine
) == 0:
915 Match
= re
.match("^\\[(.+)\\]", DscLine
)
916 if Match
is not None:
921 SectionName
= Match
.group(1).lower()
922 if SectionName
== SectionNameList
[0]:
924 if SectionName
== SectionNameList
[1]:
926 elif SectionName
== SectionNameList
[2]:
928 elif SectionName
== SectionNameList
[3]:
946 if IsDefSect
or IsPcdSect
or IsUpdSect
or IsTmpSect
:
947 Match
= False if DscLine
[0] != '!' else True
949 Match
= re
.match("^!(else|endif|ifdef|ifndef|if|elseif\
950 |include)\\s*(.+)?$", DscLine
.split("#")[0])
951 Keyword
= Match
.group(1) if Match
else ''
952 Remaining
= Match
.group(2) if Match
else ''
953 Remaining
= '' if Remaining
is None else Remaining
.strip()
955 if Keyword
in ['if', 'elseif', 'ifdef', 'ifndef', 'include'
957 raise Exception("ERROR: Expression is expected after \
958 '!if' or !elseif' for line '%s'" % DscLine
)
960 if Keyword
== 'else':
962 IfStack
[-1] = not IfStack
[-1]
964 raise Exception("ERROR: No paired '!if' found for \
965 '!else' for line '%s'" % DscLine
)
966 elif Keyword
== 'endif':
969 Level
= ElifStack
.pop()
973 raise Exception("ERROR: No paired '!if' found for \
974 '!endif' for line '%s'" % DscLine
)
975 elif Keyword
== 'ifdef' or Keyword
== 'ifndef':
976 Result
= self
.EvaulateIfdef(Remaining
)
977 if Keyword
== 'ifndef':
979 IfStack
.append(Result
)
981 elif Keyword
== 'if' or Keyword
== 'elseif':
982 Result
= self
.EvaluateExpress(Remaining
)
985 IfStack
.append(Result
)
988 IfStack
[-1] = not IfStack
[-1]
989 IfStack
.append(Result
)
990 ElifStack
[-1] = ElifStack
[-1] + 1
992 raise Exception("ERROR: No paired '!if' found for \
993 '!elif' for line '%s'" % DscLine
)
996 Handle
= reduce(lambda x
, y
: x
and y
, IfStack
)
1000 if Keyword
== 'include':
1001 Remaining
= self
.ExpandMacros(Remaining
)
1002 # Relative to DSC filepath
1003 IncludeFilePath
= os
.path
.join(
1004 os
.path
.dirname(self
._DscFile
), Remaining
)
1005 if not os
.path
.exists(IncludeFilePath
):
1006 # Relative to repository to find \
1007 # dsc in common platform
1008 IncludeFilePath
= os
.path
.join(
1009 os
.path
.dirname(self
._DscFile
), "..",
1013 IncludeDsc
= open(IncludeFilePath
, "r")
1015 raise Exception("ERROR: Cannot open \
1016 file '%s'." % IncludeFilePath
)
1017 NewDscLines
= IncludeDsc
.readlines()
1019 DscLines
= NewDscLines
+ DscLines
1020 del self
._DscLines
[-1]
1022 if DscLine
.startswith('!'):
1023 raise Exception("ERROR: Unrecoginized \
1024 directive for line '%s'" % DscLine
)
1027 del self
._DscLines
[-1]
1031 Match
= re
.match("^\\s*(?:DEFINE\\s+)*(\\w+)\\s*=\\s*(.+)",
1034 self
._MacroDict
[Match
.group(1)] = Match
.group(2)
1036 print("INFO : DEFINE %s = [ %s ]" % (Match
.group(1),
1040 Match
= re
.match("^\\s*([\\w\\.]+)\\s*\\|\\s*(\\w+)", DscLine
)
1042 self
._PcdsDict
[Match
.group(1)] = Match
.group(2)
1044 print("INFO : PCD %s = [ %s ]" % (Match
.group(1),
1048 # !BSF DEFT:{GPIO_TMPL:START}
1049 Match
= re
.match("^\\s*#\\s+(!BSF)\\s+DEFT:{(.+?):\
1050 (START|END)}", DscLine
)
1052 if Match
.group(3) == 'START' and not TemplateName
:
1053 TemplateName
= Match
.group(2).strip()
1054 self
._BsfTempDict
[TemplateName
] = []
1055 if Match
.group(3) == 'END' and (
1056 TemplateName
== Match
.group(2).strip()
1061 Match
= re
.match("^!include\\s*(.+)?$", DscLine
)
1064 self
._BsfTempDict
[TemplateName
].append(DscLine
)
1067 Match
= re
.match("^\\s*#\\s+(!BSF|!HDR)\\s+(.+)", DscLine
)
1069 Remaining
= Match
.group(2)
1070 if Match
.group(1) == '!BSF':
1071 Result
= BsfRegExp
.findall(Remaining
)
1079 "NAME:\"(.+)\"\\s*,\\s*\
1080 VER:\"(.+)\"\\s*", Remaining
)
1082 self
._CfgBlkDict
['name'] = \
1084 self
._CfgBlkDict
['ver'] = Match
.group(2
1089 Remaining
= Remaining
.strip()
1090 Match
= re
.match("(\\w+)\\s*:", Remaining
)
1092 TemplateName
= Match
.group(1)
1093 for Line
in self
._BsfTempDict
[
1094 TemplateName
][::-1]:
1095 NewLine
= self
.SubtituteLine(
1097 DscLines
.insert(0, NewLine
)
1100 elif Key
== 'PAGES':
1101 # !BSF PAGES:{HSW:"Haswell System Agent", \
1102 # LPT:"Lynx Point PCH"}
1103 PageList
= Remaining
.split(',')
1104 for Page
in PageList
:
1106 Match
= re
.match('(\\w+):\
1107 (\\w*:)?\\"(.+)\\"', Page
)
1109 PageName
= Match
.group(1)
1110 ParentName
= Match
.group(2)
1111 if not ParentName
or \
1115 ParentName
= ParentName
[:-1]
1116 if not self
.AddBsfChildPage(
1117 PageName
, ParentName
):
1118 raise Exception("Cannot find \
1119 parent page '%s'!" % ParentName
)
1121 PageName
] = Match
.group(3)
1123 raise Exception("Invalid page \
1124 definitions '%s'!" % Page
)
1126 elif Key
in ['NAME', 'HELP', 'OPTION'
1127 ] and Remaining
.startswith('+'):
1128 # Allow certain options to be extended \
1130 ConfigDict
[Key
.lower()] += Remaining
[1:]
1134 Remaining
= Remaining
.strip()
1135 elif Key
== 'CONDITION':
1136 Remaining
= self
.ExpandMacros(
1138 ConfigDict
[Key
.lower()] = Remaining
1140 Match
= HdrRegExp
.match(Remaining
)
1142 Key
= Match
.group(1)
1143 Remaining
= Match
.group(2)
1145 Parts
= Remaining
.split(':')
1146 Names
= Parts
[0].split(',')
1147 DummyDict
= ConfigDict
.copy()
1149 Remaining
= Names
[0] + ':' + ':'.join(
1151 DummyDict
['struct'] = Names
[1]
1153 DummyDict
['struct'] = Names
[0]
1154 DummyDict
['cname'] = 'Dummy'
1155 DummyDict
['name'] = ''
1156 DummyDict
['embed'] = Remaining
1157 DummyDict
['offset'] = Offset
1158 DummyDict
['length'] = 0
1159 DummyDict
['value'] = '0'
1160 DummyDict
['type'] = 'Reserved'
1161 DummyDict
['help'] = ''
1162 DummyDict
['subreg'] = []
1163 self
._CfgItemList
.append(DummyDict
)
1165 ConfigDict
[Key
.lower()] = Remaining
1167 # gCfgData.VariableName | * | 0x01 | 0x1
1170 Match
= TksRegExp
.match(DscLine
)
1172 DscLine
= 'gCfgData.%s' % Match
.group(2)
1174 if DscLine
.startswith('gCfgData.'):
1175 Match
= CfgRegExp
.match(DscLine
[9:])
1179 ConfigDict
['space'] = 'gCfgData'
1180 ConfigDict
['cname'] = Match
.group(1)
1181 if Match
.group(2) != '*':
1182 Offset
= int(Match
.group(2), 16)
1183 ConfigDict
['offset'] = Offset
1184 ConfigDict
['order'] = self
.GetOrderNumber(
1185 ConfigDict
['offset'], ConfigDict
['order'])
1187 Value
= Match
.group(4).strip()
1188 if Match
.group(3).startswith("0x"):
1189 Length
= int(Match
.group(3), 16)
1191 Length
= int(Match
.group(3))
1195 ConfigDict
['length'] = Length
1196 Match
= re
.match("\\$\\((\\w+)\\)", Value
)
1198 if Match
.group(1) in self
._MacroDict
:
1199 Value
= self
._MacroDict
[Match
.group(1)]
1201 ConfigDict
['value'] = Value
1202 if re
.match("\\{\\s*FILE:(.+)\\}", Value
):
1203 # Expand embedded binary file
1204 ValArray
= self
.ValueToByteArray(ConfigDict
['value'],
1205 ConfigDict
['length'])
1206 NewValue
= Bytes2Str(ValArray
)
1207 self
._DscLines
[-1] = re
.sub(r
'(.*)(\{\s*FILE:.+\})',
1208 r
'\1 %s' % NewValue
,
1210 ConfigDict
['value'] = NewValue
1212 if ConfigDict
['name'] == '':
1213 # Clear BSF specific items
1214 ConfigDict
['bsfname'] = ''
1215 ConfigDict
['help'] = ''
1216 ConfigDict
['type'] = ''
1217 ConfigDict
['option'] = ''
1219 self
.CfgDuplicationCheck(CfgDict
, ConfigDict
['cname'])
1220 self
._CfgItemList
.append(ConfigDict
.copy())
1224 # It could be a virtual item as below
1225 # !BSF FIELD:{SerialDebugPortAddress0:1}
1227 # @Bsf FIELD:{SerialDebugPortAddress0:1b}
1228 Match
= re
.match(r
"^\s*#\s+(!BSF)\s+FIELD:{(.+)}", DscLine
)
1230 BitFieldTxt
= Match
.group(2)
1231 Match
= re
.match("(.+):(\\d+)b([BWDQ])?", BitFieldTxt
)
1233 raise Exception("Incorrect bit field \
1234 format '%s' !" % BitFieldTxt
)
1236 SubCfgDict
= ConfigDict
.copy()
1237 SubCfgDict
['cname'] = Match
.group(1)
1238 SubCfgDict
['bitlength'] = int(
1239 Match
.group(2)) * UnitBitLen
1240 if SubCfgDict
['bitlength'] > 0:
1241 LastItem
= self
._CfgItemList
[-1]
1242 if len(LastItem
['subreg']) == 0:
1246 LastItem
['subreg'][-1]['bitoffset'] \
1247 + LastItem
['subreg'][-1]['bitlength']
1248 if Match
.group(3) == 'B':
1249 SubCfgDict
['bitunit'] = 1
1250 elif Match
.group(3) == 'W':
1251 SubCfgDict
['bitunit'] = 2
1252 elif Match
.group(3) == 'Q':
1253 SubCfgDict
['bitunit'] = 8
1255 SubCfgDict
['bitunit'] = 4
1256 SubCfgDict
['bitoffset'] = SubOffset
1257 SubCfgDict
['order'] = self
.GetOrderNumber(
1258 SubCfgDict
['offset'], SubCfgDict
['order'],
1260 SubCfgDict
['value'] = ''
1261 SubCfgDict
['cname'] = '%s_%s' % (LastItem
['cname'],
1263 self
.CfgDuplicationCheck(CfgDict
,
1264 SubCfgDict
['cname'])
1265 LastItem
['subreg'].append(SubCfgDict
.copy())
1269 ConfigDict
['name'] = ''
1270 ConfigDict
['find'] = ''
1271 ConfigDict
['struct'] = ''
1272 ConfigDict
['embed'] = ''
1273 ConfigDict
['marker'] = ''
1274 ConfigDict
['comment'] = ''
1275 ConfigDict
['order'] = -1
1276 ConfigDict
['subreg'] = []
1277 ConfigDict
['option'] = ''
1278 ConfigDict
['condition'] = ''
1282 def GetBsfBitFields(self
, subitem
, bytes
):
1283 start
= subitem
['bitoffset']
1284 end
= start
+ subitem
['bitlength']
1285 bitsvalue
= ''.join('{0:08b}'.format(i
) for i
in bytes
[::-1])
1286 bitsvalue
= bitsvalue
[::-1]
1287 bitslen
= len(bitsvalue
)
1288 if start
> bitslen
or end
> bitslen
:
1289 raise Exception("Invalid bits offset [%d,%d] %d for %s" %
1290 (start
, end
, bitslen
, subitem
['name']))
1291 return '0x%X' % (int(bitsvalue
[start
:end
][::-1], 2))
1293 def UpdateBsfBitFields(self
, SubItem
, NewValue
, ValueArray
):
1294 Start
= SubItem
['bitoffset']
1295 End
= Start
+ SubItem
['bitlength']
1296 Blen
= len(ValueArray
)
1297 BitsValue
= ''.join('{0:08b}'.format(i
) for i
in ValueArray
[::-1])
1298 BitsValue
= BitsValue
[::-1]
1299 BitsLen
= len(BitsValue
)
1300 if Start
> BitsLen
or End
> BitsLen
:
1301 raise Exception("Invalid bits offset [%d,%d] %d for %s" %
1302 (Start
, End
, BitsLen
, SubItem
['name']))
1303 BitsValue
= BitsValue
[:Start
] + '{0:0{1}b}'.format(
1304 NewValue
, SubItem
['bitlength'])[::-1] + BitsValue
[End
:]
1305 ValueArray
[:] = bytearray
.fromhex(
1306 '{0:0{1}x}'.format(int(BitsValue
[::-1], 2), Blen
* 2))[::-1]
1308 def CreateVarDict(self
):
1311 if len(self
._CfgItemList
) > 0:
1312 Item
= self
._CfgItemList
[-1]
1313 self
._VarDict
['_LENGTH_'] = '%d' % (Item
['offset'] +
1315 for Item
in self
._CfgItemList
:
1316 Embed
= Item
['embed']
1317 Match
= re
.match("^(\\w+):(\\w+):(START|END)", Embed
)
1319 StructName
= Match
.group(1)
1320 VarName
= '_%s_%s_' % (Match
.group(3), StructName
)
1321 if Match
.group(3) == 'END':
1322 self
._VarDict
[VarName
] = Item
['offset'] + Item
['length']
1323 self
._VarDict
['_LENGTH_%s_' % StructName
] = \
1324 self
._VarDict
['_END_%s_' % StructName
] - \
1325 self
._VarDict
['_START_%s_' % StructName
]
1326 if Match
.group(2).startswith('TAG_'):
1327 if (self
.Mode
!= 'FSP') and (self
._VarDict
1330 raise Exception("Size of structure '%s' is %d, \
1331 not DWORD aligned !" % (StructName
, self
._VarDict
['_LENGTH_%s_' % StructName
]))
1332 self
._VarDict
['_TAG_%s_' % StructName
] = int(
1333 Match
.group(2)[4:], 16) & 0xFFF
1335 self
._VarDict
[VarName
] = Item
['offset']
1337 self
._VarDict
['_OFFSET_%s_' % Item
['marker'].strip()] = \
1341 def UpdateBsfBitUnit(self
, Item
):
1346 UnitDec
= {1: 'BYTE', 2: 'WORD', 4: 'DWORD', 8: 'QWORD'}
1347 for Idx
, SubItem
in enumerate(Item
['subreg']):
1349 Unit
= SubItem
['bitunit']
1350 BitLength
= SubItem
['bitlength']
1351 BitTotal
+= BitLength
1352 BitOffset
+= BitLength
1354 if BitOffset
> 64 or BitOffset
> Unit
* 8:
1357 if BitOffset
== Unit
* 8:
1358 for SubIdx
in range(StartIdx
, Idx
+ 1):
1359 Item
['subreg'][SubIdx
]['bitunit'] = Unit
1365 raise Exception("Bit fields cannot fit into %s for \
1366 '%s.%s' !" % (UnitDec
[Unit
], Item
['cname'], SubItem
['cname']))
1368 ExpectedTotal
= Item
['length'] * 8
1369 if Item
['length'] * 8 != BitTotal
:
1370 raise Exception("Bit fields total length (%d) does not match \
1371 length (%d) of '%s' !" % (BitTotal
, ExpectedTotal
, Item
['cname']))
1373 def UpdateDefaultValue(self
):
1375 for Idx
, Item
in enumerate(self
._CfgItemList
):
1376 if len(Item
['subreg']) == 0:
1377 Value
= Item
['value']
1378 if (len(Value
) > 0) and (Value
[0] == '{' or Value
[0] == "'" or
1380 # {XXX} or 'XXX' strings
1381 self
.FormatListValue(self
._CfgItemList
[Idx
])
1383 Match
= re
.match("(0x[0-9a-fA-F]+|[0-9]+)", Value
)
1385 NumValue
= self
.EvaluateExpress(Value
)
1386 Item
['value'] = '0x%X' % NumValue
1388 ValArray
= self
.ValueToByteArray(Item
['value'], Item
['length'])
1389 for SubItem
in Item
['subreg']:
1390 SubItem
['value'] = self
.GetBsfBitFields(SubItem
, ValArray
)
1391 self
.UpdateBsfBitUnit(Item
)
1395 def ExpandIncludeFiles(FilePath
, CurDir
=''):
1397 CurDir
= os
.path
.dirname(FilePath
)
1398 FilePath
= os
.path
.basename(FilePath
)
1400 InputFilePath
= os
.path
.join(CurDir
, FilePath
)
1401 File
= open(InputFilePath
, "r")
1402 Lines
= File
.readlines()
1406 for LineNum
, Line
in enumerate(Lines
):
1407 Match
= re
.match("^!include\\s*(.+)?$", Line
)
1409 IncPath
= Match
.group(1)
1410 TmpPath
= os
.path
.join(CurDir
, IncPath
)
1412 if not os
.path
.exists(TmpPath
):
1413 CurDir
= os
.path
.join(os
.path
.dirname(
1414 os
.path
.realpath(__file__
)), "..", "..")
1415 TmpPath
= os
.path
.join(CurDir
, IncPath
)
1416 if not os
.path
.exists(TmpPath
):
1417 raise Exception("ERROR: Cannot open include file '%s'." %
1420 NewLines
.append(('# Included from file: %s\n' %
1421 IncPath
, TmpPath
, 0))
1422 NewLines
.append(('# %s\n' % ('=' * 80), TmpPath
, 0))
1423 NewLines
.extend(CGenCfgData
.ExpandIncludeFiles
1426 NewLines
.append((Line
, InputFilePath
, LineNum
))
1430 def OverrideDefaultValue(self
, DltFile
):
1432 DltLines
= CGenCfgData
.ExpandIncludeFiles(DltFile
)
1435 for Line
, FilePath
, LineNum
in DltLines
:
1437 if not Line
or Line
.startswith('#'):
1439 Match
= re
.match("\\s*(\\w+)\\.(\\w+)(\\.\\w+)?\\s*\\|\\s*(.+)",
1442 raise Exception("Unrecognized line '%s' (File:'%s' Line:%d) !"
1443 % (Line
, FilePath
, LineNum
+ 1))
1447 for Idx
, Item
in enumerate(self
._CfgItemList
):
1449 if not (Item
['embed'].endswith(':START') and
1450 Item
['embed'].startswith(Match
.group(1))):
1453 if Item
['cname'] == Match
.group(2):
1456 if Item
['embed'].endswith(':END') and \
1457 Item
['embed'].startswith(Match
.group(1)):
1459 Name
= '%s.%s' % (Match
.group(1), Match
.group(2))
1461 ErrItem
= Match
.group(2) if InScope
else Match
.group(1)
1462 raise Exception("Invalid configuration '%s' in '%s' \
1463 (File:'%s' Line:%d) !" % (ErrItem
, Name
, FilePath
, LineNum
+ 1))
1465 ValueStr
= Match
.group(4).strip()
1466 if Match
.group(3) is not None:
1467 # This is a subregion item
1468 BitField
= Match
.group(3)[1:]
1470 if len(Item
['subreg']) > 0:
1471 for SubItem
in Item
['subreg']:
1472 if SubItem
['cname'] == '%s_%s' % \
1473 (Item
['cname'], BitField
):
1477 raise Exception("Invalid configuration bit field \
1478 '%s' in '%s.%s' (File:'%s' Line:%d) !" % (BitField
, Name
, BitField
,
1479 FilePath
, LineNum
+ 1))
1482 Value
= int(ValueStr
, 16) if ValueStr
.startswith('0x') \
1483 else int(ValueStr
, 10)
1485 raise Exception("Invalid value '%s' for bit field '%s.%s' \
1486 (File:'%s' Line:%d) !" % (ValueStr
, Name
, BitField
, FilePath
, LineNum
+ 1))
1488 if Value
>= 2 ** SubItem
['bitlength']:
1489 raise Exception("Invalid configuration bit field value \
1490 '%s' for '%s.%s' (File:'%s' Line:%d) !" % (Value
, Name
, BitField
,
1491 FilePath
, LineNum
+ 1))
1493 ValArray
= self
.ValueToByteArray(Item
['value'], Item
['length'])
1494 self
.UpdateBsfBitFields(SubItem
, Value
, ValArray
)
1496 if Item
['value'].startswith('{'):
1497 Item
['value'] = '{' + ', '.join('0x%02X' % i
1498 for i
in ValArray
) + '}'
1500 BitsValue
= ''.join('{0:08b}'.format(i
)
1501 for i
in ValArray
[::-1])
1502 Item
['value'] = '0x%X' % (int(BitsValue
, 2))
1504 if Item
['value'].startswith('{') and \
1505 not ValueStr
.startswith('{'):
1506 raise Exception("Data array required for '%s' \
1507 (File:'%s' Line:%d) !" % (Name
, FilePath
, LineNum
+ 1))
1508 Item
['value'] = ValueStr
1510 if Name
== 'PLATFORMID_CFG_DATA.PlatformId':
1511 PlatformId
= ValueStr
1513 if (PlatformId
is None) and (self
.Mode
!= 'FSP'):
1514 raise Exception("PLATFORMID_CFG_DATA.PlatformId is missing \
1515 in file '%s' !" % (DltFile
))
1519 def ProcessMultilines(self
, String
, MaxCharLength
):
1521 StringLength
= len(String
)
1522 CurrentStringStart
= 0
1525 if len(String
) <= MaxCharLength
:
1526 while (StringOffset
< StringLength
):
1527 if StringOffset
>= 1:
1528 if String
[StringOffset
- 1] == '\\' and \
1529 String
[StringOffset
] == 'n':
1530 BreakLineDict
.append(StringOffset
+ 1)
1532 if BreakLineDict
!= []:
1533 for Each
in BreakLineDict
:
1534 Multilines
+= " %s\n" % String
[CurrentStringStart
:Each
].\
1536 CurrentStringStart
= Each
1537 if StringLength
- CurrentStringStart
> 0:
1538 Multilines
+= " %s\n" % String
[CurrentStringStart
:].\
1541 Multilines
= " %s\n" % String
1545 FoundSpaceChar
= False
1546 while(StringOffset
< StringLength
):
1547 if StringOffset
>= 1:
1548 if NewLineCount
>= MaxCharLength
- 1:
1549 if String
[StringOffset
] == ' ' and \
1550 StringLength
- StringOffset
> 10:
1551 BreakLineDict
.append(NewLineStart
+ NewLineCount
)
1552 NewLineStart
= NewLineStart
+ NewLineCount
1554 FoundSpaceChar
= True
1555 elif StringOffset
== StringLength
- 1 \
1556 and FoundSpaceChar
is False:
1557 BreakLineDict
.append(0)
1558 if String
[StringOffset
- 1] == '\\' and \
1559 String
[StringOffset
] == 'n':
1560 BreakLineDict
.append(StringOffset
+ 1)
1561 NewLineStart
= StringOffset
+ 1
1565 if BreakLineDict
!= []:
1566 BreakLineDict
.sort()
1567 for Each
in BreakLineDict
:
1569 Multilines
+= " %s\n" % String
[
1570 CurrentStringStart
:Each
].lstrip()
1571 CurrentStringStart
= Each
1572 if StringLength
- CurrentStringStart
> 0:
1573 Multilines
+= " %s\n" % String
[CurrentStringStart
:].\
1577 def CreateField(self
, Item
, Name
, Length
, Offset
, Struct
,
1578 BsfName
, Help
, Option
, BitsLength
=None):
1584 if Length
== 0 and Name
== 'Dummy':
1588 if Length
in [1, 2, 4, 8]:
1589 Type
= "UINT%d" % (Length
* 8)
1594 if Item
and Item
['value'].startswith('{'):
1600 if Struct
in ['UINT8', 'UINT16', 'UINT32', 'UINT64']:
1602 Unit
= int(Type
[4:]) // 8
1603 Length
= Length
/ Unit
1608 Name
= Name
+ '[%d]' % Length
1610 if len(Type
) < PosName
:
1611 Space1
= PosName
- len(Type
)
1616 NameLine
= " %s\n" % BsfName
1621 HelpLine
= self
.ProcessMultilines(Help
, 80)
1624 OptionLine
= self
.ProcessMultilines(Option
, 80)
1626 if BitsLength
is None:
1629 BitsLength
= ' : %d' % BitsLength
1631 return "\n/** %s%s%s**/\n %s%s%s%s;\n" % \
1632 (NameLine
, HelpLine
, OptionLine
, Type
, ' ' * Space1
, Name
,
1635 def SplitTextBody(self
, TextBody
):
1636 Marker1
= '{ /* _COMMON_STRUCT_START_ */'
1637 Marker2
= '; /* _COMMON_STRUCT_END_ */'
1641 for Line
in TextBody
:
1642 if Line
.strip().endswith(Marker1
):
1643 Line
= Line
.replace(Marker1
[1:], '')
1645 if Line
.strip().endswith(Marker2
):
1646 Line
= Line
.replace(Marker2
[1:], '')
1648 ComBody
.append(Line
)
1652 ComBody
.append(Line
)
1654 TxtBody
.append(Line
)
1655 return ComBody
, TxtBody
1657 def GetStructArrayInfo(self
, Input
):
1658 ArrayStr
= Input
.split('[')
1660 if len(ArrayStr
) > 1:
1661 NumStr
= ''.join(c
for c
in ArrayStr
[-1] if c
.isdigit())
1662 NumStr
= '1000' if len(NumStr
) == 0 else NumStr
1663 ArrayNum
= int(NumStr
)
1666 return Name
, ArrayNum
1668 def PostProcessBody(self
, TextBody
, IncludeEmbedOnly
=True):
1680 IsCommonStruct
= False
1682 for Line
in TextBody
:
1683 if Line
.startswith('#define '):
1684 IncTextBody
.append(Line
)
1687 if not Line
.startswith('/* EMBED_STRUCT:'):
1690 Match
= re
.match("^/\\*\\sEMBED_STRUCT:([\\w\\[\\]\\*]+):\
1691 ([\\w\\[\\]\\*]+):(\\w+):(START|END)([\\s\\d]+)\\*/([\\s\\S]*)", Line
)
1694 ArrayMarker
= Match
.group(5)
1695 if Match
.group(4) == 'END':
1698 Line
= Match
.group(6)
1702 Line
= Match
.group(6)
1705 TagStr
= Match
.group(3)
1706 if TagStr
.startswith('TAG_'):
1708 TagVal
= int(TagStr
[4:], 16)
1711 if (TagVal
>= 0) and (TagVal
< self
._MinCfgTagId
):
1712 IsCommonStruct
= True
1716 Suffix
= ' /* _COMMON_STRUCT_START_ */'
1719 StructBody
= ['typedef struct {%s' % Suffix
]
1720 StructName
= Match
.group(1)
1721 StructType
= Match
.group(2)
1722 VariableName
= Match
.group(3)
1723 MatchOffset
= re
.search('/\\*\\*\\sOffset\\s0x\
1724 ([a-fA-F0-9]+)', Line
)
1726 Offset
= int(MatchOffset
.group(1), 16)
1731 ModifiedStructType
= StructType
.rstrip()
1732 if ModifiedStructType
.endswith(']'):
1733 Idx
= ModifiedStructType
.index('[')
1734 if ArrayMarker
!= ' ':
1736 OldTextBody
.append('')
1737 ArrayVarName
= VariableName
1738 if int(ArrayMarker
) == 1000:
1741 Count
= int(ArrayMarker
) + 1000
1746 VariableTemp
= ArrayVarName
+ '[%d]' % (
1747 Count
if Count
< 1000 else Count
- 1000)
1748 OldTextBody
[-1] = self
.CreateField(
1749 None, VariableTemp
, 0, Offset
,
1750 ModifiedStructType
[:Idx
], '',
1751 'Structure Array', '')
1754 OldTextBody
.append(self
.CreateField(
1755 None, VariableName
, 0, Offset
,
1756 ModifiedStructType
, '', '', ''))
1759 StructBody
.append(Line
)
1761 OldTextBody
.append(Line
)
1763 if Match
and Match
.group(4) == 'END':
1765 if (StructType
!= Match
.group(2)) or \
1766 (VariableName
!= Match
.group(3)):
1767 print("Unmatched struct name '%s' and '%s' !" %
1768 (StructName
, Match
.group(2)))
1771 Suffix
= ' /* _COMMON_STRUCT_END_ */'
1774 Line
= '} %s;%s\n\n\n' % (StructName
, Suffix
)
1775 StructBody
.append(Line
)
1776 if (Line
not in NewTextBody
) and \
1777 (Line
not in OldTextBody
):
1778 NewTextBody
.extend(StructBody
)
1780 IsCommonStruct
= False
1782 if not IncludeEmbedOnly
:
1783 NewTextBody
.extend(OldTextBody
)
1786 NewTextBody
= self
.PostProcessBody(NewTextBody
, False)
1788 NewTextBody
= IncTextBody
+ NewTextBody
1791 def WriteHeaderFile(self
, TxtBody
, FileName
, Type
='h'):
1792 FileNameDef
= os
.path
.basename(FileName
).replace('.', '_')
1793 FileNameDef
= re
.sub('(.)([A-Z][a-z]+)', r
'\1_\2', FileNameDef
)
1794 FileNameDef
= re
.sub('([a-z0-9])([A-Z])', r
'\1_\2',
1795 FileNameDef
).upper()
1798 Lines
.append("%s\n" % GetCopyrightHeader(Type
))
1799 Lines
.append("#ifndef __%s__\n" % FileNameDef
)
1800 Lines
.append("#define __%s__\n\n" % FileNameDef
)
1802 Lines
.append("#pragma pack(1)\n\n")
1803 Lines
.extend(TxtBody
)
1805 Lines
.append("#pragma pack()\n\n")
1806 Lines
.append("#endif\n")
1808 # Don't rewrite if the contents are the same
1810 if os
.path
.exists(FileName
):
1811 HdrFile
= open(FileName
, "r")
1812 OrgTxt
= HdrFile
.read()
1815 NewTxt
= ''.join(Lines
)
1816 if OrgTxt
== NewTxt
:
1820 HdrFile
= open(FileName
, "w")
1821 HdrFile
.write(''.join(Lines
))
1824 def CreateHeaderFile(self
, HdrFileName
, ComHdrFileName
=''):
1837 TxtBody
.append("typedef struct {\n")
1838 for Item
in self
._CfgItemList
:
1839 # Search for CFGDATA tags
1840 Embed
= Item
["embed"].upper()
1841 if Embed
.endswith(':START'):
1842 Match
= re
.match(r
'(\w+)_CFG_DATA:TAG_([0-9A-F]+):START',
1845 TagName
= Match
.group(1)
1846 TagId
= int(Match
.group(2), 16)
1847 CfgTags
.append((TagId
, TagName
))
1849 # Only process visible items
1850 NextVisible
= LastVisible
1852 if LastVisible
and (Item
['header'] == 'OFF'):
1854 ResvOffset
= Item
['offset']
1855 elif (not LastVisible
) and Item
['header'] == 'ON':
1857 Name
= "ReservedUpdSpace%d" % ResvIdx
1858 ResvIdx
= ResvIdx
+ 1
1859 TxtBody
.append(self
.CreateField(
1860 Item
, Name
, Item
["offset"] - ResvOffset
,
1861 ResvOffset
, '', '', '', ''))
1864 if Offset
< Item
["offset"]:
1866 Name
= "UnusedUpdSpace%d" % SpaceIdx
1867 LineBuffer
.append(self
.CreateField
1868 (Item
, Name
, Item
["offset"] -
1869 Offset
, Offset
, '', '', '', ''))
1871 SpaceIdx
= SpaceIdx
+ 1
1872 Offset
= Item
["offset"]
1874 LastVisible
= NextVisible
1876 Offset
= Offset
+ Item
["length"]
1878 for Each
in LineBuffer
:
1879 TxtBody
.append(Each
)
1881 Embed
= Item
["embed"].upper()
1882 if Embed
.endswith(':START') or Embed
.endswith(':END'):
1883 # EMBED_STRUCT: StructName : \
1884 # ItemName : VariableName : START|END
1885 Name
, ArrayNum
= self
.GetStructArrayInfo(Item
["struct"])
1886 Remaining
= Item
["embed"]
1887 if (LastFieldIdx
+ 1 == FieldIdx
) and (LastStruct
== Name
):
1890 ArrayMarker
= '%d' % ArrayNum
1891 LastFieldIdx
= FieldIdx
1893 Marker
= '/* EMBED_STRUCT:%s:%s%s*/ ' % (Name
, Remaining
,
1895 # if Embed.endswith(':START') and Comment != '':
1896 # Marker = '/* COMMENT:%s */ \n' % Item["comment"] + Marker
1901 self
.Error
= "Invalid embedded structure \
1902 format '%s'!\n" % Item
["embed"]
1905 # Generate bit fields for structure
1906 if len(Item
['subreg']) > 0 and Item
["struct"]:
1907 StructType
= Item
["struct"]
1908 StructName
, ArrayNum
= self
.GetStructArrayInfo(StructType
)
1909 if (LastFieldIdx
+ 1 == FieldIdx
) and \
1910 (LastStruct
== Item
["struct"]):
1913 ArrayMarker
= '%d' % ArrayNum
1914 TxtBody
.append('/* EMBED_STRUCT:%s:%s:%s:START%s*/\n' %
1915 (StructName
, StructType
, Item
["cname"],
1917 for SubItem
in Item
['subreg']:
1918 Name
= SubItem
["cname"]
1919 if Name
.startswith(Item
["cname"]):
1920 Name
= Name
[len(Item
["cname"]) + 1:]
1921 Line
= self
.CreateField(
1922 SubItem
, Name
, SubItem
["bitunit"],
1923 SubItem
["offset"], SubItem
['struct'],
1924 SubItem
['name'], SubItem
['help'],
1925 SubItem
['option'], SubItem
['bitlength'])
1926 TxtBody
.append(Line
)
1927 TxtBody
.append('/* EMBED_STRUCT:%s:%s:%s:END%s*/\n' %
1928 (StructName
, StructType
, Item
["cname"],
1930 LastFieldIdx
= FieldIdx
1931 LastStruct
= Item
["struct"]
1935 Line
= Marker
+ self
.CreateField(
1936 Item
, Item
["cname"], Item
["length"], Item
["offset"],
1937 Item
['struct'], Item
['name'], Item
['help'],
1939 TxtBody
.append(Line
)
1941 TxtBody
.append("}\n\n")
1943 # Handle the embedded data structure
1944 TxtBody
= self
.PostProcessBody(TxtBody
)
1945 ComBody
, TxtBody
= self
.SplitTextBody(TxtBody
)
1947 # Prepare TAG defines
1948 PltTagDefTxt
= ['\n']
1949 ComTagDefTxt
= ['\n']
1950 for TagId
, TagName
in sorted(CfgTags
):
1951 TagLine
= '#define %-30s 0x%03X\n' % ('CDATA_%s_TAG' %
1953 if TagId
< self
._MinCfgTagId
:
1954 # TAG ID < 0x100, it is a generic TAG
1955 ComTagDefTxt
.append(TagLine
)
1957 PltTagDefTxt
.append(TagLine
)
1958 PltTagDefTxt
.append('\n\n')
1959 ComTagDefTxt
.append('\n\n')
1962 self
.WriteHeaderFile(PltTagDefTxt
+ TxtBody
, HdrFileName
)
1964 self
.WriteHeaderFile(ComTagDefTxt
+ ComBody
, ComHdrFileName
)
1968 def UpdateConfigItemValue(self
, Item
, ValueStr
):
1969 IsArray
= True if Item
['value'].startswith('{') else False
1970 IsString
= True if Item
['value'].startswith("'") else False
1971 Bytes
= self
.ValueToByteArray(ValueStr
, Item
['length'])
1973 NewValue
= "'%s'" % Bytes
.decode("utf-8")
1975 NewValue
= Bytes2Str(Bytes
)
1977 Fmt
= '0x%X' if Item
['value'].startswith('0x') else '%d'
1978 NewValue
= Fmt
% Bytes2Val(Bytes
)
1979 Item
['value'] = NewValue
1981 def LoadDefaultFromBinaryArray(self
, BinDat
, IgnoreFind
=False):
1984 for Item
in self
._CfgItemList
:
1985 if Item
['length'] == 0:
1987 if not IgnoreFind
and Item
['find']:
1988 FindBin
= Item
['find'].encode()
1989 Offset
= BinDat
.find(FindBin
)
1991 TestOff
= BinDat
[Offset
+len(FindBin
):].find(FindBin
)
1993 raise Exception('Multiple match found for "%s" !' %
1995 FindOff
= Offset
+ len(FindBin
)
1996 StartOff
= Item
['offset']
1998 raise Exception('Could not find "%s" !' % Item
['find'])
1999 if Item
['offset'] + Item
['length'] > len(BinDat
):
2000 raise Exception('Mismatching format between DSC \
2002 Offset
= FindOff
+ (Item
['offset'] - StartOff
)
2003 ValStr
= Bytes2Str(BinDat
[Offset
: Offset
+ Item
['length']])
2004 self
.UpdateConfigItemValue(Item
, ValStr
)
2006 self
.UpdateDefaultValue()
2008 def PatchBinaryArray(self
, BinDat
):
2014 CfgBin
= bytearray()
2015 for Item
in self
._CfgItemList
:
2016 if Item
['length'] == 0:
2021 PatchList
.append((FileOff
, CfgBin
))
2022 FindBin
= Item
['find'].encode()
2023 FileOff
= BinDat
.find(FindBin
)
2025 raise Exception('Could not find "%s" !' % Item
['find'])
2027 TestOff
= BinDat
[FileOff
+len(FindBin
):].find(FindBin
)
2029 raise Exception('Multiple match found for "%s" !' %
2031 FileOff
+= len(FindBin
)
2032 Offset
= Item
['offset']
2034 CfgBin
= bytearray()
2036 if Item
['offset'] > Offset
:
2037 Gap
= Item
['offset'] - Offset
2038 CfgBin
.extend(b
'\x00' * Gap
)
2040 if Item
['type'] == 'Reserved' and Item
['option'] == '$SKIP':
2042 NewOff
= FileOff
+ (Offset
- FindOff
)
2043 FileData
= bytearray(BinDat
[NewOff
: NewOff
+ Item
['length']])
2044 CfgBin
.extend(FileData
)
2046 CfgBin
.extend(self
.ValueToByteArray(Item
['value'],
2048 Offset
= Item
['offset'] + Item
['length']
2051 PatchList
.append((FileOff
, CfgBin
))
2053 for FileOff
, CfgBin
in PatchList
:
2054 Length
= len(CfgBin
)
2055 if FileOff
+ Length
< len(BinDat
):
2056 BinDat
[FileOff
:FileOff
+Length
] = CfgBin
[:]
2060 def GenerateBinaryArray(self
):
2062 BinDat
= bytearray()
2063 for Item
in self
._CfgItemList
:
2064 if Item
['offset'] > Offset
:
2065 Gap
= Item
['offset'] - Offset
2066 BinDat
.extend(b
'\x00' * Gap
)
2067 BinDat
.extend(self
.ValueToByteArray(Item
['value'], Item
['length']))
2068 Offset
= Item
['offset'] + Item
['length']
2071 def GenerateBinary(self
, BinFileName
):
2072 BinFile
= open(BinFileName
, "wb")
2073 BinFile
.write(self
.GenerateBinaryArray())
2077 def GenerateDataIncFile(self
, DatIncFileName
, BinFile
=None):
2078 # Put a prefix GUID before CFGDATA so that it can be located later on
2079 Prefix
= b
'\xa7\xbd\x7f\x73\x20\x1e\x46\xd6\xbe\x8f\
2080 x64\x12\x05\x8d\x0a\xa8'
2082 Fin
= open(BinFile
, 'rb')
2083 BinDat
= Prefix
+ bytearray(Fin
.read())
2086 BinDat
= Prefix
+ self
.GenerateBinaryArray()
2088 FileName
= os
.path
.basename(DatIncFileName
).upper()
2089 FileName
= FileName
.replace('.', '_')
2093 TxtLines
.append("UINT8 mConfigDataBlob[%d] = {\n" % len(BinDat
))
2097 Line
.append('0x%02X, ' % Each
)
2099 if (Count
& 0x0F) == 0:
2101 TxtLines
.append(''.join(Line
))
2104 TxtLines
.append(''.join(Line
) + '\n')
2106 TxtLines
.append("};\n\n")
2108 self
.WriteHeaderFile(TxtLines
, DatIncFileName
, 'inc')
2112 def CheckCfgData(self
):
2113 # Check if CfgData contains any duplicated name
2114 def AddItem(Item
, ChkList
):
2115 Name
= Item
['cname']
2118 if Name
not in ['Dummy', 'Reserved', 'CfgHeader', 'CondValue']:
2119 ChkList
.append(Name
)
2124 for Item
in self
._CfgItemList
:
2125 Duplicate
= AddItem(Item
, ChkList
)
2127 for SubItem
in Item
['subreg']:
2128 Duplicate
= AddItem(SubItem
, ChkList
)
2134 self
.Error
= "Duplicated CFGDATA '%s' found !\n" % \
2139 def PrintData(self
):
2140 for Item
in self
._CfgItemList
:
2141 if not Item
['length']:
2143 print("%-10s @Offset:0x%04X Len:%3d Val:%s" %
2144 (Item
['cname'], Item
['offset'], Item
['length'],
2146 for SubItem
in Item
['subreg']:
2147 print(" %-20s BitOff:0x%04X BitLen:%-3d Val:%s" %
2148 (SubItem
['cname'], SubItem
['bitoffset'],
2149 SubItem
['bitlength'], SubItem
['value']))
2151 def FormatArrayValue(self
, Input
, Length
):
2152 Dat
= self
.ValueToByteArray(Input
, Length
)
2153 return ','.join('0x%02X' % Each
for Each
in Dat
)
2155 def GetItemOptionList(self
, Item
):
2157 if Item
['type'] == "Combo":
2158 if not Item
['option'] in self
._BuidinOption
:
2159 OptList
= Item
['option'].split(',')
2160 for Option
in OptList
:
2161 Option
= Option
.strip()
2163 (OpVal
, OpStr
) = Option
.split(':')
2165 raise Exception("Invalide option format '%s' !" %
2167 TmpList
.append((OpVal
, OpStr
))
2170 def WriteBsfStruct(self
, BsfFd
, Item
):
2171 if Item
['type'] == "None":
2172 Space
= "gPlatformFspPkgTokenSpaceGuid"
2174 Space
= Item
['space']
2175 Line
= " $%s_%s" % (Space
, Item
['cname'])
2176 Match
= re
.match("\\s*(\\{.+\\})\\s*", Item
['value'])
2178 DefaultValue
= self
.FormatArrayValue(Match
.group(1).strip(),
2181 DefaultValue
= Item
['value'].strip()
2182 if 'bitlength' in Item
:
2183 if Item
['bitlength']:
2184 BsfFd
.write(" %s%s%4d bits $_DEFAULT_ = %s\n" %
2185 (Line
, ' ' * (64 - len(Line
)), Item
['bitlength'],
2189 BsfFd
.write(" %s%s%4d bytes $_DEFAULT_ = %s\n" %
2190 (Line
, ' ' * (64 - len(Line
)), Item
['length'],
2193 return self
.GetItemOptionList(Item
)
2195 def GetBsfOption(self
, OptionName
):
2196 if OptionName
in self
._CfgOptsDict
:
2197 return self
._CfgOptsDict
[OptionName
]
2201 def WriteBsfOption(self
, BsfFd
, Item
):
2202 PcdName
= Item
['space'] + '_' + Item
['cname']
2205 if Item
['type'] == "Combo":
2206 if Item
['option'] in self
._BuidinOption
:
2207 Options
= self
._BuidinOption
[Item
['option']]
2209 Options
= self
.GetBsfOption(PcdName
)
2210 BsfLines
.append(' %s $%s, "%s", &%s,\n' % (
2211 Item
['type'], PcdName
, Item
['name'], Options
))
2213 elif Item
['type'].startswith("EditNum"):
2214 Match
= re
.match("EditNum\\s*,\\s*(HEX|DEC)\\s*,\\s*\\(\
2215 (\\d+|0x[0-9A-Fa-f]+)\\s*,\\s*(\\d+|0x[0-9A-Fa-f]+)\\)", Item
['type'])
2217 BsfLines
.append(' EditNum $%s, "%s", %s,\n' % (
2218 PcdName
, Item
['name'], Match
.group(1)))
2220 elif Item
['type'].startswith("EditText"):
2221 BsfLines
.append(' %s $%s, "%s",\n' % (Item
['type'], PcdName
,
2224 elif Item
['type'] == "Table":
2225 Columns
= Item
['option'].split(',')
2226 if len(Columns
) != 0:
2227 BsfLines
.append(' %s $%s "%s",' % (Item
['type'], PcdName
,
2230 Fmt
= Col
.split(':')
2232 raise Exception("Column format '%s' is invalid !" %
2235 Dtype
= int(Fmt
[1].strip())
2237 raise Exception("Column size '%s' is invalid !" %
2239 BsfLines
.append('\n Column "%s", %d bytes, %s' %
2240 (Fmt
[0].strip(), Dtype
, Fmt
[2].strip()))
2241 BsfLines
.append(',\n')
2245 HelpLines
= Item
['help'].split('\\n\\r')
2247 for HelpLine
in HelpLines
:
2250 BsfLines
.append(' Help "%s"\n' % (HelpLine
))
2252 BsfLines
.append(' "%s"\n' % (HelpLine
))
2254 BsfLines
.append(' "Valid range: %s ~ %s"\n' %
2255 (Match
.group(2), Match
.group(3)))
2257 if len(Item
['condition']) > 4:
2258 CondList
= Item
['condition'].split(',')
2260 for Cond
in CondList
:
2262 if Cond
.startswith('#'):
2263 BsfLines
.insert(Idx
, Cond
+ '\n')
2265 elif Cond
.startswith('@#'):
2266 BsfLines
.append(Cond
[1:] + '\n')
2268 for Line
in BsfLines
:
2271 def WriteBsfPages(self
, PageTree
, BsfFd
):
2273 Key
= next(iter(PageTree
))
2274 for Page
in PageTree
[Key
]:
2275 PageName
= next(iter(Page
))
2276 BsfFd
.write('Page "%s"\n' % self
._CfgPageDict
[PageName
])
2277 if len(PageTree
[Key
]):
2278 self
.WriteBsfPages(Page
, BsfFd
)
2281 for Item
in self
._CfgItemList
:
2282 if Item
['name'] != '':
2283 if Item
['page'] != PageName
:
2285 if len(Item
['subreg']) > 0:
2286 for SubItem
in Item
['subreg']:
2287 if SubItem
['name'] != '':
2288 BsfItems
.append(SubItem
)
2290 BsfItems
.append(Item
)
2292 BsfItems
.sort(key
=lambda x
: x
['order'])
2294 for Item
in BsfItems
:
2295 self
.WriteBsfOption(BsfFd
, Item
)
2296 BsfFd
.write("EndPage\n\n")
2298 def GenerateBsfFile(self
, BsfFile
):
2301 self
.Error
= "BSF output file '%s' is invalid" % BsfFile
2306 BsfFd
= open(BsfFile
, "w")
2307 BsfFd
.write("%s\n" % GetCopyrightHeader('bsf'))
2308 BsfFd
.write("%s\n" % self
._GlobalDataDef
)
2309 BsfFd
.write("StructDef\n")
2311 for Item
in self
._CfgItemList
:
2312 if Item
['find'] != '':
2313 BsfFd
.write('\n Find "%s"\n' % Item
['find'])
2314 NextOffset
= Item
['offset'] + Item
['length']
2315 if Item
['name'] != '':
2316 if NextOffset
!= Item
['offset']:
2317 BsfFd
.write(" Skip %d bytes\n" %
2318 (Item
['offset'] - NextOffset
))
2319 if len(Item
['subreg']) > 0:
2320 NextOffset
= Item
['offset']
2321 BitsOffset
= NextOffset
* 8
2322 for SubItem
in Item
['subreg']:
2323 BitsOffset
+= SubItem
['bitlength']
2324 if SubItem
['name'] == '':
2325 if 'bitlength' in SubItem
:
2326 BsfFd
.write(" Skip %d bits\n" %
2327 (SubItem
['bitlength']))
2329 BsfFd
.write(" Skip %d bytes\n" %
2330 (SubItem
['length']))
2332 Options
= self
.WriteBsfStruct(BsfFd
, SubItem
)
2333 if len(Options
) > 0:
2335 ['space']+'_'+SubItem
2336 ['cname']] = Options
2338 NextBitsOffset
= (Item
['offset'] + Item
['length']) * 8
2339 if NextBitsOffset
> BitsOffset
:
2340 BitsGap
= NextBitsOffset
- BitsOffset
2341 BitsRemain
= BitsGap
% 8
2343 BsfFd
.write(" Skip %d bits\n" % BitsRemain
)
2344 BitsGap
-= BitsRemain
2345 BytesRemain
= BitsGap
// 8
2347 BsfFd
.write(" Skip %d bytes\n" %
2349 NextOffset
= Item
['offset'] + Item
['length']
2351 NextOffset
= Item
['offset'] + Item
['length']
2352 Options
= self
.WriteBsfStruct(BsfFd
, Item
)
2353 if len(Options
) > 0:
2354 OptionDict
[Item
['space']+'_'+Item
['cname']] = Options
2355 BsfFd
.write("\nEndStruct\n\n")
2357 BsfFd
.write("%s" % self
._BuidinOptionTxt
)
2361 for Each
in sorted(OptionDict
):
2362 if OptionDict
[Each
] not in OptionList
:
2363 NameList
.append(Each
)
2364 OptionList
.append(OptionDict
[Each
])
2365 BsfFd
.write("List &%s\n" % Each
)
2366 for Item
in OptionDict
[Each
]:
2367 BsfFd
.write(' Selection %s , "%s"\n' %
2368 (self
.EvaluateExpress(Item
[0]), Item
[1]))
2369 BsfFd
.write("EndList\n\n")
2371 # Item has idential options as other item
2372 # Try to reuse the previous options instead
2373 Idx
= OptionList
.index(OptionDict
[Each
])
2374 self
._CfgOptsDict
[Each
] = NameList
[Idx
]
2376 BsfFd
.write("BeginInfoBlock\n")
2377 BsfFd
.write(' PPVer "%s"\n' % (self
._CfgBlkDict
['ver']))
2378 BsfFd
.write(' Description "%s"\n' % (self
._CfgBlkDict
['name']))
2379 BsfFd
.write("EndInfoBlock\n\n")
2381 self
.WriteBsfPages(self
._CfgPageTree
, BsfFd
)
2386 def WriteDeltaLine(self
, OutLines
, Name
, ValStr
, IsArray
):
2388 Output
= '%s | { %s }' % (Name
, ValStr
)
2390 Output
= '%s | 0x%X' % (Name
, Array2Val(ValStr
))
2391 OutLines
.append(Output
)
2393 def WriteDeltaFile(self
, OutFile
, PlatformId
, OutLines
):
2394 DltFd
= open(OutFile
, "w")
2395 DltFd
.write("%s\n" % GetCopyrightHeader('dlt', True))
2396 if PlatformId
is not None:
2398 DltFd
.write('# Delta configuration values \
2399 for platform ID 0x%04X\n' % PlatformId
)
2400 DltFd
.write('#\n\n')
2401 for Line
in OutLines
:
2402 DltFd
.write('%s\n' % Line
)
2405 def GenerateDeltaFile(self
, OutFile
, AbsfFile
):
2406 # Parse ABSF Build in dict
2407 if not os
.path
.exists(AbsfFile
):
2410 with
open(AbsfFile
) as Fin
:
2411 Lines
= Fin
.readlines()
2413 AbsfBuiltValDict
= {}
2417 if Line
.startswith('StructDef'):
2419 if Line
.startswith('EndStruct'):
2423 Match
= re
.match('\\s*\\$gCfgData_(\\w+)\\s+\
2424 (\\d+)\\s+(bits|bytes)\\s+\\$_AS_BUILT_\\s+=\\s+(.+)\\$', Line
)
2426 if Match
.group(1) not in AbsfBuiltValDict
:
2427 AbsfBuiltValDict
[Match
.group(1)] = Match
.group(4).strip()
2429 raise Exception("Duplicated configuration \
2430 name '%s' found !", Match
.group(1))
2432 # Match config item in DSC
2437 for Item
in self
._CfgItemList
:
2439 if Level
== 0 and Item
['embed'].endswith(':START'):
2440 TagName
= Item
['embed'].split(':')[0]
2442 if Item
['cname'] in AbsfBuiltValDict
:
2443 ValStr
= AbsfBuiltValDict
[Item
['cname']]
2444 Name
= '%s.%s' % (TagName
, Item
['cname'])
2445 if not Item
['subreg'] and Item
['value'].startswith('{'):
2446 Value
= Array2Val(Item
['value'])
2449 Value
= int(Item
['value'], 16)
2451 AbsfVal
= Array2Val(ValStr
)
2452 if AbsfVal
!= Value
:
2453 if 'PLATFORMID_CFG_DATA.PlatformId' == Name
:
2454 PlatformId
= AbsfVal
2455 self
.WriteDeltaLine(OutLines
, Name
, ValStr
, IsArray
)
2457 if 'PLATFORMID_CFG_DATA.PlatformId' == Name
:
2458 raise Exception("'PlatformId' has the \
2459 same value as DSC default !")
2462 for SubItem
in Item
['subreg']:
2463 if SubItem
['cname'] in AbsfBuiltValDict
:
2464 ValStr
= AbsfBuiltValDict
[SubItem
['cname']]
2465 if Array2Val(ValStr
) == int(SubItem
['value'], 16):
2467 Name
= '%s.%s.%s' % (TagName
, Item
['cname'],
2469 self
.WriteDeltaLine(OutLines
, Name
, ValStr
, False)
2471 if Item
['embed'].endswith(':END'):
2474 if PlatformId
is None and Lines
:
2475 raise Exception("'PlatformId' configuration \
2476 is missing in ABSF file!")
2480 self
.WriteDeltaFile(OutFile
, PlatformId
, Lines
)
2484 def GenerateDscFile(self
, OutFile
):
2485 DscFd
= open(OutFile
, "w")
2486 for Line
in self
._DscLines
:
2487 DscFd
.write(Line
+ '\n')
2494 "GenCfgData Version 0.01",
2496 " GenCfgData GENINC BinFile \
2497 IncOutFile [-D Macros]",
2498 " GenCfgData GENPKL DscFile \
2499 PklOutFile [-D Macros]",
2500 " GenCfgData GENINC DscFile[;DltFile] \
2501 IncOutFile [-D Macros]",
2502 " GenCfgData GENBIN DscFile[;DltFile] \
2503 BinOutFile [-D Macros]",
2504 " GenCfgData GENBSF DscFile[;DltFile] \
2505 BsfOutFile [-D Macros]",
2506 " GenCfgData GENDLT DscFile[;AbsfFile] \
2507 DltOutFile [-D Macros]",
2508 " GenCfgData GENDSC DscFile \
2509 DscOutFile [-D Macros]",
2510 " GenCfgData GENHDR DscFile[;DltFile] \
2511 HdrOutFile[;ComHdrOutFile] [-D Macros]"
2517 # Parse the options and args
2519 argc
= len(sys
.argv
)
2524 GenCfgData
= CGenCfgData()
2525 Command
= sys
.argv
[1].upper()
2526 OutFile
= sys
.argv
[3]
2528 if argc
> 5 and GenCfgData
.ParseMacros(sys
.argv
[4:]) != 0:
2529 raise Exception("ERROR: Macro parsing failed !")
2531 FileList
= sys
.argv
[2].split(';')
2532 if len(FileList
) == 2:
2533 DscFile
= FileList
[0]
2534 DltFile
= FileList
[1]
2535 elif len(FileList
) == 1:
2536 DscFile
= FileList
[0]
2539 raise Exception("ERROR: Invalid parameter '%s' !" % sys
.argv
[2])
2541 if Command
== "GENDLT" and DscFile
.endswith('.dlt'):
2542 # It needs to expand an existing DLT file
2544 Lines
= CGenCfgData
.ExpandIncludeFiles(DltFile
)
2545 OutTxt
= ''.join([x
[0] for x
in Lines
])
2546 OutFile
= open(OutFile
, "w")
2547 OutFile
.write(OutTxt
)
2551 if not os
.path
.exists(DscFile
):
2552 raise Exception("ERROR: Cannot open file '%s' !" % DscFile
)
2556 if not os
.path
.exists(DltFile
):
2557 raise Exception("ERROR: Cannot open file '%s' !" % DltFile
)
2558 if Command
== "GENDLT":
2559 CfgBinFile
= DltFile
2563 if (DscFile
.lower().endswith('.bin')) and (Command
== "GENINC"):
2569 if GenCfgData
.GenerateDataIncFile(OutFile
, BinFile
) != 0:
2570 raise Exception(GenCfgData
.Error
)
2573 if DscFile
.lower().endswith('.pkl'):
2574 with
open(DscFile
, "rb") as PklFile
:
2575 GenCfgData
.__dict
__ = marshal
.load(PklFile
)
2577 if GenCfgData
.ParseDscFile(DscFile
) != 0:
2578 raise Exception(GenCfgData
.Error
)
2580 # if GenCfgData.CheckCfgData() != 0:
2581 # raise Exception(GenCfgData.Error)
2583 if GenCfgData
.CreateVarDict() != 0:
2584 raise Exception(GenCfgData
.Error
)
2586 if Command
== 'GENPKL':
2587 with
open(OutFile
, "wb") as PklFile
:
2588 marshal
.dump(GenCfgData
.__dict
__, PklFile
)
2591 if DltFile
and Command
in ['GENHDR', 'GENBIN', 'GENINC', 'GENBSF']:
2592 if GenCfgData
.OverrideDefaultValue(DltFile
) != 0:
2593 raise Exception(GenCfgData
.Error
)
2595 if GenCfgData
.UpdateDefaultValue() != 0:
2596 raise Exception(GenCfgData
.Error
)
2598 # GenCfgData.PrintData ()
2600 if sys
.argv
[1] == "GENBIN":
2601 if GenCfgData
.GenerateBinary(OutFile
) != 0:
2602 raise Exception(GenCfgData
.Error
)
2604 elif sys
.argv
[1] == "GENHDR":
2605 OutFiles
= OutFile
.split(';')
2606 BrdOutFile
= OutFiles
[0].strip()
2607 if len(OutFiles
) > 1:
2608 ComOutFile
= OutFiles
[1].strip()
2611 if GenCfgData
.CreateHeaderFile(BrdOutFile
, ComOutFile
) != 0:
2612 raise Exception(GenCfgData
.Error
)
2614 elif sys
.argv
[1] == "GENBSF":
2615 if GenCfgData
.GenerateBsfFile(OutFile
) != 0:
2616 raise Exception(GenCfgData
.Error
)
2618 elif sys
.argv
[1] == "GENINC":
2619 if GenCfgData
.GenerateDataIncFile(OutFile
) != 0:
2620 raise Exception(GenCfgData
.Error
)
2622 elif sys
.argv
[1] == "GENDLT":
2623 if GenCfgData
.GenerateDeltaFile(OutFile
, CfgBinFile
) != 0:
2624 raise Exception(GenCfgData
.Error
)
2626 elif sys
.argv
[1] == "GENDSC":
2627 if GenCfgData
.GenerateDscFile(OutFile
) != 0:
2628 raise Exception(GenCfgData
.Error
)
2631 raise Exception("Unsuported command '%s' !" % Command
)
2636 if __name__
== '__main__':