]>
git.proxmox.com Git - mirror_edk2.git/blob - IntelFsp2Pkg/Tools/GenCfgOpt.py
3 # Copyright (c) 2014 - 2021, Intel Corporation. All rights reserved.<BR>
4 # SPDX-License-Identifier: BSD-2-Clause-Patent
12 from datetime
import date
13 from functools
import reduce
15 # Generated file copyright header
17 __copyright_txt__
= """## @file
19 # THIS IS AUTO-GENERATED FILE BY BUILD TOOLS AND PLEASE DO NOT MAKE MODIFICATION.
21 # This file lists all VPD informations for a platform collected by build.exe.
23 # Copyright (c) %4d, Intel Corporation. All rights reserved.<BR>
24 # This program and the accompanying materials
25 # are licensed and made available under the terms and conditions of the BSD License
26 # which accompanies this distribution. The full text of the license may be found at
27 # http://opensource.org/licenses/bsd-license.php
29 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
30 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
34 __copyright_bsf__
= """/** @file
36 Boot Setting File for Platform Configuration.
38 Copyright (c) %4d, Intel Corporation. All rights reserved.<BR>
39 This program and the accompanying materials
40 are licensed and made available under the terms and conditions of the BSD License
41 which accompanies this distribution. The full text of the license may be found at
42 http://opensource.org/licenses/bsd-license.php
44 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
45 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
47 This file is automatically generated. Please do NOT modify !!!
53 __copyright_h__
= """/** @file
55 Copyright (c) %4d, Intel Corporation. All rights reserved.<BR>
57 Redistribution and use in source and binary forms, with or without modification,
58 are permitted provided that the following conditions are met:
60 * Redistributions of source code must retain the above copyright notice, this
61 list of conditions and the following disclaimer.
62 * Redistributions in binary form must reproduce the above copyright notice, this
63 list of conditions and the following disclaimer in the documentation and/or
64 other materials provided with the distribution.
65 * Neither the name of Intel Corporation nor the names of its contributors may
66 be used to endorse or promote products derived from this software without
67 specific prior written permission.
69 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
70 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
71 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
72 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
73 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
74 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
75 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
76 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
77 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
78 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
79 THE POSSIBILITY OF SUCH DAMAGE.
81 This file is automatically generated. Please do NOT modify !!!
88 class CLogicalExpression
:
93 def errExit(self
, err
= ''):
94 print ("ERROR: Express parsing for:")
95 print (" %s" % self
.string
)
96 print (" %s^" % (' ' * self
.index
))
98 print ("INFO : %s" % err
)
101 def getNonNumber (self
, n1
, n2
):
108 def getCurr(self
, lens
= 1):
111 return self
.string
[self
.index
:]
113 if self
.index
+ lens
> len(self
.string
):
114 lens
= len(self
.string
) - self
.index
115 return self
.string
[self
.index
: self
.index
+ lens
]
120 return self
.index
== len(self
.string
)
122 def moveNext(self
, len = 1):
126 while not self
.isLast():
127 if self
.getCurr() in ' \t':
132 def normNumber (self
, val
):
133 return True if val
else False
135 def getNumber(self
, var
):
137 if re
.match('^0x[a-fA-F0-9]+$', var
):
139 elif re
.match('^[+-]?\d+$', var
):
145 def parseValue(self
):
148 while not self
.isLast():
149 char
= self
.getCurr()
150 if re
.match('^[\w.]', char
):
155 val
= self
.getNumber(var
)
162 def parseSingleOp(self
):
164 if re
.match('^NOT\W', self
.getCurr(-1)):
166 op
= self
.parseBrace()
167 val
= self
.getNumber (op
)
169 self
.errExit ("'%s' is not a number" % op
)
170 return "%d" % (not self
.normNumber(int(op
)))
172 return self
.parseValue()
174 def parseBrace(self
):
176 char
= self
.getCurr()
179 value
= self
.parseExpr()
181 if self
.getCurr() != ')':
182 self
.errExit ("Expecting closing brace or operator")
186 value
= self
.parseSingleOp()
189 def parseCompare(self
):
190 value
= self
.parseBrace()
193 char
= self
.getCurr()
194 if char
in ['<', '>']:
196 next
= self
.getCurr()
202 result
= self
.parseBrace()
203 test
= self
.getNonNumber(result
, value
)
205 value
= "%d" % self
.normNumber(eval (value
+ op
+ result
))
207 self
.errExit ("'%s' is not a valid number for comparision" % test
)
208 elif char
in ['=', '!']:
210 if op
in ['==', '!=']:
212 result
= self
.parseBrace()
213 test
= self
.getNonNumber(result
, value
)
215 value
= "%d" % self
.normNumber((eval (value
+ op
+ result
)))
217 value
= "%d" % self
.normNumber(eval ("'" + value
+ "'" + op
+ "'" + result
+ "'"))
225 value
= self
.parseCompare()
228 if re
.match('^AND\W', self
.getCurr(-1)):
230 result
= self
.parseCompare()
231 test
= self
.getNonNumber(result
, value
)
233 value
= "%d" % self
.normNumber(int(value
) & int(result
))
235 self
.errExit ("'%s' is not a valid op number for AND" % test
)
240 def parseOrXor(self
):
241 value
= self
.parseAnd()
246 if re
.match('^XOR\W', self
.getCurr(-1)):
249 elif re
.match('^OR\W', self
.getCurr(-1)):
255 result
= self
.parseAnd()
256 test
= self
.getNonNumber(result
, value
)
258 value
= "%d" % self
.normNumber(eval (value
+ op
+ result
))
260 self
.errExit ("'%s' is not a valid op number for XOR/OR" % test
)
264 return self
.parseOrXor()
267 value
= self
.parseExpr()
269 if not self
.isLast():
270 self
.errExit ("Unexpected character found '%s'" % self
.getCurr())
271 test
= self
.getNumber(value
)
273 self
.errExit ("Result '%s' is not a number" % value
)
276 def evaluateExpress (self
, Expr
):
286 def __init__(self
, Mode
= ''):
290 self
._GlobalDataDef
= """
296 self
._BuidinOptionTxt
= """
298 Selection 0x1 , "Enabled"
299 Selection 0x0 , "Disabled"
303 self
._BsfKeyList
= ['FIND','NAME','HELP','TYPE','PAGE', 'PAGES', 'BLOCK', 'OPTION','CONDITION','ORDER', 'MARKER', 'SUBT']
304 self
._HdrKeyList
= ['HEADER','STRUCT', 'EMBED', 'COMMENT']
305 self
._BuidinOption
= {'$EN_DIS' : 'EN_DIS'}
310 self
._CfgBlkDict
= {}
311 self
._CfgPageDict
= {}
312 self
._BsfTempDict
= {}
313 self
._CfgItemList
= []
320 def ParseMacros (self
, MacroDefStr
):
321 # ['-DABC=1', '-D', 'CFG_DEBUG=1', '-D', 'CFG_OUTDIR=Build']
324 for Macro
in MacroDefStr
:
325 if Macro
.startswith('-D'):
333 Match
= re
.match("(\w+)=(.+)", Macro
)
335 self
._MacroDict
[Match
.group(1)] = Match
.group(2)
337 Match
= re
.match("(\w+)", Macro
)
339 self
._MacroDict
[Match
.group(1)] = ''
340 if len(self
._MacroDict
) == 0:
345 print ("INFO : Macro dictionary:")
346 for Each
in self
._MacroDict
:
347 print (" $(%s) = [ %s ]" % (Each
, self
._MacroDict
[Each
]))
350 def EvaulateIfdef (self
, Macro
):
351 Result
= Macro
in self
._MacroDict
353 print ("INFO : Eval Ifdef [%s] : %s" % (Macro
, Result
))
356 def ExpandMacros (self
, Input
, Preserve
= False):
358 Match
= re
.findall("\$\(\w+\)", Input
)
361 Variable
= Each
[2:-1]
362 if Variable
in self
._MacroDict
:
363 Line
= Line
.replace(Each
, self
._MacroDict
[Variable
])
366 print ("WARN : %s is not defined" % Each
)
368 Line
= Line
.replace(Each
, Each
[2:-1])
371 def ExpandPcds (self
, Input
):
373 Match
= re
.findall("(\w+\.\w+)", Input
)
375 for PcdName
in Match
:
376 if PcdName
in self
._PcdsDict
:
377 Line
= Line
.replace(PcdName
, self
._PcdsDict
[PcdName
])
380 print ("WARN : %s is not defined" % PcdName
)
383 def EvaluateExpress (self
, Expr
):
384 ExpExpr
= self
.ExpandPcds(Expr
)
385 ExpExpr
= self
.ExpandMacros(ExpExpr
)
386 LogExpr
= CLogicalExpression()
387 Result
= LogExpr
.evaluateExpress (ExpExpr
)
389 print ("INFO : Eval Express [%s] : %s" % (Expr
, Result
))
392 def ValueToByteArray (self
, ValueStr
, Length
):
393 Match
= re
.match("\{\s*FILE:(.+)\}", ValueStr
)
395 FileList
= Match
.group(1).split(',')
397 for File
in FileList
:
399 BinPath
= os
.path
.join(os
.path
.dirname(self
._DscFile
), File
)
400 Result
.extend(bytearray(open(BinPath
, 'rb').read()))
403 Result
= bytearray(self
.ValueToList(ValueStr
, Length
))
404 except ValueError as e
:
405 raise Exception ("Bytes in '%s' must be in range 0~255 !" % ValueStr
)
406 if len(Result
) < Length
:
407 Result
.extend(b
'\x00' * (Length
- len(Result
)))
408 elif len(Result
) > Length
:
409 raise Exception ("Value '%s' is too big to fit into %d bytes !" % (ValueStr
, Length
))
411 return Result
[:Length
]
413 def ValueToList (self
, ValueStr
, Length
):
414 if ValueStr
[0] == '{':
416 BinList
= ValueStr
[1:-1].split(',')
418 LastInBitField
= False
421 for Element
in BinList
:
423 Each
= Element
.strip()
427 if Each
[0] in ['"', "'"]:
428 Result
.extend(list(bytearray(Each
[1:-1], 'utf-8')))
430 Match
= re
.match("(.+):(\d+)b", Each
)
432 raise Exception("Invald value list format '%s' !" % Each
)
434 CurrentBitLen
= int(Match
.group(2))
435 CurrentValue
= ((self
.EvaluateExpress(Match
.group(1)) & (1<<CurrentBitLen
) - 1)) << BitLen
437 Result
.append(self
.EvaluateExpress(Each
.strip()))
439 Value
+= CurrentValue
440 BitLen
+= CurrentBitLen
441 if LastInBitField
and ((not InBitField
) or (Element
== BinList
[-1])):
443 raise Exception("Invald bit field length!")
444 Result
.extend(Val2Bytes(Value
, BitLen
// 8))
447 LastInBitField
= InBitField
448 elif ValueStr
.startswith("'") and ValueStr
.endswith("'"):
449 Result
= Str2Bytes (ValueStr
, Length
)
450 elif ValueStr
.startswith('"') and ValueStr
.endswith('"'):
451 Result
= Str2Bytes (ValueStr
, Length
)
453 Result
= Val2Bytes (self
.EvaluateExpress(ValueStr
), Length
)
456 def FormatListValue(self
, ConfigDict
):
457 Struct
= ConfigDict
['struct']
458 if Struct
not in ['UINT8','UINT16','UINT32','UINT64']:
462 binlist
= ConfigDict
['value'][1:-1].split(',')
465 if each
.startswith('0x'):
466 value
= int(each
, 16)
469 dataarray
.append(value
)
471 unit
= int(Struct
[4:]) / 8
472 if int(ConfigDict
['length']) != unit
* len(dataarray
):
473 raise Exception("Array size is not proper for '%s' !" % ConfigDict
['cname'])
476 for each
in dataarray
:
478 for loop
in range(int(unit
)):
479 bytearray
.append("0x%02X" % (value
& 0xFF))
481 newvalue
= '{' + ','.join(bytearray
) + '}'
482 ConfigDict
['value'] = newvalue
485 def ParseDscFile (self
, DscFile
, FvDir
):
488 self
._CfgItemList
= []
489 self
._CfgPageDict
= {}
490 self
._CfgBlkDict
= {}
491 self
._DscFile
= DscFile
495 self
._BsfTempDict
= {}
497 # Initial DSC time is parent DSC time.
498 self
._DscTime
= os
.path
.getmtime(DscFile
)
516 if type(DscFile
) is list:
517 # it is DSC lines already
521 DscFd
= open(DscFile
, "r")
522 DscLines
= DscFd
.readlines()
524 self
._DscFile
= DscFile
528 MaxAlign
= 32 #Default align to 32, but if there are 64 bit unit, align to 64
529 SizeAlign
= 0 #record the struct max align
530 Base
= 0 #Starting offset of sub-structure.
533 DscLine
= DscLines
.pop(0).strip()
535 self
._DscLines
.append (DscLine
)
537 SkipLines
= SkipLines
- 1
538 if len(DscLine
) == 0:
542 Match
= re
.match("^\[(.+)\]", DscLine
)
543 if Match
is not None:
549 SectionName
= Match
.group(1).lower()
550 if SectionName
== "Defines".lower():
552 if (SectionName
== "PcdsFeatureFlag".lower() or SectionName
== "PcdsFixedAtBuild".lower()):
554 elif SectionName
== "PcdsDynamicVpd.Tmp".lower():
556 elif SectionName
== "PcdsDynamicVpd.Upd".lower():
558 ConfigDict
['header'] = 'ON'
559 ConfigDict
['region'] = 'UPD'
560 ConfigDict
['order'] = -1
561 ConfigDict
['page'] = ''
562 ConfigDict
['name'] = ''
563 ConfigDict
['find'] = ''
564 ConfigDict
['marker'] = ''
565 ConfigDict
['struct'] = ''
566 ConfigDict
['embed'] = ''
567 ConfigDict
['comment'] = ''
568 ConfigDict
['subreg'] = []
569 ConfigDict
['condition'] = ''
570 ConfigDict
['option'] = ''
574 if IsDefSect
or IsPcdSect
or IsUpdSect
or IsVpdSect
or IsTmpSect
:
576 Match
= False if DscLine
[0] != '!' else True
578 Match
= re
.match("^!(else|endif|ifdef|ifndef|if|elseif|include)\s*(.+)?$", DscLine
.split("#")[0])
579 Keyword
= Match
.group(1) if Match
else ''
580 Remaining
= Match
.group(2) if Match
else ''
581 Remaining
= '' if Remaining
is None else Remaining
.strip()
583 if Keyword
in ['if', 'elseif', 'ifdef', 'ifndef', 'include'] and not Remaining
:
584 raise Exception ("ERROR: Expression is expected after '!if' or !elseif' for line '%s'" % DscLine
)
586 if Keyword
== 'else':
588 IfStack
[-1] = not IfStack
[-1]
590 raise Exception ("ERROR: No paired '!if' found for '!else' for line '%s'" % DscLine
)
591 elif Keyword
== 'endif':
594 Level
= ElifStack
.pop()
598 raise Exception ("ERROR: No paired '!if' found for '!endif' for line '%s'" % DscLine
)
599 elif Keyword
== 'ifdef' or Keyword
== 'ifndef':
600 Result
= self
.EvaulateIfdef (Remaining
)
601 if Keyword
== 'ifndef':
603 IfStack
.append(Result
)
605 elif Keyword
== 'if' or Keyword
== 'elseif':
606 Result
= self
.EvaluateExpress(Remaining
)
609 IfStack
.append(Result
)
612 IfStack
[-1] = not IfStack
[-1]
613 IfStack
.append(Result
)
614 ElifStack
[-1] = ElifStack
[-1] + 1
616 raise Exception ("ERROR: No paired '!if' found for '!elif' for line '%s'" % DscLine
)
619 Handle
= reduce(lambda x
,y
: x
and y
, IfStack
)
623 Match
= re
.match("!include\s+(.+)", DscLine
)
625 IncludeFilePath
= Match
.group(1)
626 IncludeFilePath
= self
.ExpandMacros(IncludeFilePath
)
627 PackagesPath
= os
.getenv("PACKAGES_PATH")
629 for PackagePath
in PackagesPath
.split(os
.pathsep
):
630 IncludeFilePathAbs
= os
.path
.join(os
.path
.normpath(PackagePath
), os
.path
.normpath(IncludeFilePath
))
631 if os
.path
.exists(IncludeFilePathAbs
):
632 IncludeDsc
= open(IncludeFilePathAbs
, "r")
635 IncludeDsc
= open(IncludeFilePath
, "r")
636 if IncludeDsc
== None:
637 print("ERROR: Cannot open file '%s'" % IncludeFilePath
)
640 # Update DscTime when newer DSC time found.
641 CurrentDscTime
= os
.path
.getmtime(os
.path
.realpath(IncludeDsc
.name
))
642 if CurrentDscTime
> self
._DscTime
:
643 self
._DscTime
= CurrentDscTime
645 NewDscLines
= IncludeDsc
.readlines()
647 DscLines
= NewDscLines
+ DscLines
648 del self
._DscLines
[-1]
651 if DscLine
.startswith('!'):
652 print("ERROR: Unrecognized directive for line '%s'" % DscLine
)
655 del self
._DscLines
[-1]
659 #DEFINE UPD_TOOL_GUID = 8C3D856A-9BE6-468E-850A-24F7A8D38E09
660 #DEFINE FSP_T_UPD_TOOL_GUID = 34686CA3-34F9-4901-B82A-BA630F0714C6
661 #DEFINE FSP_M_UPD_TOOL_GUID = 39A250DB-E465-4DD1-A2AC-E2BD3C0E2385
662 #DEFINE FSP_S_UPD_TOOL_GUID = CAE3605B-5B34-4C85-B3D7-27D54273C40F
663 Match
= re
.match("^\s*(?:DEFINE\s+)*(\w+)\s*=\s*(.+)", DscLine
)
665 self
._MacroDict
[Match
.group(1)] = self
.ExpandMacros(Match
.group(2))
667 print ("INFO : DEFINE %s = [ %s ]" % (Match
.group(1), self
.ExpandMacros(Match
.group(2))))
669 #gSiPkgTokenSpaceGuid.PcdTxtEnable|FALSE
670 #gSiPkgTokenSpaceGuid.PcdOverclockEnable|TRUE
671 Match
= re
.match("^\s*([\w\.]+)\s*\|\s*(\w+)", DscLine
)
673 self
._PcdsDict
[Match
.group(1)] = Match
.group(2)
675 print ("INFO : PCD %s = [ %s ]" % (Match
.group(1), Match
.group(2)))
677 while i
< len(BuildOptionPcd
):
678 Match
= re
.match("\s*([\w\.]+)\s*\=\s*(\w+)", BuildOptionPcd
[i
])
680 self
._PcdsDict
[Match
.group(1)] = Match
.group(2)
684 # !BSF DEFT:{GPIO_TMPL:START}
685 Match
= re
.match("^\s*#\s+(!BSF)\s+DEFT:{(.+?):(START|END)}", DscLine
)
687 if Match
.group(3) == 'START' and not TemplateName
:
688 TemplateName
= Match
.group(2).strip()
689 self
._BsfTempDict
[TemplateName
] = []
690 if Match
.group(3) == 'END' and (TemplateName
== Match
.group(2).strip()) and TemplateName
:
694 Match
= re
.match("^!include\s*(.+)?$", DscLine
)
697 self
._BsfTempDict
[TemplateName
].append(DscLine
)
700 Match
= re
.match("^\s*#\s+(!BSF|@Bsf|!HDR)\s+(.+)", DscLine
)
702 Remaining
= Match
.group(2)
703 if Match
.group(1) == '!BSF' or Match
.group(1) == '@Bsf':
704 Match
= re
.match("(?:^|.+\s+)PAGES:{(.+?)}", Remaining
)
706 # !BSF PAGES:{HSW:"Haswell System Agent", LPT:"Lynx Point PCH"}
707 PageList
= Match
.group(1).split(',')
708 for Page
in PageList
:
710 Match
= re
.match("(\w+):\"(.+)\"", Page
)
711 self
._CfgPageDict
[Match
.group(1)] = Match
.group(2)
713 Match
= re
.match("(?:^|.+\s+)BLOCK:{NAME:\"(.+)\"\s*,\s*VER:\"(.+)\"\s*}", Remaining
)
715 self
._CfgBlkDict
['name'] = Match
.group(1)
716 self
._CfgBlkDict
['ver'] = Match
.group(2)
718 for Key
in self
._BsfKeyList
:
719 Match
= re
.match("(?:^|.+\s+)%s:{(.+?)}" % Key
, Remaining
)
721 if Key
in ['NAME', 'HELP', 'OPTION'] and Match
.group(1).startswith('+'):
722 ConfigDict
[Key
.lower()] += Match
.group(1)[1:]
724 ConfigDict
[Key
.lower()] = Match
.group(1)
726 for Key
in self
._HdrKeyList
:
727 Match
= re
.match("(?:^|.+\s+)%s:{(.+?)}" % Key
, Remaining
)
729 ConfigDict
[Key
.lower()] = Match
.group(1)
731 Match
= re
.match("^\s*#\s+@Prompt\s+(.+)", DscLine
)
733 ConfigDict
['name'] = Match
.group(1)
735 Match
= re
.match("^\s*#\s*@ValidList\s*(.+)\s*\|\s*(.+)\s*\|\s*(.+)\s*", DscLine
)
737 if Match
.group(2).strip() in self
._BuidinOption
:
738 ConfigDict
['option'] = Match
.group(2).strip()
740 OptionValueList
= Match
.group(2).split(',')
741 OptionStringList
= Match
.group(3).split(',')
743 for Option
in OptionValueList
:
744 Option
= Option
.strip()
745 ConfigDict
['option'] = ConfigDict
['option'] + str(Option
) + ':' + OptionStringList
[Index
].strip()
747 if Index
in range(len(OptionValueList
)):
748 ConfigDict
['option'] += ', '
749 ConfigDict
['type'] = "Combo"
751 Match
= re
.match("^\s*#\s*@ValidRange\s*(.+)\s*\|\s*(.+)\s*-\s*(.+)\s*", DscLine
)
753 if "0x" in Match
.group(2) or "0x" in Match
.group(3):
754 ConfigDict
['type'] = "EditNum, HEX, (%s,%s)" % (Match
.group(2), Match
.group(3))
756 ConfigDict
['type'] = "EditNum, DEC, (%s,%s)" % (Match
.group(2), Match
.group(3))
758 Match
= re
.match("^\s*##\s+(.+)", DscLine
)
760 ConfigDict
['help'] = Match
.group(1)
764 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
)
766 Match
= re
.match("^([_a-zA-Z0-9]+).([_a-zA-Z0-9]+)\s*\|\s*(0x[0-9A-F]+)(?:\s*\|\s*(.+))?", DscLine
)
768 ConfigDict
['space'] = Match
.group(1)
769 ConfigDict
['cname'] = Match
.group(2)
770 if Match
.group(3) != '*':
772 Offset
= int (Match
.group(3), 16)
776 if Hardcode
and AutoAlign
:
777 print("Hardcode and auto-align mixed mode is not supported by GenCfgOpt")
779 ConfigDict
['offset'] = Offset
780 if ConfigDict
['order'] == -1:
781 ConfigDict
['order'] = ConfigDict
['offset'] << 8
783 (Major
, Minor
) = ConfigDict
['order'].split('.')
784 ConfigDict
['order'] = (int (Major
, 16) << 8 ) + int (Minor
, 16)
786 Value
= Match
.group(5).strip()
787 if Match
.group(4).startswith("0x"):
788 Length
= int (Match
.group(4), 16)
790 Length
= int (Match
.group(4))
793 Value
= Match
.group(4)
796 Value
= Value
.strip()
798 Match
= re
.match("^.+\s*\|\s*(.+)", Value
)
800 Value
= Match
.group(1)
803 ConfigDict
['length'] = Length
804 Match
= re
.match("\$\((\w+)\)", Value
)
806 if Match
.group(1) in self
._MacroDict
:
807 Value
= self
._MacroDict
[Match
.group(1)]
809 ConfigDict
['value'] = Value
810 if (len(Value
) > 0) and (Value
[0] == '{'):
811 Value
= self
.FormatListValue(ConfigDict
)
813 if ConfigDict
['name'] == '':
814 # Clear BSF specific items
815 ConfigDict
['bsfname'] = ''
816 ConfigDict
['help'] = ''
817 ConfigDict
['type'] = ''
818 ConfigDict
['option'] = ''
819 if IsUpdSect
and AutoAlign
:
820 ItemLength
= int(ConfigDict
['length'])
821 ItemOffset
= int(ConfigDict
['offset'])
822 ItemStruct
= ConfigDict
['struct']
824 if ItemLength
in [1, 2, 4, 8] and not ConfigDict
['value'].startswith('{'):
826 # If there are 64 bit unit, align to 64
831 UnitDict
= {'UINT8':1, 'UINT16':2, 'UINT32':4, 'UINT64':8}
832 if ItemStruct
in ['UINT8', 'UINT16', 'UINT32', 'UINT64']:
833 Unit
= UnitDict
[ItemStruct
]
834 # If there are 64 bit unit, align to 64
837 SizeAlign
= max(SizeAlign
, Unit
)
838 if (ConfigDict
['embed'].find(':START') != -1):
840 SubOffset
= ItemOffset
- Base
841 SubRemainder
= SubOffset
% Unit
843 Diff
= Unit
- SubRemainder
844 Offset
= Offset
+ Diff
845 ItemOffset
= ItemOffset
+ Diff
847 if (ConfigDict
['embed'].find(':END') != -1):
848 Remainder
= Offset
% (MaxAlign
/8) # MaxAlign is either 32 or 64
850 Diff
= int((MaxAlign
/8) - Remainder
)
851 Offset
= Offset
+ Diff
852 ItemOffset
= ItemOffset
+ Diff
853 MaxAlign
= 32 # Reset to default 32 align when struct end
854 if (ConfigDict
['cname'] == 'UpdTerminator'):
855 # ItemLength is the size of UpdTerminator
856 # Itemlength might be 16, 32, or 64
857 # Struct align to 64 if UpdTerminator
858 # or struct size is 64 bit, else align to 32
859 Remainder
= Offset
% max(ItemLength
/8, 4, SizeAlign
)
860 Offset
= Offset
+ ItemLength
862 Diff
= int(max(ItemLength
/8, 4, SizeAlign
) - Remainder
)
863 ItemOffset
= ItemOffset
+ Diff
864 ConfigDict
['offset'] = ItemOffset
866 self
._CfgItemList
.append(ConfigDict
.copy())
867 ConfigDict
['name'] = ''
868 ConfigDict
['find'] = ''
869 ConfigDict
['struct'] = ''
870 ConfigDict
['embed'] = ''
871 ConfigDict
['comment'] = ''
872 ConfigDict
['marker'] = ''
873 ConfigDict
['order'] = -1
874 ConfigDict
['subreg'] = []
875 ConfigDict
['option'] = ''
877 # It could be a virtual item as below
878 # !BSF FIELD:{SerialDebugPortAddress0:1}
880 # @Bsf FIELD:{SerialDebugPortAddress0:1b}
881 Match
= re
.match("^\s*#\s+(!BSF|@Bsf)\s+FIELD:{(.+):(\d+)([Bb])?}", DscLine
)
883 SubCfgDict
= ConfigDict
.copy()
884 if (Match
.group(4) == None) or (Match
.group(4) == 'B'):
886 elif Match
.group(4) == 'b':
889 print("ERROR: Invalide BSF FIELD length for line '%s'" % DscLine
)
891 SubCfgDict
['cname'] = Match
.group(2)
892 SubCfgDict
['bitlength'] = int (Match
.group(3)) * UnitBitLen
893 if SubCfgDict
['bitlength'] > 0:
894 LastItem
= self
._CfgItemList
[-1]
895 if len(LastItem
['subreg']) == 0:
898 SubOffset
= LastItem
['subreg'][-1]['bitoffset'] + LastItem
['subreg'][-1]['bitlength']
899 SubCfgDict
['bitoffset'] = SubOffset
900 LastItem
['subreg'].append (SubCfgDict
.copy())
901 ConfigDict
['name'] = ''
904 def GetBsfBitFields (self
, subitem
, bytes
):
905 start
= subitem
['bitoffset']
906 end
= start
+ subitem
['bitlength']
907 bitsvalue
= ''.join('{0:08b}'.format(i
) for i
in bytes
[::-1])
908 bitsvalue
= bitsvalue
[::-1]
909 bitslen
= len(bitsvalue
)
910 if start
> bitslen
or end
> bitslen
:
911 raise Exception ("Invalid bits offset [%d,%d] %d for %s" % (start
, end
, bitslen
, subitem
['name']))
912 return '0x%X' % (int(bitsvalue
[start
:end
][::-1], 2))
914 def UpdateSubRegionDefaultValue (self
):
916 for Item
in self
._CfgItemList
:
917 if len(Item
['subreg']) == 0:
920 if Item
['value'][0] == '{':
921 binlist
= Item
['value'][1:-1].split(',')
924 if each
.startswith('0x'):
925 value
= int(each
, 16)
928 bytearray
.append(value
)
930 if Item
['value'].startswith('0x'):
931 value
= int(Item
['value'], 16)
933 value
= int(Item
['value'])
935 while idx
< Item
['length']:
936 bytearray
.append(value
& 0xFF)
939 for SubItem
in Item
['subreg']:
940 valuestr
= self
.GetBsfBitFields(SubItem
, bytearray
)
941 SubItem
['value'] = valuestr
944 def NoDscFileChange (self
, OutPutFile
):
946 if not os
.path
.exists(OutPutFile
):
949 OutputTime
= os
.path
.getmtime(OutPutFile
)
950 if self
._DscTime
> OutputTime
:
954 def CreateSplitUpdTxt (self
, UpdTxtFile
):
955 GuidList
= ['FSP_T_UPD_TOOL_GUID','FSP_M_UPD_TOOL_GUID','FSP_S_UPD_TOOL_GUID']
956 SignatureList
= ['0x545F', '0x4D5F','0x535F'] # _T, _M, and _S signature for FSPT, FSPM, FSPS
957 for Index
in range(len(GuidList
)):
960 if GuidList
[Index
] not in self
._MacroDict
:
961 self
.Error
= "%s definition is missing in DSC file" % (GuidList
[Index
])
965 UpdTxtFile
= os
.path
.join(FvDir
, self
._MacroDict
[GuidList
[Index
]] + '.txt')
967 if (self
.NoDscFileChange (UpdTxtFile
)):
968 # DSC has not been modified yet
969 # So don't have to re-generate other files
970 self
.Error
= 'No DSC file change, skip to create UPD TXT file'
973 TxtFd
= open(UpdTxtFile
, "w")
974 TxtFd
.write("%s\n" % (__copyright_txt__
% date
.today().year
))
982 for Item
in self
._CfgItemList
:
983 if Item
['cname'] == 'Signature' and str(Item
['value'])[0:6] == SignatureList
[Index
]:
984 StartAddr
= Item
['offset']
985 NextOffset
= StartAddr
987 if Item
['cname'] == 'UpdTerminator' and InRange
== True:
988 EndAddr
= Item
['offset']
991 for Item
in self
._CfgItemList
:
992 if Item
['cname'] == 'Signature' and str(Item
['value'])[0:6] == SignatureList
[Index
]:
996 if Item
['cname'] == 'UpdTerminator':
998 if Item
['region'] != 'UPD':
1000 Offset
= Item
['offset']
1001 if StartAddr
> Offset
or EndAddr
< Offset
:
1003 if NextOffset
< Offset
:
1005 TxtFd
.write("%s.UnusedUpdSpace%d|%s0x%04X|0x%04X|{0}\n" % (Item
['space'], SpaceIdx
, Default
, NextOffset
- StartAddr
, Offset
- NextOffset
))
1006 SpaceIdx
= SpaceIdx
+ 1
1007 NextOffset
= Offset
+ Item
['length']
1008 TxtFd
.write("%s.%s|%s0x%04X|%s|%s\n" % (Item
['space'],Item
['cname'],Default
,Item
['offset'] - StartAddr
,Item
['length'],Item
['value']))
1012 def CreateVarDict (self
):
1015 if len(self
._CfgItemList
) > 0:
1016 Item
= self
._CfgItemList
[-1]
1017 self
._VarDict
['_LENGTH_'] = '%d' % (Item
['offset'] + Item
['length'])
1018 for Item
in self
._CfgItemList
:
1019 Embed
= Item
['embed']
1020 Match
= re
.match("^(\w+):(\w+):(START|END)", Embed
)
1022 StructName
= Match
.group(1)
1023 VarName
= '_%s_%s_' % (Match
.group(3), StructName
)
1024 if Match
.group(3) == 'END':
1025 self
._VarDict
[VarName
] = Item
['offset'] + Item
['length']
1026 self
._VarDict
['_LENGTH_%s_' % StructName
] = \
1027 self
._VarDict
['_END_%s_' % StructName
] - self
._VarDict
['_START_%s_' % StructName
]
1028 if Match
.group(2).startswith('TAG_'):
1029 if (self
.Mode
!= 'FSP') and (self
._VarDict
['_LENGTH_%s_' % StructName
] % 4):
1030 raise Exception("Size of structure '%s' is %d, not DWORD aligned !" % (StructName
, self
._VarDict
['_LENGTH_%s_' % StructName
]))
1031 self
._VarDict
['_TAG_%s_' % StructName
] = int (Match
.group(2)[4:], 16) & 0xFFF
1033 self
._VarDict
[VarName
] = Item
['offset']
1035 self
._VarDict
['_OFFSET_%s_' % Item
['marker'].strip()] = Item
['offset']
1038 def UpdateBsfBitUnit (self
, Item
):
1043 UnitDec
= {1:'BYTE', 2:'WORD', 4:'DWORD', 8:'QWORD'}
1044 for Idx
, SubItem
in enumerate(Item
['subreg']):
1046 Unit
= SubItem
['bitunit']
1047 BitLength
= SubItem
['bitlength']
1048 BitTotal
+= BitLength
1049 BitOffset
+= BitLength
1051 if BitOffset
> 64 or BitOffset
> Unit
* 8:
1054 if BitOffset
== Unit
* 8:
1055 for SubIdx
in range (StartIdx
, Idx
+ 1):
1056 Item
['subreg'][SubIdx
]['bitunit'] = Unit
1062 raise Exception ("Bit fields cannot fit into %s for '%s.%s' !" % (UnitDec
[Unit
], Item
['cname'], SubItem
['cname']))
1064 ExpectedTotal
= Item
['length'] * 8
1065 if Item
['length'] * 8 != BitTotal
:
1066 raise Exception ("Bit fields total length (%d) does not match length (%d) of '%s' !" % (BitTotal
, ExpectedTotal
, Item
['cname']))
1068 def UpdateDefaultValue (self
):
1070 for Idx
, Item
in enumerate(self
._CfgItemList
):
1071 if len(Item
['subreg']) == 0:
1072 Value
= Item
['value']
1073 if (len(Value
) > 0) and (Value
[0] == '{' or Value
[0] == "'" or Value
[0] == '"'):
1074 # {XXX} or 'XXX' strings
1075 self
.FormatListValue(self
._CfgItemList
[Idx
])
1077 Match
= re
.match("(0x[0-9a-fA-F]+|[0-9]+)", Value
)
1079 NumValue
= self
.EvaluateExpress (Value
)
1080 Item
['value'] = '0x%X' % NumValue
1082 ValArray
= self
.ValueToByteArray (Item
['value'], Item
['length'])
1083 for SubItem
in Item
['subreg']:
1084 SubItem
['value'] = self
.GetBsfBitFields(SubItem
, ValArray
)
1085 self
.UpdateBsfBitUnit (Item
)
1088 def ProcessMultilines (self
, String
, MaxCharLength
):
1090 StringLength
= len(String
)
1091 CurrentStringStart
= 0
1094 if len(String
) <= MaxCharLength
:
1095 while (StringOffset
< StringLength
):
1096 if StringOffset
>= 1:
1097 if String
[StringOffset
- 1] == '\\' and String
[StringOffset
] == 'n':
1098 BreakLineDict
.append (StringOffset
+ 1)
1100 if BreakLineDict
!= []:
1101 for Each
in BreakLineDict
:
1102 Multilines
+= " %s\n" % String
[CurrentStringStart
:Each
].lstrip()
1103 CurrentStringStart
= Each
1104 if StringLength
- CurrentStringStart
> 0:
1105 Multilines
+= " %s\n" % String
[CurrentStringStart
:].lstrip()
1107 Multilines
= " %s\n" % String
1111 FoundSpaceChar
= False
1112 while (StringOffset
< StringLength
):
1113 if StringOffset
>= 1:
1114 if NewLineCount
>= MaxCharLength
- 1:
1115 if String
[StringOffset
] == ' ' and StringLength
- StringOffset
> 10:
1116 BreakLineDict
.append (NewLineStart
+ NewLineCount
)
1117 NewLineStart
= NewLineStart
+ NewLineCount
1119 FoundSpaceChar
= True
1120 elif StringOffset
== StringLength
- 1 and FoundSpaceChar
== False:
1121 BreakLineDict
.append (0)
1122 if String
[StringOffset
- 1] == '\\' and String
[StringOffset
] == 'n':
1123 BreakLineDict
.append (StringOffset
+ 1)
1124 NewLineStart
= StringOffset
+ 1
1128 if BreakLineDict
!= []:
1129 BreakLineDict
.sort ()
1130 for Each
in BreakLineDict
:
1132 Multilines
+= " %s\n" % String
[CurrentStringStart
:Each
].lstrip()
1133 CurrentStringStart
= Each
1134 if StringLength
- CurrentStringStart
> 0:
1135 Multilines
+= " %s\n" % String
[CurrentStringStart
:].lstrip()
1138 def CreateField (self
, Item
, Name
, Length
, Offset
, Struct
, BsfName
, Help
, Option
, BitsLength
= None):
1145 if Length
== 0 and Name
== 'Dummy':
1149 if Length
in [1,2,4,8]:
1150 Type
= "UINT%d" % (Length
* 8)
1151 if Name
.startswith("UnusedUpdSpace") and Length
!= 1:
1158 if Item
and Item
['value'].startswith('{'):
1164 if Struct
in ['UINT8','UINT16','UINT32','UINT64']:
1166 Unit
= int(Type
[4:]) / 8
1167 Length
= Length
/ Unit
1172 Name
= Name
+ '[%d]' % Length
1174 if len(Type
) < PosName
:
1175 Space1
= PosName
- len(Type
)
1180 NameLine
=" - %s\n" % BsfName
1185 HelpLine
= self
.ProcessMultilines (Help
, 80)
1188 OptionLine
= self
.ProcessMultilines (Option
, 80)
1193 OffsetStr
= '0x%04X' % Offset
1195 if BitsLength
is None:
1198 BitsLength
= ' : %d' % BitsLength
1200 return "\n/** Offset %s%s%s%s**/\n %s%s%s%s;\n" % (OffsetStr
, NameLine
, HelpLine
, OptionLine
, Type
, ' ' * Space1
, Name
, BitsLength
)
1202 def PostProcessBody (self
, TextBody
):
1208 IsUpdHdrDefined
= False
1210 for Line
in TextBody
:
1211 SplitToLines
= Line
.splitlines()
1212 MatchComment
= re
.match("^/\*\sCOMMENT:(\w+):([\w|\W|\s]+)\s\*/\s([\s\S]*)", SplitToLines
[0])
1214 if MatchComment
.group(1) == 'FSP_UPD_HEADER':
1218 if IsUpdHdrDefined
!= True or IsUpdHeader
!= True:
1219 CommentLine
= " " + MatchComment
.group(2) + "\n"
1220 NewTextBody
.append("/**" + CommentLine
+ "**/\n")
1221 Line
= Line
[(len(SplitToLines
[0]) + 1):]
1223 Match
= re
.match("^/\*\sEMBED_STRUCT:(\w+):(\w+):(START|END)\s\*/\s([\s\S]*)", Line
)
1225 Line
= Match
.group(4)
1226 if Match
.group(1) == 'FSP_UPD_HEADER':
1231 if Match
and Match
.group(3) == 'START':
1232 if IsUpdHdrDefined
!= True or IsUpdHeader
!= True:
1233 NewTextBody
.append ('typedef struct {\n')
1234 StructName
= Match
.group(1)
1235 VariableName
= Match
.group(2)
1236 MatchOffset
= re
.search('/\*\*\sOffset\s0x([a-fA-F0-9]+)', Line
)
1238 Offset
= int(MatchOffset
.group(1), 16)
1243 OldTextBody
.append (self
.CreateField (None, VariableName
, 0, Offset
, StructName
, '', '', ''))
1245 if IsUpdHdrDefined
!= True or IsUpdHeader
!= True:
1246 NewTextBody
.append (Line
)
1248 OldTextBody
.append (Line
)
1250 if Match
and Match
.group(3) == 'END':
1251 if (StructName
!= Match
.group(1)) or (VariableName
!= Match
.group(2)):
1252 print ("Unmatched struct name '%s' and '%s' !" % (StructName
, Match
.group(1)))
1254 if IsUpdHdrDefined
!= True or IsUpdHeader
!= True:
1255 NewTextBody
.append ('} %s;\n\n' % StructName
)
1256 IsUpdHdrDefined
= True
1258 NewTextBody
.extend(OldTextBody
)
1261 def WriteLinesWithoutTailingSpace (self
, HeaderFd
, Line
):
1262 TxtBody2
= Line
.splitlines(True)
1263 for Line2
in TxtBody2
:
1264 Line2
= Line2
.rstrip()
1266 HeaderFd
.write (Line2
)
1268 def CreateHeaderFile (self
, InputHeaderFile
):
1271 HeaderFileName
= 'FspUpd.h'
1272 HeaderFile
= os
.path
.join(FvDir
, HeaderFileName
)
1274 # Check if header needs to be recreated
1275 if (self
.NoDscFileChange (HeaderFile
)):
1276 # DSC has not been modified yet
1277 # So don't have to re-generate other files
1278 self
.Error
= 'No DSC file change, skip to create UPD header file'
1282 for Item
in self
._CfgItemList
:
1283 if str(Item
['cname']) == 'Signature' and Item
['length'] == 8:
1284 Value
= int(Item
['value'], 16)
1287 Chars
.append(chr(Value
& 0xFF))
1289 SignatureStr
= ''.join(Chars
)
1290 # Signature will be _T / _M / _S for FSPT / FSPM / FSPS accordingly
1291 if '_T' in SignatureStr
[6:6+2]:
1292 TxtBody
.append("#define FSPT_UPD_SIGNATURE %s /* '%s' */\n\n" % (Item
['value'], SignatureStr
))
1293 elif '_M' in SignatureStr
[6:6+2]:
1294 TxtBody
.append("#define FSPM_UPD_SIGNATURE %s /* '%s' */\n\n" % (Item
['value'], SignatureStr
))
1295 elif '_S' in SignatureStr
[6:6+2]:
1296 TxtBody
.append("#define FSPS_UPD_SIGNATURE %s /* '%s' */\n\n" % (Item
['value'], SignatureStr
))
1297 TxtBody
.append("\n")
1299 for Region
in ['UPD']:
1301 UpdSignature
= ['0x545F', '0x4D5F', '0x535F'] #['_T', '_M', '_S'] signature for FSPT, FSPM, FSPS
1302 UpdStructure
= ['FSPT_UPD', 'FSPM_UPD', 'FSPS_UPD']
1303 for Item
in self
._CfgItemList
:
1304 if Item
["cname"] == 'Signature' and Item
["value"][0:6] in UpdSignature
:
1305 Item
["offset"] = 0 # re-initialize offset to 0 when new UPD structure starting
1306 UpdOffsetTable
.append (Item
["offset"])
1308 for UpdIdx
in range(len(UpdOffsetTable
)):
1310 for Item
in self
._CfgItemList
:
1311 if Item
["comment"] != '' and Item
["offset"] >= UpdOffsetTable
[UpdIdx
]:
1312 MatchComment
= re
.match("^(U|V)PD_DATA_REGION:([\w|\W|\s]+)", Item
["comment"])
1313 if MatchComment
and MatchComment
.group(1) == Region
[0]:
1314 CommentLine
= " " + MatchComment
.group(2) + "\n"
1315 TxtBody
.append("/**" + CommentLine
+ "**/\n")
1316 elif Item
["offset"] >= UpdOffsetTable
[UpdIdx
] and Item
["comment"] == '':
1317 Match
= re
.match("^FSP([\w|\W|\s])_UPD", UpdStructure
[UpdIdx
])
1319 TxtBody
.append("/** Fsp " + Match
.group(1) + " UPD Configuration\n**/\n")
1320 TxtBody
.append("typedef struct {\n")
1330 for Item
in self
._CfgItemList
:
1331 if Item
['cname'] == 'Signature' and str(Item
['value'])[0:6] == UpdSignature
[UpdIdx
] or Region
[0] == 'V':
1335 if Item
['cname'] == 'UpdTerminator':
1338 if Item
['region'] != Region
:
1341 if Item
["offset"] < UpdOffsetTable
[UpdIdx
]:
1344 NextVisible
= LastVisible
1346 if LastVisible
and (Item
['header'] == 'OFF'):
1348 ResvOffset
= Item
['offset']
1349 elif (not LastVisible
) and Item
['header'] == 'ON':
1351 Name
= "Reserved" + Region
[0] + "pdSpace%d" % ResvIdx
1352 ResvIdx
= ResvIdx
+ 1
1353 TxtBody
.append(self
.CreateField (Item
, Name
, Item
["offset"] - ResvOffset
, ResvOffset
, '', '', '', ''))
1355 if Offset
< Item
["offset"]:
1357 Name
= "Unused" + Region
[0] + "pdSpace%d" % SpaceIdx
1358 LineBuffer
.append(self
.CreateField (Item
, Name
, Item
["offset"] - Offset
, Offset
, '', '', '', ''))
1359 SpaceIdx
= SpaceIdx
+ 1
1360 Offset
= Item
["offset"]
1362 LastVisible
= NextVisible
1364 Offset
= Offset
+ Item
["length"]
1366 for Each
in LineBuffer
:
1367 TxtBody
.append (Each
)
1369 Comment
= Item
["comment"]
1370 Embed
= Item
["embed"].upper()
1371 if Embed
.endswith(':START') or Embed
.endswith(':END'):
1372 if not Comment
== '' and Embed
.endswith(':START'):
1373 Marker
= '/* COMMENT:%s */ \n' % Item
["comment"]
1374 Marker
= Marker
+ '/* EMBED_STRUCT:%s */ ' % Item
["embed"]
1376 Marker
= '/* EMBED_STRUCT:%s */ ' % Item
["embed"]
1381 self
.Error
= "Invalid embedded structure format '%s'!\n" % Item
["embed"]
1383 Line
= Marker
+ self
.CreateField (Item
, Item
["cname"], Item
["length"], Item
["offset"], Item
['struct'], Item
['name'], Item
['help'], Item
['option'])
1384 TxtBody
.append(Line
)
1385 if Item
['cname'] == 'UpdTerminator':
1387 TxtBody
.append("} " + UpdStructure
[UpdIdx
] + ";\n\n")
1389 # Handle the embedded data structure
1390 TxtBody
= self
.PostProcessBody (TxtBody
)
1392 HeaderTFileName
= 'FsptUpd.h'
1393 HeaderMFileName
= 'FspmUpd.h'
1394 HeaderSFileName
= 'FspsUpd.h'
1396 UpdRegionCheck
= ['FSPT', 'FSPM', 'FSPS'] # FSPX_UPD_REGION
1397 UpdConfigCheck
= ['FSP_T', 'FSP_M', 'FSP_S'] # FSP_X_CONFIG, FSP_X_TEST_CONFIG, FSP_X_RESTRICTED_CONFIG
1398 UpdSignatureCheck
= ['FSPT_UPD_SIGNATURE', 'FSPM_UPD_SIGNATURE', 'FSPS_UPD_SIGNATURE']
1399 ExcludedSpecificUpd
= ['FSPT_ARCH_UPD', 'FSPM_ARCH_UPD', 'FSPS_ARCH_UPD']
1402 if InputHeaderFile
!= '':
1403 if not os
.path
.exists(InputHeaderFile
):
1404 self
.Error
= "Input header file '%s' does not exist" % InputHeaderFile
1407 InFd
= open(InputHeaderFile
, "r")
1408 IncLines
= InFd
.readlines()
1411 for item
in range(len(UpdRegionCheck
)):
1412 if UpdRegionCheck
[item
] == 'FSPT':
1413 HeaderFd
= open(os
.path
.join(FvDir
, HeaderTFileName
), "w")
1414 FileBase
= os
.path
.basename(os
.path
.join(FvDir
, HeaderTFileName
))
1415 elif UpdRegionCheck
[item
] == 'FSPM':
1416 HeaderFd
= open(os
.path
.join(FvDir
, HeaderMFileName
), "w")
1417 FileBase
= os
.path
.basename(os
.path
.join(FvDir
, HeaderMFileName
))
1418 elif UpdRegionCheck
[item
] == 'FSPS':
1419 HeaderFd
= open(os
.path
.join(FvDir
, HeaderSFileName
), "w")
1420 FileBase
= os
.path
.basename(os
.path
.join(FvDir
, HeaderSFileName
))
1421 FileName
= FileBase
.replace(".", "_").upper()
1422 HeaderFd
.write("%s\n" % (__copyright_h__
% date
.today().year
))
1423 HeaderFd
.write("#ifndef __%s__\n" % FileName
)
1424 HeaderFd
.write("#define __%s__\n\n" % FileName
)
1425 HeaderFd
.write("#include <%s>\n\n" % HeaderFileName
)
1426 HeaderFd
.write("#pragma pack(1)\n\n")
1429 for Line
in IncLines
:
1430 Match
= re
.search ("!EXPORT\s+([A-Z]+)\s+EXTERNAL_BOOTLOADER_STRUCT_(BEGIN|END)\s+", Line
)
1432 if Match
.group(2) == "BEGIN" and Match
.group(1) == UpdRegionCheck
[item
]:
1439 HeaderFd
.write(Line
)
1440 HeaderFd
.write("\n")
1446 StructStartWithComment
= []
1448 for Line
in TxtBody
:
1450 Match
= re
.match("(typedef struct {)", Line
)
1452 StartIndex
= Index
- 1
1453 Match
= re
.match("}\s([_A-Z0-9]+);", Line
)
1454 if Match
and (UpdRegionCheck
[item
] in Match
.group(1) or UpdConfigCheck
[item
] in Match
.group(1)) and (ExcludedSpecificUpd
[item
] not in Match
.group(1)):
1456 StructStart
.append(StartIndex
)
1457 StructEnd
.append(EndIndex
)
1459 for Line
in TxtBody
:
1461 for Item
in range(len(StructStart
)):
1462 if Index
== StructStart
[Item
]:
1463 Match
= re
.match("^(/\*\*\s*)", Line
)
1465 StructStartWithComment
.append(StructStart
[Item
])
1467 StructStartWithComment
.append(StructStart
[Item
] + 1)
1469 for Line
in TxtBody
:
1471 for Item
in range(len(StructStart
)):
1472 if Index
>= StructStartWithComment
[Item
] and Index
<= StructEnd
[Item
]:
1473 self
.WriteLinesWithoutTailingSpace(HeaderFd
, Line
)
1474 HeaderFd
.write("#pragma pack()\n\n")
1475 HeaderFd
.write("#endif\n")
1478 HeaderFd
= open(HeaderFile
, "w")
1479 FileBase
= os
.path
.basename(HeaderFile
)
1480 FileName
= FileBase
.replace(".", "_").upper()
1481 HeaderFd
.write("%s\n" % (__copyright_h__
% date
.today().year
))
1482 HeaderFd
.write("#ifndef __%s__\n" % FileName
)
1483 HeaderFd
.write("#define __%s__\n\n" % FileName
)
1484 HeaderFd
.write("#include <FspEas.h>\n\n")
1485 HeaderFd
.write("#pragma pack(1)\n\n")
1487 for item
in range(len(UpdRegionCheck
)):
1492 StructStartWithComment
= []
1494 for Line
in TxtBody
:
1496 Match
= re
.match("(typedef struct {)", Line
)
1498 StartIndex
= Index
- 1
1499 Match
= re
.match("#define\s([_A-Z0-9]+)\s*", Line
)
1500 if Match
and (UpdSignatureCheck
[item
] in Match
.group(1) or UpdSignatureCheck
[item
] in Match
.group(1)):
1501 StructStart
.append(Index
- 1)
1502 StructEnd
.append(Index
)
1504 for Line
in TxtBody
:
1506 for Item
in range(len(StructStart
)):
1507 if Index
== StructStart
[Item
]:
1508 Match
= re
.match("^(/\*\*\s*)", Line
)
1510 StructStartWithComment
.append(StructStart
[Item
])
1512 StructStartWithComment
.append(StructStart
[Item
] + 1)
1514 for Line
in TxtBody
:
1516 for Item
in range(len(StructStart
)):
1517 if Index
>= StructStartWithComment
[Item
] and Index
<= StructEnd
[Item
]:
1518 self
.WriteLinesWithoutTailingSpace(HeaderFd
, Line
)
1519 HeaderFd
.write("#pragma pack()\n\n")
1520 HeaderFd
.write("#endif\n")
1525 def WriteBsfStruct (self
, BsfFd
, Item
):
1526 LogExpr
= CLogicalExpression()
1527 if Item
['type'] == "None":
1528 Space
= "gPlatformFspPkgTokenSpaceGuid"
1530 Space
= Item
['space']
1531 Line
= " $%s_%s" % (Space
, Item
['cname'])
1532 Match
= re
.match("\s*\{([x0-9a-fA-F,\s]+)\}\s*", Item
['value'])
1534 DefaultValue
= Match
.group(1).strip()
1536 DefaultValue
= Item
['value'].strip()
1537 if 'bitlength' in Item
:
1538 BsfFd
.write(" %s%s%4d bits $_DEFAULT_ = %s\n" % (Line
, ' ' * (64 - len(Line
)), Item
['bitlength'], DefaultValue
))
1540 BsfFd
.write(" %s%s%4d bytes $_DEFAULT_ = %s\n" % (Line
, ' ' * (64 - len(Line
)), Item
['length'], DefaultValue
))
1542 if Item
['type'] == "Combo":
1543 if not Item
['option'] in self
._BuidinOption
:
1544 OptList
= Item
['option'].split(',')
1545 for Option
in OptList
:
1546 Option
= Option
.strip()
1547 (OpVal
, OpStr
) = Option
.split(':')
1548 test
= LogExpr
.getNumber (OpVal
)
1550 raise Exception("Selection Index '%s' is not a number" % OpVal
)
1551 TmpList
.append((OpVal
, OpStr
))
1554 def WriteBsfOption (self
, BsfFd
, Item
):
1555 PcdName
= Item
['space'] + '_' + Item
['cname']
1557 if Item
['type'] == "Combo":
1558 if Item
['option'] in self
._BuidinOption
:
1559 Options
= self
._BuidinOption
[Item
['option']]
1562 BsfFd
.write(' %s $%s, "%s", &%s,\n' % (Item
['type'], PcdName
, Item
['name'], Options
))
1564 elif Item
['type'].startswith("EditNum"):
1565 Match
= re
.match("EditNum\s*,\s*(HEX|DEC)\s*,\s*\((\d+|0x[0-9A-Fa-f]+)\s*,\s*(\d+|0x[0-9A-Fa-f]+)\)", Item
['type'])
1567 BsfFd
.write(' EditNum $%s, "%s", %s,\n' % (PcdName
, Item
['name'], Match
.group(1)))
1569 elif Item
['type'].startswith("EditText"):
1570 BsfFd
.write(' %s $%s, "%s",\n' % (Item
['type'], PcdName
, Item
['name']))
1572 elif Item
['type'] == "Table":
1573 Columns
= Item
['option'].split(',')
1574 if len(Columns
) != 0:
1575 BsfFd
.write(' %s $%s "%s",' % (Item
['type'], PcdName
, Item
['name']))
1577 Fmt
= Col
.split(':')
1579 raise Exception("Column format '%s' is invalid !" % Fmt
)
1581 Dtype
= int(Fmt
[1].strip())
1583 raise Exception("Column size '%s' is invalid !" % Fmt
[1])
1584 BsfFd
.write('\n Column "%s", %d bytes, %s' % (Fmt
[0].strip(), Dtype
, Fmt
[2].strip()))
1589 HelpLines
= Item
['help'].split('\\n\\r')
1591 for HelpLine
in HelpLines
:
1594 BsfFd
.write(' Help "%s"\n' % (HelpLine
))
1596 BsfFd
.write(' "%s"\n' % (HelpLine
))
1598 BsfFd
.write(' "Valid range: %s ~ %s"\n' % (Match
.group(2), Match
.group(3)))
1600 def GenerateBsfFile (self
, BsfFile
):
1603 self
.Error
= "BSF output file '%s' is invalid" % BsfFile
1606 if (self
.NoDscFileChange (BsfFile
)):
1607 # DSC has not been modified yet
1608 # So don't have to re-generate other files
1609 self
.Error
= 'No DSC file change, skip to create UPD BSF file'
1614 BsfFd
= open(BsfFile
, "w")
1615 BsfFd
.write("%s\n" % (__copyright_bsf__
% date
.today().year
))
1616 BsfFd
.write("%s\n" % self
._GlobalDataDef
)
1617 BsfFd
.write("StructDef\n")
1619 for Item
in self
._CfgItemList
:
1620 if Item
['find'] != '':
1621 BsfFd
.write('\n Find "%s"\n' % Item
['find'])
1622 NextOffset
= Item
['offset'] + Item
['length']
1623 if Item
['name'] != '':
1624 if NextOffset
!= Item
['offset']:
1625 BsfFd
.write(" Skip %d bytes\n" % (Item
['offset'] - NextOffset
))
1626 if len(Item
['subreg']) > 0:
1627 NextOffset
= Item
['offset']
1628 BitsOffset
= NextOffset
* 8
1629 for SubItem
in Item
['subreg']:
1630 BitsOffset
+= SubItem
['bitlength']
1631 if SubItem
['name'] == '':
1632 if 'bitlength' in SubItem
:
1633 BsfFd
.write(" Skip %d bits\n" % (SubItem
['bitlength']))
1635 BsfFd
.write(" Skip %d bytes\n" % (SubItem
['length']))
1637 Options
= self
.WriteBsfStruct(BsfFd
, SubItem
)
1638 if len(Options
) > 0:
1639 OptionDict
[SubItem
['space']+'_'+SubItem
['cname']] = Options
1641 NextBitsOffset
= (Item
['offset'] + Item
['length']) * 8
1642 if NextBitsOffset
> BitsOffset
:
1643 BitsGap
= NextBitsOffset
- BitsOffset
1644 BitsRemain
= BitsGap
% 8
1646 BsfFd
.write(" Skip %d bits\n" % BitsRemain
)
1647 BitsGap
-= BitsRemain
1648 BytesRemain
= int(BitsGap
/ 8)
1650 BsfFd
.write(" Skip %d bytes\n" % BytesRemain
)
1651 NextOffset
= Item
['offset'] + Item
['length']
1653 NextOffset
= Item
['offset'] + Item
['length']
1654 Options
= self
.WriteBsfStruct(BsfFd
, Item
)
1655 if len(Options
) > 0:
1656 OptionDict
[Item
['space']+'_'+Item
['cname']] = Options
1657 BsfFd
.write("\nEndStruct\n\n")
1659 BsfFd
.write("%s" % self
._BuidinOptionTxt
)
1661 for Each
in OptionDict
:
1662 BsfFd
.write("List &%s\n" % Each
)
1663 for Item
in OptionDict
[Each
]:
1664 BsfFd
.write(' Selection %s , "%s"\n' % (Item
[0], Item
[1]))
1665 BsfFd
.write("EndList\n\n")
1667 BsfFd
.write("BeginInfoBlock\n")
1668 BsfFd
.write(' PPVer "%s"\n' % (self
._CfgBlkDict
['ver']))
1669 BsfFd
.write(' Description "%s"\n' % (self
._CfgBlkDict
['name']))
1670 BsfFd
.write("EndInfoBlock\n\n")
1672 for Each
in self
._CfgPageDict
:
1673 BsfFd
.write('Page "%s"\n' % self
._CfgPageDict
[Each
])
1675 for Item
in self
._CfgItemList
:
1676 if Item
['name'] != '':
1677 if Item
['page'] != Each
:
1679 if len(Item
['subreg']) > 0:
1680 for SubItem
in Item
['subreg']:
1681 if SubItem
['name'] != '':
1682 BsfItems
.append(SubItem
)
1684 BsfItems
.append(Item
)
1686 BsfItems
.sort(key
=lambda x
: x
['order'])
1688 for Item
in BsfItems
:
1689 self
.WriteBsfOption (BsfFd
, Item
)
1690 BsfFd
.write("EndPage\n\n")
1697 print ("GenCfgOpt Version 0.56")
1699 print (" GenCfgOpt UPDTXT PlatformDscFile BuildFvDir [-D Macros]")
1700 print (" GenCfgOpt HEADER PlatformDscFile BuildFvDir InputHFile [-D Macros]")
1701 print (" GenCfgOpt GENBSF PlatformDscFile BuildFvDir BsfOutFile [-D Macros]")
1705 # Parse the options and args
1709 GenCfgOpt
= CGenCfgOpt()
1710 while i
< len(sys
.argv
):
1711 if sys
.argv
[i
].strip().lower() == "--pcd":
1712 BuildOptionPcd
.append(sys
.argv
[i
+1])
1715 argc
= len(sys
.argv
)
1720 DscFile
= sys
.argv
[2]
1721 if not os
.path
.exists(DscFile
):
1722 print ("ERROR: Cannot open DSC file '%s' !" % DscFile
)
1727 if sys
.argv
[4][0] == '-':
1730 OutFile
= sys
.argv
[4]
1733 if GenCfgOpt
.ParseMacros(sys
.argv
[Start
:]) != 0:
1734 print ("ERROR: Macro parsing failed !")
1738 if not os
.path
.exists(FvDir
):
1741 if GenCfgOpt
.ParseDscFile(DscFile
, FvDir
) != 0:
1742 print ("ERROR: %s !" % GenCfgOpt
.Error
)
1745 if GenCfgOpt
.UpdateSubRegionDefaultValue() != 0:
1746 print ("ERROR: %s !" % GenCfgOpt
.Error
)
1749 if sys
.argv
[1] == "UPDTXT":
1750 Ret
= GenCfgOpt
.CreateSplitUpdTxt(OutFile
)
1752 # No change is detected
1754 print ("INFO: %s !" % (GenCfgOpt
.Error
))
1756 print ("ERROR: %s !" % (GenCfgOpt
.Error
))
1758 elif sys
.argv
[1] == "HEADER":
1759 Ret
= GenCfgOpt
.CreateHeaderFile(OutFile
)
1761 # No change is detected
1763 print ("INFO: %s !" % (GenCfgOpt
.Error
))
1765 print ("ERROR: %s !" % (GenCfgOpt
.Error
))
1768 elif sys
.argv
[1] == "GENBSF":
1769 Ret
= GenCfgOpt
.GenerateBsfFile(OutFile
)
1771 # No change is detected
1773 print ("INFO: %s !" % (GenCfgOpt
.Error
))
1775 print ("ERROR: %s !" % (GenCfgOpt
.Error
))
1782 print ("ERROR: Unknown command '%s' !" % sys
.argv
[1])
1789 if __name__
== '__main__':