]>
git.proxmox.com Git - mirror_edk2.git/blob - IntelFsp2Pkg/Tools/GenCfgOpt.py
3 # Copyright (c) 2014 - 2020, 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
):
290 self
._GlobalDataDef
= """
296 self
._BuidinOptionTxt
= """
298 Selection 0x1 , "Enabled"
299 Selection 0x0 , "Disabled"
304 self
._BsfKeyList
= ['FIND','NAME','HELP','TYPE','PAGE','OPTION','ORDER']
305 self
._HdrKeyList
= ['HEADER','STRUCT', 'EMBED', 'COMMENT']
306 self
._BuidinOption
= {'$EN_DIS' : 'EN_DIS'}
310 self
._CfgBlkDict
= {}
311 self
._CfgPageDict
= {}
312 self
._CfgItemList
= []
317 def ParseMacros (self
, MacroDefStr
):
318 # ['-DABC=1', '-D', 'CFG_DEBUG=1', '-D', 'CFG_OUTDIR=Build']
321 for Macro
in MacroDefStr
:
322 if Macro
.startswith('-D'):
330 Match
= re
.match("(\w+)=(.+)", Macro
)
332 self
._MacroDict
[Match
.group(1)] = Match
.group(2)
334 Match
= re
.match("(\w+)", Macro
)
336 self
._MacroDict
[Match
.group(1)] = ''
337 if len(self
._MacroDict
) == 0:
342 print ("INFO : Macro dictionary:")
343 for Each
in self
._MacroDict
:
344 print (" $(%s) = [ %s ]" % (Each
, self
._MacroDict
[Each
]))
347 def EvaulateIfdef (self
, Macro
):
348 Result
= Macro
in self
._MacroDict
350 print ("INFO : Eval Ifdef [%s] : %s" % (Macro
, Result
))
353 def ExpandMacros (self
, Input
):
355 Match
= re
.findall("\$\(\w+\)", Input
)
358 Variable
= Each
[2:-1]
359 if Variable
in self
._MacroDict
:
360 Line
= Line
.replace(Each
, self
._MacroDict
[Variable
])
363 print ("WARN : %s is not defined" % Each
)
364 Line
= Line
.replace(Each
, Each
[2:-1])
367 def ExpandPcds (self
, Input
):
369 Match
= re
.findall("(\w+\.\w+)", Input
)
371 for PcdName
in Match
:
372 if PcdName
in self
._PcdsDict
:
373 Line
= Line
.replace(PcdName
, self
._PcdsDict
[PcdName
])
376 print ("WARN : %s is not defined" % PcdName
)
379 def EvaluateExpress (self
, Expr
):
380 ExpExpr
= self
.ExpandPcds(Expr
)
381 ExpExpr
= self
.ExpandMacros(ExpExpr
)
382 LogExpr
= CLogicalExpression()
383 Result
= LogExpr
.evaluateExpress (ExpExpr
)
385 print ("INFO : Eval Express [%s] : %s" % (Expr
, Result
))
388 def FormatListValue(self
, ConfigDict
):
389 Struct
= ConfigDict
['struct']
390 if Struct
not in ['UINT8','UINT16','UINT32','UINT64']:
394 binlist
= ConfigDict
['value'][1:-1].split(',')
397 if each
.startswith('0x'):
398 value
= int(each
, 16)
401 dataarray
.append(value
)
403 unit
= int(Struct
[4:]) / 8
404 if int(ConfigDict
['length']) != unit
* len(dataarray
):
405 raise Exception("Array size is not proper for '%s' !" % ConfigDict
['cname'])
408 for each
in dataarray
:
410 for loop
in range(int(unit
)):
411 bytearray
.append("0x%02X" % (value
& 0xFF))
413 newvalue
= '{' + ','.join(bytearray
) + '}'
414 ConfigDict
['value'] = newvalue
417 def ParseDscFile (self
, DscFile
, FvDir
):
420 self
._CfgItemList
= []
421 self
._CfgPageDict
= {}
422 self
._CfgBlkDict
= {}
423 self
._DscFile
= DscFile
436 DscFd
= open(DscFile
, "r")
437 DscLines
= DscFd
.readlines()
440 MaxAlign
= 32 #Default align to 32, but if there are 64 bit unit, align to 64
441 SizeAlign
= 0 #record the struct max align
442 Base
= 0 #Starting offset of sub-structure.
444 DscLine
= DscLines
.pop(0).strip()
446 Match
= re
.match("^\[(.+)\]", DscLine
)
447 if Match
is not None:
452 if Match
.group(1).lower() == "Defines".lower():
454 if (Match
.group(1).lower() == "PcdsFeatureFlag".lower() or Match
.group(1).lower() == "PcdsFixedAtBuild".lower()):
456 elif Match
.group(1).lower() == "PcdsDynamicVpd.Upd".lower():
458 ConfigDict
['header'] = 'ON'
459 ConfigDict
['region'] = 'UPD'
460 ConfigDict
['order'] = -1
461 ConfigDict
['page'] = ''
462 ConfigDict
['name'] = ''
463 ConfigDict
['find'] = ''
464 ConfigDict
['struct'] = ''
465 ConfigDict
['embed'] = ''
466 ConfigDict
['comment'] = ''
467 ConfigDict
['subreg'] = []
471 if IsDefSect
or IsPcdSect
or IsUpdSect
or IsVpdSect
:
472 if re
.match("^!else($|\s+#.+)", DscLine
):
474 IfStack
[-1] = not IfStack
[-1]
476 print("ERROR: No paired '!if' found for '!else' for line '%s'" % DscLine
)
478 elif re
.match("^!endif($|\s+#.+)", DscLine
):
481 Level
= ElifStack
.pop()
485 print("ERROR: No paired '!if' found for '!endif' for line '%s'" % DscLine
)
489 Match
= re
.match("!(ifdef|ifndef)\s+(.+)", DscLine
)
491 Result
= self
.EvaulateIfdef (Match
.group(2))
492 if Match
.group(1) == 'ifndef':
494 IfStack
.append(Result
)
497 Match
= re
.match("!(if|elseif)\s+(.+)", DscLine
.split("#")[0])
499 Result
= self
.EvaluateExpress(Match
.group(2))
500 if Match
.group(1) == "if":
502 IfStack
.append(Result
)
505 IfStack
[-1] = not IfStack
[-1]
506 IfStack
.append(Result
)
507 ElifStack
[-1] = ElifStack
[-1] + 1
509 print("ERROR: No paired '!if' found for '!elif' for line '%s'" % DscLine
)
513 Handle
= reduce(lambda x
,y
: x
and y
, IfStack
)
517 Match
= re
.match("!include\s+(.+)", DscLine
)
519 IncludeFilePath
= Match
.group(1)
520 IncludeFilePath
= self
.ExpandMacros(IncludeFilePath
)
521 PackagesPath
= os
.getenv("PACKAGES_PATH")
523 for PackagePath
in PackagesPath
.split(os
.pathsep
):
524 IncludeFilePathAbs
= os
.path
.join(os
.path
.normpath(PackagePath
), os
.path
.normpath(IncludeFilePath
))
525 if os
.path
.exists(IncludeFilePathAbs
):
526 IncludeDsc
= open(IncludeFilePathAbs
, "r")
529 IncludeDsc
= open(IncludeFilePath
, "r")
530 if IncludeDsc
== None:
531 print("ERROR: Cannot open file '%s'" % IncludeFilePath
)
533 NewDscLines
= IncludeDsc
.readlines()
535 DscLines
= NewDscLines
+ DscLines
538 if DscLine
.startswith('!'):
539 print("ERROR: Unrecognized directive for line '%s'" % DscLine
)
545 #DEFINE UPD_TOOL_GUID = 8C3D856A-9BE6-468E-850A-24F7A8D38E09
546 #DEFINE FSP_T_UPD_TOOL_GUID = 34686CA3-34F9-4901-B82A-BA630F0714C6
547 #DEFINE FSP_M_UPD_TOOL_GUID = 39A250DB-E465-4DD1-A2AC-E2BD3C0E2385
548 #DEFINE FSP_S_UPD_TOOL_GUID = CAE3605B-5B34-4C85-B3D7-27D54273C40F
549 Match
= re
.match("^\s*(?:DEFINE\s+)*(\w+)\s*=\s*([/$()-.\w]+)", DscLine
)
551 self
._MacroDict
[Match
.group(1)] = self
.ExpandMacros(Match
.group(2))
553 print ("INFO : DEFINE %s = [ %s ]" % (Match
.group(1), self
.ExpandMacros(Match
.group(2))))
555 #gSiPkgTokenSpaceGuid.PcdTxtEnable|FALSE
556 #gSiPkgTokenSpaceGuid.PcdOverclockEnable|TRUE
557 Match
= re
.match("^\s*([\w\.]+)\s*\|\s*(\w+)", DscLine
)
559 self
._PcdsDict
[Match
.group(1)] = Match
.group(2)
561 print ("INFO : PCD %s = [ %s ]" % (Match
.group(1), Match
.group(2)))
563 while i
< len(BuildOptionPcd
):
564 Match
= re
.match("\s*([\w\.]+)\s*\=\s*(\w+)", BuildOptionPcd
[i
])
566 self
._PcdsDict
[Match
.group(1)] = Match
.group(2)
569 Match
= re
.match("^\s*#\s+(!BSF|@Bsf|!HDR)\s+(.+)", DscLine
)
571 Remaining
= Match
.group(2)
572 if Match
.group(1) == '!BSF' or Match
.group(1) == '@Bsf':
573 Match
= re
.match("(?:^|.+\s+)PAGES:{(.+?)}", Remaining
)
575 # !BSF PAGES:{HSW:"Haswell System Agent", LPT:"Lynx Point PCH"}
576 PageList
= Match
.group(1).split(',')
577 for Page
in PageList
:
579 Match
= re
.match("(\w+):\"(.+)\"", Page
)
580 self
._CfgPageDict
[Match
.group(1)] = Match
.group(2)
582 Match
= re
.match("(?:^|.+\s+)BLOCK:{NAME:\"(.+)\"\s*,\s*VER:\"(.+)\"\s*}", Remaining
)
584 self
._CfgBlkDict
['name'] = Match
.group(1)
585 self
._CfgBlkDict
['ver'] = Match
.group(2)
587 for Key
in self
._BsfKeyList
:
588 Match
= re
.match("(?:^|.+\s+)%s:{(.+?)}" % Key
, Remaining
)
590 if Key
in ['NAME', 'HELP', 'OPTION'] and Match
.group(1).startswith('+'):
591 ConfigDict
[Key
.lower()] += Match
.group(1)[1:]
593 ConfigDict
[Key
.lower()] = Match
.group(1)
595 for Key
in self
._HdrKeyList
:
596 Match
= re
.match("(?:^|.+\s+)%s:{(.+?)}" % Key
, Remaining
)
598 ConfigDict
[Key
.lower()] = Match
.group(1)
600 Match
= re
.match("^\s*#\s+@Prompt\s+(.+)", DscLine
)
602 ConfigDict
['name'] = Match
.group(1)
604 Match
= re
.match("^\s*#\s*@ValidList\s*(.+)\s*\|\s*(.+)\s*\|\s*(.+)\s*", DscLine
)
606 if Match
.group(2).strip() in self
._BuidinOption
:
607 ConfigDict
['option'] = Match
.group(2).strip()
609 OptionValueList
= Match
.group(2).split(',')
610 OptionStringList
= Match
.group(3).split(',')
612 for Option
in OptionValueList
:
613 Option
= Option
.strip()
614 ConfigDict
['option'] = ConfigDict
['option'] + str(Option
) + ':' + OptionStringList
[Index
].strip()
616 if Index
in range(len(OptionValueList
)):
617 ConfigDict
['option'] += ', '
618 ConfigDict
['type'] = "Combo"
620 Match
= re
.match("^\s*#\s*@ValidRange\s*(.+)\s*\|\s*(.+)\s*-\s*(.+)\s*", DscLine
)
622 if "0x" in Match
.group(2) or "0x" in Match
.group(3):
623 ConfigDict
['type'] = "EditNum, HEX, (%s,%s)" % (Match
.group(2), Match
.group(3))
625 ConfigDict
['type'] = "EditNum, DEC, (%s,%s)" % (Match
.group(2), Match
.group(3))
627 Match
= re
.match("^\s*##\s+(.+)", DscLine
)
629 ConfigDict
['help'] = Match
.group(1)
633 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
)
635 Match
= re
.match("^([_a-zA-Z0-9]+).([_a-zA-Z0-9]+)\s*\|\s*(0x[0-9A-F]+)(?:\s*\|\s*(.+))?", DscLine
)
637 ConfigDict
['space'] = Match
.group(1)
638 ConfigDict
['cname'] = Match
.group(2)
639 if Match
.group(3) != '*':
641 Offset
= int (Match
.group(3), 16)
645 if Hardcode
and AutoAlign
:
646 print("Hardcode and auto-align mixed mode is not supported by GenCfgOpt")
648 ConfigDict
['offset'] = Offset
649 if ConfigDict
['order'] == -1:
650 ConfigDict
['order'] = ConfigDict
['offset'] << 8
652 (Major
, Minor
) = ConfigDict
['order'].split('.')
653 ConfigDict
['order'] = (int (Major
, 16) << 8 ) + int (Minor
, 16)
655 Value
= Match
.group(5).strip()
656 if Match
.group(4).startswith("0x"):
657 Length
= int (Match
.group(4), 16)
659 Length
= int (Match
.group(4))
662 Value
= Match
.group(4)
665 Value
= Value
.strip()
667 Match
= re
.match("^.+\s*\|\s*(.+)", Value
)
669 Value
= Match
.group(1)
672 ConfigDict
['length'] = Length
673 Match
= re
.match("\$\((\w+)\)", Value
)
675 if Match
.group(1) in self
._MacroDict
:
676 Value
= self
._MacroDict
[Match
.group(1)]
678 ConfigDict
['value'] = Value
679 if (len(Value
) > 0) and (Value
[0] == '{'):
680 Value
= self
.FormatListValue(ConfigDict
)
682 if ConfigDict
['name'] == '':
683 # Clear BSF specific items
684 ConfigDict
['bsfname'] = ''
685 ConfigDict
['help'] = ''
686 ConfigDict
['type'] = ''
687 ConfigDict
['option'] = ''
688 if IsUpdSect
and AutoAlign
:
689 ItemLength
= int(ConfigDict
['length'])
690 ItemOffset
= int(ConfigDict
['offset'])
691 ItemStruct
= ConfigDict
['struct']
693 if ItemLength
in [1, 2, 4, 8] and not ConfigDict
['value'].startswith('{'):
695 # If there are 64 bit unit, align to 64
700 UnitDict
= {'UINT8':1, 'UINT16':2, 'UINT32':4, 'UINT64':8}
701 if ItemStruct
in ['UINT8', 'UINT16', 'UINT32', 'UINT64']:
702 Unit
= UnitDict
[ItemStruct
]
703 # If there are 64 bit unit, align to 64
706 SizeAlign
= max(SizeAlign
, Unit
)
707 if (ConfigDict
['embed'].find(':START') != -1):
709 SubOffset
= ItemOffset
- Base
710 SubRemainder
= SubOffset
% Unit
712 Diff
= Unit
- SubRemainder
713 Offset
= Offset
+ Diff
714 ItemOffset
= ItemOffset
+ Diff
716 if (ConfigDict
['embed'].find(':END') != -1):
717 Remainder
= Offset
% (MaxAlign
/8) # MaxAlign is either 32 or 64
719 Diff
= int((MaxAlign
/8) - Remainder
)
720 Offset
= Offset
+ Diff
721 ItemOffset
= ItemOffset
+ Diff
722 MaxAlign
= 32 # Reset to default 32 align when struct end
723 if (ConfigDict
['cname'] == 'UpdTerminator'):
724 # ItemLength is the size of UpdTerminator
725 # Itemlength might be 16, 32, or 64
726 # Struct align to 64 if UpdTerminator
727 # or struct size is 64 bit, else align to 32
728 Remainder
= Offset
% max(ItemLength
/8, 4, SizeAlign
)
729 Offset
= Offset
+ ItemLength
731 Diff
= int(max(ItemLength
/8, 4, SizeAlign
) - Remainder
)
732 ItemOffset
= ItemOffset
+ Diff
733 ConfigDict
['offset'] = ItemOffset
735 self
._CfgItemList
.append(ConfigDict
.copy())
736 ConfigDict
['name'] = ''
737 ConfigDict
['find'] = ''
738 ConfigDict
['struct'] = ''
739 ConfigDict
['embed'] = ''
740 ConfigDict
['comment'] = ''
741 ConfigDict
['order'] = -1
742 ConfigDict
['subreg'] = []
743 ConfigDict
['option'] = ''
745 # It could be a virtual item as below
746 # !BSF FIELD:{SerialDebugPortAddress0:1}
748 # @Bsf FIELD:{SerialDebugPortAddress0:1b}
749 Match
= re
.match("^\s*#\s+(!BSF|@Bsf)\s+FIELD:{(.+):(\d+)([Bb])?}", DscLine
)
751 SubCfgDict
= ConfigDict
.copy()
752 if (Match
.group(4) == None) or (Match
.group(4) == 'B'):
754 elif Match
.group(4) == 'b':
757 print("ERROR: Invalide BSF FIELD length for line '%s'" % DscLine
)
759 SubCfgDict
['cname'] = Match
.group(2)
760 SubCfgDict
['bitlength'] = int (Match
.group(3)) * UnitBitLen
761 if SubCfgDict
['bitlength'] > 0:
762 LastItem
= self
._CfgItemList
[-1]
763 if len(LastItem
['subreg']) == 0:
766 SubOffset
= LastItem
['subreg'][-1]['bitoffset'] + LastItem
['subreg'][-1]['bitlength']
767 SubCfgDict
['bitoffset'] = SubOffset
768 LastItem
['subreg'].append (SubCfgDict
.copy())
769 ConfigDict
['name'] = ''
772 def GetBsfBitFields (self
, subitem
, bytes
):
773 start
= subitem
['bitoffset']
774 end
= start
+ subitem
['bitlength']
775 bitsvalue
= ''.join('{0:08b}'.format(i
) for i
in bytes
[::-1])
776 bitsvalue
= bitsvalue
[::-1]
777 bitslen
= len(bitsvalue
)
778 if start
> bitslen
or end
> bitslen
:
779 print ("Invalid bits offset [%d,%d] for %s" % (start
, end
, subitem
['name']))
781 return hex(int(bitsvalue
[start
:end
][::-1], 2))
783 def UpdateSubRegionDefaultValue (self
):
785 for Item
in self
._CfgItemList
:
786 if len(Item
['subreg']) == 0:
789 if Item
['value'][0] == '{':
790 binlist
= Item
['value'][1:-1].split(',')
793 if each
.startswith('0x'):
794 value
= int(each
, 16)
797 bytearray
.append(value
)
799 if Item
['value'].startswith('0x'):
800 value
= int(Item
['value'], 16)
802 value
= int(Item
['value'])
804 while idx
< Item
['length']:
805 bytearray
.append(value
& 0xFF)
808 for SubItem
in Item
['subreg']:
809 valuestr
= self
.GetBsfBitFields(SubItem
, bytearray
)
810 SubItem
['value'] = valuestr
813 def NoDscFileChange (self
, OutPutFile
):
815 if not os
.path
.exists(OutPutFile
):
818 DscTime
= os
.path
.getmtime(self
._DscFile
)
819 OutputTime
= os
.path
.getmtime(OutPutFile
)
820 if DscTime
> OutputTime
:
824 def CreateSplitUpdTxt (self
, UpdTxtFile
):
825 GuidList
= ['FSP_T_UPD_TOOL_GUID','FSP_M_UPD_TOOL_GUID','FSP_S_UPD_TOOL_GUID']
826 SignatureList
= ['0x545F', '0x4D5F','0x535F'] # _T, _M, and _S signature for FSPT, FSPM, FSPS
827 for Index
in range(len(GuidList
)):
830 if GuidList
[Index
] not in self
._MacroDict
:
831 self
.Error
= "%s definition is missing in DSC file" % (GuidList
[Index
])
835 UpdTxtFile
= os
.path
.join(FvDir
, self
._MacroDict
[GuidList
[Index
]] + '.txt')
837 if (self
.NoDscFileChange (UpdTxtFile
)):
838 # DSC has not been modified yet
839 # So don't have to re-generate other files
840 self
.Error
= 'No DSC file change, skip to create UPD TXT file'
843 TxtFd
= open(UpdTxtFile
, "w")
844 TxtFd
.write("%s\n" % (__copyright_txt__
% date
.today().year
))
852 for Item
in self
._CfgItemList
:
853 if Item
['cname'] == 'Signature' and str(Item
['value'])[0:6] == SignatureList
[Index
]:
854 StartAddr
= Item
['offset']
855 NextOffset
= StartAddr
857 if Item
['cname'] == 'UpdTerminator' and InRange
== True:
858 EndAddr
= Item
['offset']
861 for Item
in self
._CfgItemList
:
862 if Item
['cname'] == 'Signature' and str(Item
['value'])[0:6] == SignatureList
[Index
]:
866 if Item
['cname'] == 'UpdTerminator':
868 if Item
['region'] != 'UPD':
870 Offset
= Item
['offset']
871 if StartAddr
> Offset
or EndAddr
< Offset
:
873 if NextOffset
< Offset
:
875 TxtFd
.write("%s.UnusedUpdSpace%d|%s0x%04X|0x%04X|{0}\n" % (Item
['space'], SpaceIdx
, Default
, NextOffset
- StartAddr
, Offset
- NextOffset
))
876 SpaceIdx
= SpaceIdx
+ 1
877 NextOffset
= Offset
+ Item
['length']
878 TxtFd
.write("%s.%s|%s0x%04X|%s|%s\n" % (Item
['space'],Item
['cname'],Default
,Item
['offset'] - StartAddr
,Item
['length'],Item
['value']))
882 def ProcessMultilines (self
, String
, MaxCharLength
):
884 StringLength
= len(String
)
885 CurrentStringStart
= 0
888 if len(String
) <= MaxCharLength
:
889 while (StringOffset
< StringLength
):
890 if StringOffset
>= 1:
891 if String
[StringOffset
- 1] == '\\' and String
[StringOffset
] == 'n':
892 BreakLineDict
.append (StringOffset
+ 1)
894 if BreakLineDict
!= []:
895 for Each
in BreakLineDict
:
896 Multilines
+= " %s\n" % String
[CurrentStringStart
:Each
].lstrip()
897 CurrentStringStart
= Each
898 if StringLength
- CurrentStringStart
> 0:
899 Multilines
+= " %s\n" % String
[CurrentStringStart
:].lstrip()
901 Multilines
= " %s\n" % String
905 FoundSpaceChar
= False
906 while (StringOffset
< StringLength
):
907 if StringOffset
>= 1:
908 if NewLineCount
>= MaxCharLength
- 1:
909 if String
[StringOffset
] == ' ' and StringLength
- StringOffset
> 10:
910 BreakLineDict
.append (NewLineStart
+ NewLineCount
)
911 NewLineStart
= NewLineStart
+ NewLineCount
913 FoundSpaceChar
= True
914 elif StringOffset
== StringLength
- 1 and FoundSpaceChar
== False:
915 BreakLineDict
.append (0)
916 if String
[StringOffset
- 1] == '\\' and String
[StringOffset
] == 'n':
917 BreakLineDict
.append (StringOffset
+ 1)
918 NewLineStart
= StringOffset
+ 1
922 if BreakLineDict
!= []:
923 BreakLineDict
.sort ()
924 for Each
in BreakLineDict
:
926 Multilines
+= " %s\n" % String
[CurrentStringStart
:Each
].lstrip()
927 CurrentStringStart
= Each
928 if StringLength
- CurrentStringStart
> 0:
929 Multilines
+= " %s\n" % String
[CurrentStringStart
:].lstrip()
932 def CreateField (self
, Item
, Name
, Length
, Offset
, Struct
, BsfName
, Help
, Option
):
940 if Length
in [1,2,4,8]:
941 Type
= "UINT%d" % (Length
* 8)
942 if Name
.startswith("UnusedUpdSpace") and Length
!= 1:
949 if Item
and Item
['value'].startswith('{'):
955 if Struct
in ['UINT8','UINT16','UINT32','UINT64']:
957 Unit
= int(Type
[4:]) / 8
958 Length
= Length
/ Unit
963 Name
= Name
+ '[%d]' % Length
965 if len(Type
) < PosName
:
966 Space1
= PosName
- len(Type
)
971 NameLine
=" - %s\n" % BsfName
976 HelpLine
= self
.ProcessMultilines (Help
, 80)
979 OptionLine
= self
.ProcessMultilines (Option
, 80)
984 OffsetStr
= '0x%04X' % Offset
986 return "\n/** Offset %s%s%s%s**/\n %s%s%s;\n" % (OffsetStr
, NameLine
, HelpLine
, OptionLine
, Type
, ' ' * Space1
, Name
,)
988 def PostProcessBody (self
, TextBody
):
994 IsUpdHdrDefined
= False
996 for Line
in TextBody
:
997 SplitToLines
= Line
.splitlines()
998 MatchComment
= re
.match("^/\*\sCOMMENT:(\w+):([\w|\W|\s]+)\s\*/\s([\s\S]*)", SplitToLines
[0])
1000 if MatchComment
.group(1) == 'FSP_UPD_HEADER':
1004 if IsUpdHdrDefined
!= True or IsUpdHeader
!= True:
1005 CommentLine
= " " + MatchComment
.group(2) + "\n"
1006 NewTextBody
.append("/**" + CommentLine
+ "**/\n")
1007 Line
= Line
[(len(SplitToLines
[0]) + 1):]
1009 Match
= re
.match("^/\*\sEMBED_STRUCT:(\w+):(\w+):(START|END)\s\*/\s([\s\S]*)", Line
)
1011 Line
= Match
.group(4)
1012 if Match
.group(1) == 'FSP_UPD_HEADER':
1017 if Match
and Match
.group(3) == 'START':
1018 if IsUpdHdrDefined
!= True or IsUpdHeader
!= True:
1019 NewTextBody
.append ('typedef struct {\n')
1020 StructName
= Match
.group(1)
1021 VariableName
= Match
.group(2)
1022 MatchOffset
= re
.search('/\*\*\sOffset\s0x([a-fA-F0-9]+)', Line
)
1024 Offset
= int(MatchOffset
.group(1), 16)
1029 OldTextBody
.append (self
.CreateField (None, VariableName
, 0, Offset
, StructName
, '', '', ''))
1031 if IsUpdHdrDefined
!= True or IsUpdHeader
!= True:
1032 NewTextBody
.append (Line
)
1034 OldTextBody
.append (Line
)
1036 if Match
and Match
.group(3) == 'END':
1037 if (StructName
!= Match
.group(1)) or (VariableName
!= Match
.group(2)):
1038 print ("Unmatched struct name '%s' and '%s' !" % (StructName
, Match
.group(1)))
1040 if IsUpdHdrDefined
!= True or IsUpdHeader
!= True:
1041 NewTextBody
.append ('} %s;\n\n' % StructName
)
1042 IsUpdHdrDefined
= True
1044 NewTextBody
.extend(OldTextBody
)
1047 def WriteLinesWithoutTailingSpace (self
, HeaderFd
, Line
):
1048 TxtBody2
= Line
.splitlines(True)
1049 for Line2
in TxtBody2
:
1050 Line2
= Line2
.rstrip()
1052 HeaderFd
.write (Line2
)
1054 def CreateHeaderFile (self
, InputHeaderFile
):
1057 HeaderFileName
= 'FspUpd.h'
1058 HeaderFile
= os
.path
.join(FvDir
, HeaderFileName
)
1060 # Check if header needs to be recreated
1061 if (self
.NoDscFileChange (HeaderFile
)):
1062 # DSC has not been modified yet
1063 # So don't have to re-generate other files
1064 self
.Error
= 'No DSC file change, skip to create UPD header file'
1068 for Item
in self
._CfgItemList
:
1069 if str(Item
['cname']) == 'Signature' and Item
['length'] == 8:
1070 Value
= int(Item
['value'], 16)
1073 Chars
.append(chr(Value
& 0xFF))
1075 SignatureStr
= ''.join(Chars
)
1076 # Signature will be _T / _M / _S for FSPT / FSPM / FSPS accordingly
1077 if '_T' in SignatureStr
[6:6+2]:
1078 TxtBody
.append("#define FSPT_UPD_SIGNATURE %s /* '%s' */\n\n" % (Item
['value'], SignatureStr
))
1079 elif '_M' in SignatureStr
[6:6+2]:
1080 TxtBody
.append("#define FSPM_UPD_SIGNATURE %s /* '%s' */\n\n" % (Item
['value'], SignatureStr
))
1081 elif '_S' in SignatureStr
[6:6+2]:
1082 TxtBody
.append("#define FSPS_UPD_SIGNATURE %s /* '%s' */\n\n" % (Item
['value'], SignatureStr
))
1083 TxtBody
.append("\n")
1085 for Region
in ['UPD']:
1087 UpdSignature
= ['0x545F', '0x4D5F', '0x535F'] #['_T', '_M', '_S'] signature for FSPT, FSPM, FSPS
1088 UpdStructure
= ['FSPT_UPD', 'FSPM_UPD', 'FSPS_UPD']
1089 for Item
in self
._CfgItemList
:
1090 if Item
["cname"] == 'Signature' and Item
["value"][0:6] in UpdSignature
:
1091 UpdOffsetTable
.append (Item
["offset"])
1093 for UpdIdx
in range(len(UpdOffsetTable
)):
1095 for Item
in self
._CfgItemList
:
1096 if Item
["comment"] != '' and Item
["offset"] >= UpdOffsetTable
[UpdIdx
]:
1097 MatchComment
= re
.match("^(U|V)PD_DATA_REGION:([\w|\W|\s]+)", Item
["comment"])
1098 if MatchComment
and MatchComment
.group(1) == Region
[0]:
1099 CommentLine
= " " + MatchComment
.group(2) + "\n"
1100 TxtBody
.append("/**" + CommentLine
+ "**/\n")
1101 elif Item
["offset"] >= UpdOffsetTable
[UpdIdx
] and Item
["comment"] == '':
1102 Match
= re
.match("^FSP([\w|\W|\s])_UPD", UpdStructure
[UpdIdx
])
1104 TxtBody
.append("/** Fsp " + Match
.group(1) + " UPD Configuration\n**/\n")
1105 TxtBody
.append("typedef struct {\n")
1115 for Item
in self
._CfgItemList
:
1116 if Item
['cname'] == 'Signature' and str(Item
['value'])[0:6] == UpdSignature
[UpdIdx
] or Region
[0] == 'V':
1120 if Item
['cname'] == 'UpdTerminator':
1123 if Item
['region'] != Region
:
1126 if Item
["offset"] < UpdOffsetTable
[UpdIdx
]:
1129 NextVisible
= LastVisible
1131 if LastVisible
and (Item
['header'] == 'OFF'):
1133 ResvOffset
= Item
['offset']
1134 elif (not LastVisible
) and Item
['header'] == 'ON':
1136 Name
= "Reserved" + Region
[0] + "pdSpace%d" % ResvIdx
1137 ResvIdx
= ResvIdx
+ 1
1138 TxtBody
.append(self
.CreateField (Item
, Name
, Item
["offset"] - ResvOffset
, ResvOffset
, '', '', '', ''))
1140 if Offset
< Item
["offset"]:
1142 Name
= "Unused" + Region
[0] + "pdSpace%d" % SpaceIdx
1143 LineBuffer
.append(self
.CreateField (Item
, Name
, Item
["offset"] - Offset
, Offset
, '', '', '', ''))
1144 SpaceIdx
= SpaceIdx
+ 1
1145 Offset
= Item
["offset"]
1147 LastVisible
= NextVisible
1149 Offset
= Offset
+ Item
["length"]
1151 for Each
in LineBuffer
:
1152 TxtBody
.append (Each
)
1154 Comment
= Item
["comment"]
1155 Embed
= Item
["embed"].upper()
1156 if Embed
.endswith(':START') or Embed
.endswith(':END'):
1157 if not Comment
== '' and Embed
.endswith(':START'):
1158 Marker
= '/* COMMENT:%s */ \n' % Item
["comment"]
1159 Marker
= Marker
+ '/* EMBED_STRUCT:%s */ ' % Item
["embed"]
1161 Marker
= '/* EMBED_STRUCT:%s */ ' % Item
["embed"]
1166 self
.Error
= "Invalid embedded structure format '%s'!\n" % Item
["embed"]
1168 Line
= Marker
+ self
.CreateField (Item
, Item
["cname"], Item
["length"], Item
["offset"], Item
['struct'], Item
['name'], Item
['help'], Item
['option'])
1169 TxtBody
.append(Line
)
1170 if Item
['cname'] == 'UpdTerminator':
1172 TxtBody
.append("} " + UpdStructure
[UpdIdx
] + ";\n\n")
1174 # Handle the embedded data structure
1175 TxtBody
= self
.PostProcessBody (TxtBody
)
1177 HeaderTFileName
= 'FsptUpd.h'
1178 HeaderMFileName
= 'FspmUpd.h'
1179 HeaderSFileName
= 'FspsUpd.h'
1181 UpdRegionCheck
= ['FSPT', 'FSPM', 'FSPS'] # FSPX_UPD_REGION
1182 UpdConfigCheck
= ['FSP_T', 'FSP_M', 'FSP_S'] # FSP_X_CONFIG, FSP_X_TEST_CONFIG, FSP_X_RESTRICTED_CONFIG
1183 UpdSignatureCheck
= ['FSPT_UPD_SIGNATURE', 'FSPM_UPD_SIGNATURE', 'FSPS_UPD_SIGNATURE']
1184 ExcludedSpecificUpd
= ['FSPT_ARCH_UPD', 'FSPM_ARCH_UPD', 'FSPS_ARCH_UPD']
1187 if InputHeaderFile
!= '':
1188 if not os
.path
.exists(InputHeaderFile
):
1189 self
.Error
= "Input header file '%s' does not exist" % InputHeaderFile
1192 InFd
= open(InputHeaderFile
, "r")
1193 IncLines
= InFd
.readlines()
1196 for item
in range(len(UpdRegionCheck
)):
1197 if UpdRegionCheck
[item
] == 'FSPT':
1198 HeaderFd
= open(os
.path
.join(FvDir
, HeaderTFileName
), "w")
1199 FileBase
= os
.path
.basename(os
.path
.join(FvDir
, HeaderTFileName
))
1200 elif UpdRegionCheck
[item
] == 'FSPM':
1201 HeaderFd
= open(os
.path
.join(FvDir
, HeaderMFileName
), "w")
1202 FileBase
= os
.path
.basename(os
.path
.join(FvDir
, HeaderMFileName
))
1203 elif UpdRegionCheck
[item
] == 'FSPS':
1204 HeaderFd
= open(os
.path
.join(FvDir
, HeaderSFileName
), "w")
1205 FileBase
= os
.path
.basename(os
.path
.join(FvDir
, HeaderSFileName
))
1206 FileName
= FileBase
.replace(".", "_").upper()
1207 HeaderFd
.write("%s\n" % (__copyright_h__
% date
.today().year
))
1208 HeaderFd
.write("#ifndef __%s__\n" % FileName
)
1209 HeaderFd
.write("#define __%s__\n\n" % FileName
)
1210 HeaderFd
.write("#include <%s>\n\n" % HeaderFileName
)
1211 HeaderFd
.write("#pragma pack(1)\n\n")
1214 for Line
in IncLines
:
1215 Match
= re
.search ("!EXPORT\s+([A-Z]+)\s+EXTERNAL_BOOTLOADER_STRUCT_(BEGIN|END)\s+", Line
)
1217 if Match
.group(2) == "BEGIN" and Match
.group(1) == UpdRegionCheck
[item
]:
1224 HeaderFd
.write(Line
)
1225 HeaderFd
.write("\n")
1231 StructStartWithComment
= []
1233 for Line
in TxtBody
:
1235 Match
= re
.match("(typedef struct {)", Line
)
1237 StartIndex
= Index
- 1
1238 Match
= re
.match("}\s([_A-Z0-9]+);", Line
)
1239 if Match
and (UpdRegionCheck
[item
] in Match
.group(1) or UpdConfigCheck
[item
] in Match
.group(1)) and (ExcludedSpecificUpd
[item
] not in Match
.group(1)):
1241 StructStart
.append(StartIndex
)
1242 StructEnd
.append(EndIndex
)
1244 for Line
in TxtBody
:
1246 for Item
in range(len(StructStart
)):
1247 if Index
== StructStart
[Item
]:
1248 Match
= re
.match("^(/\*\*\s*)", Line
)
1250 StructStartWithComment
.append(StructStart
[Item
])
1252 StructStartWithComment
.append(StructStart
[Item
] + 1)
1254 for Line
in TxtBody
:
1256 for Item
in range(len(StructStart
)):
1257 if Index
>= StructStartWithComment
[Item
] and Index
<= StructEnd
[Item
]:
1258 self
.WriteLinesWithoutTailingSpace(HeaderFd
, Line
)
1259 HeaderFd
.write("#pragma pack()\n\n")
1260 HeaderFd
.write("#endif\n")
1263 HeaderFd
= open(HeaderFile
, "w")
1264 FileBase
= os
.path
.basename(HeaderFile
)
1265 FileName
= FileBase
.replace(".", "_").upper()
1266 HeaderFd
.write("%s\n" % (__copyright_h__
% date
.today().year
))
1267 HeaderFd
.write("#ifndef __%s__\n" % FileName
)
1268 HeaderFd
.write("#define __%s__\n\n" % FileName
)
1269 HeaderFd
.write("#include <FspEas.h>\n\n")
1270 HeaderFd
.write("#pragma pack(1)\n\n")
1272 for item
in range(len(UpdRegionCheck
)):
1277 StructStartWithComment
= []
1279 for Line
in TxtBody
:
1281 Match
= re
.match("(typedef struct {)", Line
)
1283 StartIndex
= Index
- 1
1284 Match
= re
.match("#define\s([_A-Z0-9]+)\s*", Line
)
1285 if Match
and (UpdSignatureCheck
[item
] in Match
.group(1) or UpdSignatureCheck
[item
] in Match
.group(1)):
1286 StructStart
.append(Index
- 1)
1287 StructEnd
.append(Index
)
1289 for Line
in TxtBody
:
1291 for Item
in range(len(StructStart
)):
1292 if Index
== StructStart
[Item
]:
1293 Match
= re
.match("^(/\*\*\s*)", Line
)
1295 StructStartWithComment
.append(StructStart
[Item
])
1297 StructStartWithComment
.append(StructStart
[Item
] + 1)
1299 for Line
in TxtBody
:
1301 for Item
in range(len(StructStart
)):
1302 if Index
>= StructStartWithComment
[Item
] and Index
<= StructEnd
[Item
]:
1303 self
.WriteLinesWithoutTailingSpace(HeaderFd
, Line
)
1304 HeaderFd
.write("#pragma pack()\n\n")
1305 HeaderFd
.write("#endif\n")
1310 def WriteBsfStruct (self
, BsfFd
, Item
):
1311 LogExpr
= CLogicalExpression()
1312 if Item
['type'] == "None":
1313 Space
= "gPlatformFspPkgTokenSpaceGuid"
1315 Space
= Item
['space']
1316 Line
= " $%s_%s" % (Space
, Item
['cname'])
1317 Match
= re
.match("\s*\{([x0-9a-fA-F,\s]+)\}\s*", Item
['value'])
1319 DefaultValue
= Match
.group(1).strip()
1321 DefaultValue
= Item
['value'].strip()
1322 if 'bitlength' in Item
:
1323 BsfFd
.write(" %s%s%4d bits $_DEFAULT_ = %s\n" % (Line
, ' ' * (64 - len(Line
)), Item
['bitlength'], DefaultValue
))
1325 BsfFd
.write(" %s%s%4d bytes $_DEFAULT_ = %s\n" % (Line
, ' ' * (64 - len(Line
)), Item
['length'], DefaultValue
))
1327 if Item
['type'] == "Combo":
1328 if not Item
['option'] in self
._BuidinOption
:
1329 OptList
= Item
['option'].split(',')
1330 for Option
in OptList
:
1331 Option
= Option
.strip()
1332 (OpVal
, OpStr
) = Option
.split(':')
1333 test
= LogExpr
.getNumber (OpVal
)
1335 raise Exception("Selection Index '%s' is not a number" % OpVal
)
1336 TmpList
.append((OpVal
, OpStr
))
1339 def WriteBsfOption (self
, BsfFd
, Item
):
1340 PcdName
= Item
['space'] + '_' + Item
['cname']
1342 if Item
['type'] == "Combo":
1343 if Item
['option'] in self
._BuidinOption
:
1344 Options
= self
._BuidinOption
[Item
['option']]
1347 BsfFd
.write(' %s $%s, "%s", &%s,\n' % (Item
['type'], PcdName
, Item
['name'], Options
))
1349 elif Item
['type'].startswith("EditNum"):
1350 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'])
1352 BsfFd
.write(' EditNum $%s, "%s", %s,\n' % (PcdName
, Item
['name'], Match
.group(1)))
1354 elif Item
['type'].startswith("EditText"):
1355 BsfFd
.write(' %s $%s, "%s",\n' % (Item
['type'], PcdName
, Item
['name']))
1357 elif Item
['type'] == "Table":
1358 Columns
= Item
['option'].split(',')
1359 if len(Columns
) != 0:
1360 BsfFd
.write(' %s $%s "%s",' % (Item
['type'], PcdName
, Item
['name']))
1362 Fmt
= Col
.split(':')
1364 raise Exception("Column format '%s' is invalid !" % Fmt
)
1366 Dtype
= int(Fmt
[1].strip())
1368 raise Exception("Column size '%s' is invalid !" % Fmt
[1])
1369 BsfFd
.write('\n Column "%s", %d bytes, %s' % (Fmt
[0].strip(), Dtype
, Fmt
[2].strip()))
1374 HelpLines
= Item
['help'].split('\\n\\r')
1376 for HelpLine
in HelpLines
:
1379 BsfFd
.write(' Help "%s"\n' % (HelpLine
))
1381 BsfFd
.write(' "%s"\n' % (HelpLine
))
1383 BsfFd
.write(' "Valid range: %s ~ %s"\n' % (Match
.group(2), Match
.group(3)))
1385 def GenerateBsfFile (self
, BsfFile
):
1388 self
.Error
= "BSF output file '%s' is invalid" % BsfFile
1391 if (self
.NoDscFileChange (BsfFile
)):
1392 # DSC has not been modified yet
1393 # So don't have to re-generate other files
1394 self
.Error
= 'No DSC file change, skip to create UPD BSF file'
1399 BsfFd
= open(BsfFile
, "w")
1400 BsfFd
.write("%s\n" % (__copyright_bsf__
% date
.today().year
))
1401 BsfFd
.write("%s\n" % self
._GlobalDataDef
)
1402 BsfFd
.write("StructDef\n")
1404 for Item
in self
._CfgItemList
:
1405 if Item
['find'] != '':
1406 BsfFd
.write('\n Find "%s"\n' % Item
['find'])
1407 NextOffset
= Item
['offset'] + Item
['length']
1408 if Item
['name'] != '':
1409 if NextOffset
!= Item
['offset']:
1410 BsfFd
.write(" Skip %d bytes\n" % (Item
['offset'] - NextOffset
))
1411 if len(Item
['subreg']) > 0:
1412 NextOffset
= Item
['offset']
1413 BitsOffset
= NextOffset
* 8
1414 for SubItem
in Item
['subreg']:
1415 BitsOffset
+= SubItem
['bitlength']
1416 if SubItem
['name'] == '':
1417 if 'bitlength' in SubItem
:
1418 BsfFd
.write(" Skip %d bits\n" % (SubItem
['bitlength']))
1420 BsfFd
.write(" Skip %d bytes\n" % (SubItem
['length']))
1422 Options
= self
.WriteBsfStruct(BsfFd
, SubItem
)
1423 if len(Options
) > 0:
1424 OptionDict
[SubItem
['space']+'_'+SubItem
['cname']] = Options
1426 NextBitsOffset
= (Item
['offset'] + Item
['length']) * 8
1427 if NextBitsOffset
> BitsOffset
:
1428 BitsGap
= NextBitsOffset
- BitsOffset
1429 BitsRemain
= BitsGap
% 8
1431 BsfFd
.write(" Skip %d bits\n" % BitsRemain
)
1432 BitsGap
-= BitsRemain
1433 BytesRemain
= int(BitsGap
/ 8)
1435 BsfFd
.write(" Skip %d bytes\n" % BytesRemain
)
1436 NextOffset
= Item
['offset'] + Item
['length']
1438 NextOffset
= Item
['offset'] + Item
['length']
1439 Options
= self
.WriteBsfStruct(BsfFd
, Item
)
1440 if len(Options
) > 0:
1441 OptionDict
[Item
['space']+'_'+Item
['cname']] = Options
1442 BsfFd
.write("\nEndStruct\n\n")
1444 BsfFd
.write("%s" % self
._BuidinOptionTxt
)
1446 for Each
in OptionDict
:
1447 BsfFd
.write("List &%s\n" % Each
)
1448 for Item
in OptionDict
[Each
]:
1449 BsfFd
.write(' Selection %s , "%s"\n' % (Item
[0], Item
[1]))
1450 BsfFd
.write("EndList\n\n")
1452 BsfFd
.write("BeginInfoBlock\n")
1453 BsfFd
.write(' PPVer "%s"\n' % (self
._CfgBlkDict
['ver']))
1454 BsfFd
.write(' Description "%s"\n' % (self
._CfgBlkDict
['name']))
1455 BsfFd
.write("EndInfoBlock\n\n")
1457 for Each
in self
._CfgPageDict
:
1458 BsfFd
.write('Page "%s"\n' % self
._CfgPageDict
[Each
])
1460 for Item
in self
._CfgItemList
:
1461 if Item
['name'] != '':
1462 if Item
['page'] != Each
:
1464 if len(Item
['subreg']) > 0:
1465 for SubItem
in Item
['subreg']:
1466 if SubItem
['name'] != '':
1467 BsfItems
.append(SubItem
)
1469 BsfItems
.append(Item
)
1471 BsfItems
.sort(key
=lambda x
: x
['order'])
1473 for Item
in BsfItems
:
1474 self
.WriteBsfOption (BsfFd
, Item
)
1475 BsfFd
.write("EndPage\n\n")
1482 print ("GenCfgOpt Version 0.56")
1484 print (" GenCfgOpt UPDTXT PlatformDscFile BuildFvDir [-D Macros]")
1485 print (" GenCfgOpt HEADER PlatformDscFile BuildFvDir InputHFile [-D Macros]")
1486 print (" GenCfgOpt GENBSF PlatformDscFile BuildFvDir BsfOutFile [-D Macros]")
1490 # Parse the options and args
1494 GenCfgOpt
= CGenCfgOpt()
1495 while i
< len(sys
.argv
):
1496 if sys
.argv
[i
].strip().lower() == "--pcd":
1497 BuildOptionPcd
.append(sys
.argv
[i
+1])
1500 argc
= len(sys
.argv
)
1505 DscFile
= sys
.argv
[2]
1506 if not os
.path
.exists(DscFile
):
1507 print ("ERROR: Cannot open DSC file '%s' !" % DscFile
)
1512 if sys
.argv
[4][0] == '-':
1515 OutFile
= sys
.argv
[4]
1518 if GenCfgOpt
.ParseMacros(sys
.argv
[Start
:]) != 0:
1519 print ("ERROR: Macro parsing failed !")
1523 if not os
.path
.exists(FvDir
):
1526 if GenCfgOpt
.ParseDscFile(DscFile
, FvDir
) != 0:
1527 print ("ERROR: %s !" % GenCfgOpt
.Error
)
1530 if GenCfgOpt
.UpdateSubRegionDefaultValue() != 0:
1531 print ("ERROR: %s !" % GenCfgOpt
.Error
)
1534 if sys
.argv
[1] == "UPDTXT":
1535 Ret
= GenCfgOpt
.CreateSplitUpdTxt(OutFile
)
1537 # No change is detected
1539 print ("INFO: %s !" % (GenCfgOpt
.Error
))
1541 print ("ERROR: %s !" % (GenCfgOpt
.Error
))
1543 elif sys
.argv
[1] == "HEADER":
1544 Ret
= GenCfgOpt
.CreateHeaderFile(OutFile
)
1546 # No change is detected
1548 print ("INFO: %s !" % (GenCfgOpt
.Error
))
1550 print ("ERROR: %s !" % (GenCfgOpt
.Error
))
1553 elif sys
.argv
[1] == "GENBSF":
1554 Ret
= GenCfgOpt
.GenerateBsfFile(OutFile
)
1556 # No change is detected
1558 print ("INFO: %s !" % (GenCfgOpt
.Error
))
1560 print ("ERROR: %s !" % (GenCfgOpt
.Error
))
1567 print ("ERROR: Unknown command '%s' !" % sys
.argv
[1])
1574 if __name__
== '__main__':