]>
git.proxmox.com Git - mirror_edk2.git/blob - IntelFsp2Pkg/Tools/GenCfgOpt.py
a0b8bba81e6ba46d7be799538329b9ce686a1d7d
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
= []
318 def ParseMacros (self
, MacroDefStr
):
319 # ['-DABC=1', '-D', 'CFG_DEBUG=1', '-D', 'CFG_OUTDIR=Build']
322 for Macro
in MacroDefStr
:
323 if Macro
.startswith('-D'):
331 Match
= re
.match("(\w+)=(.+)", Macro
)
333 self
._MacroDict
[Match
.group(1)] = Match
.group(2)
335 Match
= re
.match("(\w+)", Macro
)
337 self
._MacroDict
[Match
.group(1)] = ''
338 if len(self
._MacroDict
) == 0:
343 print ("INFO : Macro dictionary:")
344 for Each
in self
._MacroDict
:
345 print (" $(%s) = [ %s ]" % (Each
, self
._MacroDict
[Each
]))
348 def EvaulateIfdef (self
, Macro
):
349 Result
= Macro
in self
._MacroDict
351 print ("INFO : Eval Ifdef [%s] : %s" % (Macro
, Result
))
354 def ExpandMacros (self
, Input
):
356 Match
= re
.findall("\$\(\w+\)", Input
)
359 Variable
= Each
[2:-1]
360 if Variable
in self
._MacroDict
:
361 Line
= Line
.replace(Each
, self
._MacroDict
[Variable
])
364 print ("WARN : %s is not defined" % Each
)
365 Line
= Line
.replace(Each
, Each
[2:-1])
368 def ExpandPcds (self
, Input
):
370 Match
= re
.findall("(\w+\.\w+)", Input
)
372 for PcdName
in Match
:
373 if PcdName
in self
._PcdsDict
:
374 Line
= Line
.replace(PcdName
, self
._PcdsDict
[PcdName
])
377 print ("WARN : %s is not defined" % PcdName
)
380 def EvaluateExpress (self
, Expr
):
381 ExpExpr
= self
.ExpandPcds(Expr
)
382 ExpExpr
= self
.ExpandMacros(ExpExpr
)
383 LogExpr
= CLogicalExpression()
384 Result
= LogExpr
.evaluateExpress (ExpExpr
)
386 print ("INFO : Eval Express [%s] : %s" % (Expr
, Result
))
389 def FormatListValue(self
, ConfigDict
):
390 Struct
= ConfigDict
['struct']
391 if Struct
not in ['UINT8','UINT16','UINT32','UINT64']:
395 binlist
= ConfigDict
['value'][1:-1].split(',')
398 if each
.startswith('0x'):
399 value
= int(each
, 16)
402 dataarray
.append(value
)
404 unit
= int(Struct
[4:]) / 8
405 if int(ConfigDict
['length']) != unit
* len(dataarray
):
406 raise Exception("Array size is not proper for '%s' !" % ConfigDict
['cname'])
409 for each
in dataarray
:
411 for loop
in range(int(unit
)):
412 bytearray
.append("0x%02X" % (value
& 0xFF))
414 newvalue
= '{' + ','.join(bytearray
) + '}'
415 ConfigDict
['value'] = newvalue
418 def ParseDscFile (self
, DscFile
, FvDir
):
421 self
._CfgItemList
= []
422 self
._CfgPageDict
= {}
423 self
._CfgBlkDict
= {}
424 self
._DscFile
= DscFile
427 # Initial DSC time is parent DSC time.
428 self
._DscTime
= os
.path
.getmtime(DscFile
)
440 DscFd
= open(DscFile
, "r")
441 DscLines
= DscFd
.readlines()
444 MaxAlign
= 32 #Default align to 32, but if there are 64 bit unit, align to 64
445 SizeAlign
= 0 #record the struct max align
446 Base
= 0 #Starting offset of sub-structure.
448 DscLine
= DscLines
.pop(0).strip()
450 Match
= re
.match("^\[(.+)\]", DscLine
)
451 if Match
is not None:
456 if Match
.group(1).lower() == "Defines".lower():
458 if (Match
.group(1).lower() == "PcdsFeatureFlag".lower() or Match
.group(1).lower() == "PcdsFixedAtBuild".lower()):
460 elif Match
.group(1).lower() == "PcdsDynamicVpd.Upd".lower():
462 ConfigDict
['header'] = 'ON'
463 ConfigDict
['region'] = 'UPD'
464 ConfigDict
['order'] = -1
465 ConfigDict
['page'] = ''
466 ConfigDict
['name'] = ''
467 ConfigDict
['find'] = ''
468 ConfigDict
['struct'] = ''
469 ConfigDict
['embed'] = ''
470 ConfigDict
['comment'] = ''
471 ConfigDict
['subreg'] = []
475 if IsDefSect
or IsPcdSect
or IsUpdSect
or IsVpdSect
:
476 if re
.match("^!else($|\s+#.+)", DscLine
):
478 IfStack
[-1] = not IfStack
[-1]
480 print("ERROR: No paired '!if' found for '!else' for line '%s'" % DscLine
)
482 elif re
.match("^!endif($|\s+#.+)", DscLine
):
485 Level
= ElifStack
.pop()
489 print("ERROR: No paired '!if' found for '!endif' for line '%s'" % DscLine
)
493 Match
= re
.match("!(ifdef|ifndef)\s+(.+)", DscLine
)
495 Result
= self
.EvaulateIfdef (Match
.group(2))
496 if Match
.group(1) == 'ifndef':
498 IfStack
.append(Result
)
501 Match
= re
.match("!(if|elseif)\s+(.+)", DscLine
.split("#")[0])
503 Result
= self
.EvaluateExpress(Match
.group(2))
504 if Match
.group(1) == "if":
506 IfStack
.append(Result
)
509 IfStack
[-1] = not IfStack
[-1]
510 IfStack
.append(Result
)
511 ElifStack
[-1] = ElifStack
[-1] + 1
513 print("ERROR: No paired '!if' found for '!elif' for line '%s'" % DscLine
)
517 Handle
= reduce(lambda x
,y
: x
and y
, IfStack
)
521 Match
= re
.match("!include\s+(.+)", DscLine
)
523 IncludeFilePath
= Match
.group(1)
524 IncludeFilePath
= self
.ExpandMacros(IncludeFilePath
)
525 PackagesPath
= os
.getenv("PACKAGES_PATH")
527 for PackagePath
in PackagesPath
.split(os
.pathsep
):
528 IncludeFilePathAbs
= os
.path
.join(os
.path
.normpath(PackagePath
), os
.path
.normpath(IncludeFilePath
))
529 if os
.path
.exists(IncludeFilePathAbs
):
530 IncludeDsc
= open(IncludeFilePathAbs
, "r")
533 IncludeDsc
= open(IncludeFilePath
, "r")
534 if IncludeDsc
== None:
535 print("ERROR: Cannot open file '%s'" % IncludeFilePath
)
538 # Update DscTime when newer DSC time found.
539 CurrentDscTime
= os
.path
.getmtime(os
.path
.realpath(IncludeDsc
.name
))
540 if CurrentDscTime
> self
._DscTime
:
541 self
._DscTime
= CurrentDscTime
543 NewDscLines
= IncludeDsc
.readlines()
545 DscLines
= NewDscLines
+ DscLines
548 if DscLine
.startswith('!'):
549 print("ERROR: Unrecognized directive for line '%s'" % DscLine
)
555 #DEFINE UPD_TOOL_GUID = 8C3D856A-9BE6-468E-850A-24F7A8D38E09
556 #DEFINE FSP_T_UPD_TOOL_GUID = 34686CA3-34F9-4901-B82A-BA630F0714C6
557 #DEFINE FSP_M_UPD_TOOL_GUID = 39A250DB-E465-4DD1-A2AC-E2BD3C0E2385
558 #DEFINE FSP_S_UPD_TOOL_GUID = CAE3605B-5B34-4C85-B3D7-27D54273C40F
559 Match
= re
.match("^\s*(?:DEFINE\s+)*(\w+)\s*=\s*([/$()-.\w]+)", DscLine
)
561 self
._MacroDict
[Match
.group(1)] = self
.ExpandMacros(Match
.group(2))
563 print ("INFO : DEFINE %s = [ %s ]" % (Match
.group(1), self
.ExpandMacros(Match
.group(2))))
565 #gSiPkgTokenSpaceGuid.PcdTxtEnable|FALSE
566 #gSiPkgTokenSpaceGuid.PcdOverclockEnable|TRUE
567 Match
= re
.match("^\s*([\w\.]+)\s*\|\s*(\w+)", DscLine
)
569 self
._PcdsDict
[Match
.group(1)] = Match
.group(2)
571 print ("INFO : PCD %s = [ %s ]" % (Match
.group(1), Match
.group(2)))
573 while i
< len(BuildOptionPcd
):
574 Match
= re
.match("\s*([\w\.]+)\s*\=\s*(\w+)", BuildOptionPcd
[i
])
576 self
._PcdsDict
[Match
.group(1)] = Match
.group(2)
579 Match
= re
.match("^\s*#\s+(!BSF|@Bsf|!HDR)\s+(.+)", DscLine
)
581 Remaining
= Match
.group(2)
582 if Match
.group(1) == '!BSF' or Match
.group(1) == '@Bsf':
583 Match
= re
.match("(?:^|.+\s+)PAGES:{(.+?)}", Remaining
)
585 # !BSF PAGES:{HSW:"Haswell System Agent", LPT:"Lynx Point PCH"}
586 PageList
= Match
.group(1).split(',')
587 for Page
in PageList
:
589 Match
= re
.match("(\w+):\"(.+)\"", Page
)
590 self
._CfgPageDict
[Match
.group(1)] = Match
.group(2)
592 Match
= re
.match("(?:^|.+\s+)BLOCK:{NAME:\"(.+)\"\s*,\s*VER:\"(.+)\"\s*}", Remaining
)
594 self
._CfgBlkDict
['name'] = Match
.group(1)
595 self
._CfgBlkDict
['ver'] = Match
.group(2)
597 for Key
in self
._BsfKeyList
:
598 Match
= re
.match("(?:^|.+\s+)%s:{(.+?)}" % Key
, Remaining
)
600 if Key
in ['NAME', 'HELP', 'OPTION'] and Match
.group(1).startswith('+'):
601 ConfigDict
[Key
.lower()] += Match
.group(1)[1:]
603 ConfigDict
[Key
.lower()] = Match
.group(1)
605 for Key
in self
._HdrKeyList
:
606 Match
= re
.match("(?:^|.+\s+)%s:{(.+?)}" % Key
, Remaining
)
608 ConfigDict
[Key
.lower()] = Match
.group(1)
610 Match
= re
.match("^\s*#\s+@Prompt\s+(.+)", DscLine
)
612 ConfigDict
['name'] = Match
.group(1)
614 Match
= re
.match("^\s*#\s*@ValidList\s*(.+)\s*\|\s*(.+)\s*\|\s*(.+)\s*", DscLine
)
616 if Match
.group(2).strip() in self
._BuidinOption
:
617 ConfigDict
['option'] = Match
.group(2).strip()
619 OptionValueList
= Match
.group(2).split(',')
620 OptionStringList
= Match
.group(3).split(',')
622 for Option
in OptionValueList
:
623 Option
= Option
.strip()
624 ConfigDict
['option'] = ConfigDict
['option'] + str(Option
) + ':' + OptionStringList
[Index
].strip()
626 if Index
in range(len(OptionValueList
)):
627 ConfigDict
['option'] += ', '
628 ConfigDict
['type'] = "Combo"
630 Match
= re
.match("^\s*#\s*@ValidRange\s*(.+)\s*\|\s*(.+)\s*-\s*(.+)\s*", DscLine
)
632 if "0x" in Match
.group(2) or "0x" in Match
.group(3):
633 ConfigDict
['type'] = "EditNum, HEX, (%s,%s)" % (Match
.group(2), Match
.group(3))
635 ConfigDict
['type'] = "EditNum, DEC, (%s,%s)" % (Match
.group(2), Match
.group(3))
637 Match
= re
.match("^\s*##\s+(.+)", DscLine
)
639 ConfigDict
['help'] = Match
.group(1)
643 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
)
645 Match
= re
.match("^([_a-zA-Z0-9]+).([_a-zA-Z0-9]+)\s*\|\s*(0x[0-9A-F]+)(?:\s*\|\s*(.+))?", DscLine
)
647 ConfigDict
['space'] = Match
.group(1)
648 ConfigDict
['cname'] = Match
.group(2)
649 if Match
.group(3) != '*':
651 Offset
= int (Match
.group(3), 16)
655 if Hardcode
and AutoAlign
:
656 print("Hardcode and auto-align mixed mode is not supported by GenCfgOpt")
658 ConfigDict
['offset'] = Offset
659 if ConfigDict
['order'] == -1:
660 ConfigDict
['order'] = ConfigDict
['offset'] << 8
662 (Major
, Minor
) = ConfigDict
['order'].split('.')
663 ConfigDict
['order'] = (int (Major
, 16) << 8 ) + int (Minor
, 16)
665 Value
= Match
.group(5).strip()
666 if Match
.group(4).startswith("0x"):
667 Length
= int (Match
.group(4), 16)
669 Length
= int (Match
.group(4))
672 Value
= Match
.group(4)
675 Value
= Value
.strip()
677 Match
= re
.match("^.+\s*\|\s*(.+)", Value
)
679 Value
= Match
.group(1)
682 ConfigDict
['length'] = Length
683 Match
= re
.match("\$\((\w+)\)", Value
)
685 if Match
.group(1) in self
._MacroDict
:
686 Value
= self
._MacroDict
[Match
.group(1)]
688 ConfigDict
['value'] = Value
689 if (len(Value
) > 0) and (Value
[0] == '{'):
690 Value
= self
.FormatListValue(ConfigDict
)
692 if ConfigDict
['name'] == '':
693 # Clear BSF specific items
694 ConfigDict
['bsfname'] = ''
695 ConfigDict
['help'] = ''
696 ConfigDict
['type'] = ''
697 ConfigDict
['option'] = ''
698 if IsUpdSect
and AutoAlign
:
699 ItemLength
= int(ConfigDict
['length'])
700 ItemOffset
= int(ConfigDict
['offset'])
701 ItemStruct
= ConfigDict
['struct']
703 if ItemLength
in [1, 2, 4, 8] and not ConfigDict
['value'].startswith('{'):
705 # If there are 64 bit unit, align to 64
710 UnitDict
= {'UINT8':1, 'UINT16':2, 'UINT32':4, 'UINT64':8}
711 if ItemStruct
in ['UINT8', 'UINT16', 'UINT32', 'UINT64']:
712 Unit
= UnitDict
[ItemStruct
]
713 # If there are 64 bit unit, align to 64
716 SizeAlign
= max(SizeAlign
, Unit
)
717 if (ConfigDict
['embed'].find(':START') != -1):
719 SubOffset
= ItemOffset
- Base
720 SubRemainder
= SubOffset
% Unit
722 Diff
= Unit
- SubRemainder
723 Offset
= Offset
+ Diff
724 ItemOffset
= ItemOffset
+ Diff
726 if (ConfigDict
['embed'].find(':END') != -1):
727 Remainder
= Offset
% (MaxAlign
/8) # MaxAlign is either 32 or 64
729 Diff
= int((MaxAlign
/8) - Remainder
)
730 Offset
= Offset
+ Diff
731 ItemOffset
= ItemOffset
+ Diff
732 MaxAlign
= 32 # Reset to default 32 align when struct end
733 if (ConfigDict
['cname'] == 'UpdTerminator'):
734 # ItemLength is the size of UpdTerminator
735 # Itemlength might be 16, 32, or 64
736 # Struct align to 64 if UpdTerminator
737 # or struct size is 64 bit, else align to 32
738 Remainder
= Offset
% max(ItemLength
/8, 4, SizeAlign
)
739 Offset
= Offset
+ ItemLength
741 Diff
= int(max(ItemLength
/8, 4, SizeAlign
) - Remainder
)
742 ItemOffset
= ItemOffset
+ Diff
743 ConfigDict
['offset'] = ItemOffset
745 self
._CfgItemList
.append(ConfigDict
.copy())
746 ConfigDict
['name'] = ''
747 ConfigDict
['find'] = ''
748 ConfigDict
['struct'] = ''
749 ConfigDict
['embed'] = ''
750 ConfigDict
['comment'] = ''
751 ConfigDict
['order'] = -1
752 ConfigDict
['subreg'] = []
753 ConfigDict
['option'] = ''
755 # It could be a virtual item as below
756 # !BSF FIELD:{SerialDebugPortAddress0:1}
758 # @Bsf FIELD:{SerialDebugPortAddress0:1b}
759 Match
= re
.match("^\s*#\s+(!BSF|@Bsf)\s+FIELD:{(.+):(\d+)([Bb])?}", DscLine
)
761 SubCfgDict
= ConfigDict
.copy()
762 if (Match
.group(4) == None) or (Match
.group(4) == 'B'):
764 elif Match
.group(4) == 'b':
767 print("ERROR: Invalide BSF FIELD length for line '%s'" % DscLine
)
769 SubCfgDict
['cname'] = Match
.group(2)
770 SubCfgDict
['bitlength'] = int (Match
.group(3)) * UnitBitLen
771 if SubCfgDict
['bitlength'] > 0:
772 LastItem
= self
._CfgItemList
[-1]
773 if len(LastItem
['subreg']) == 0:
776 SubOffset
= LastItem
['subreg'][-1]['bitoffset'] + LastItem
['subreg'][-1]['bitlength']
777 SubCfgDict
['bitoffset'] = SubOffset
778 LastItem
['subreg'].append (SubCfgDict
.copy())
779 ConfigDict
['name'] = ''
782 def GetBsfBitFields (self
, subitem
, bytes
):
783 start
= subitem
['bitoffset']
784 end
= start
+ subitem
['bitlength']
785 bitsvalue
= ''.join('{0:08b}'.format(i
) for i
in bytes
[::-1])
786 bitsvalue
= bitsvalue
[::-1]
787 bitslen
= len(bitsvalue
)
788 if start
> bitslen
or end
> bitslen
:
789 print ("Invalid bits offset [%d,%d] for %s" % (start
, end
, subitem
['name']))
791 return hex(int(bitsvalue
[start
:end
][::-1], 2))
793 def UpdateSubRegionDefaultValue (self
):
795 for Item
in self
._CfgItemList
:
796 if len(Item
['subreg']) == 0:
799 if Item
['value'][0] == '{':
800 binlist
= Item
['value'][1:-1].split(',')
803 if each
.startswith('0x'):
804 value
= int(each
, 16)
807 bytearray
.append(value
)
809 if Item
['value'].startswith('0x'):
810 value
= int(Item
['value'], 16)
812 value
= int(Item
['value'])
814 while idx
< Item
['length']:
815 bytearray
.append(value
& 0xFF)
818 for SubItem
in Item
['subreg']:
819 valuestr
= self
.GetBsfBitFields(SubItem
, bytearray
)
820 SubItem
['value'] = valuestr
823 def NoDscFileChange (self
, OutPutFile
):
825 if not os
.path
.exists(OutPutFile
):
828 OutputTime
= os
.path
.getmtime(OutPutFile
)
829 if self
._DscTime
> OutputTime
:
833 def CreateSplitUpdTxt (self
, UpdTxtFile
):
834 GuidList
= ['FSP_T_UPD_TOOL_GUID','FSP_M_UPD_TOOL_GUID','FSP_S_UPD_TOOL_GUID']
835 SignatureList
= ['0x545F', '0x4D5F','0x535F'] # _T, _M, and _S signature for FSPT, FSPM, FSPS
836 for Index
in range(len(GuidList
)):
839 if GuidList
[Index
] not in self
._MacroDict
:
840 self
.Error
= "%s definition is missing in DSC file" % (GuidList
[Index
])
844 UpdTxtFile
= os
.path
.join(FvDir
, self
._MacroDict
[GuidList
[Index
]] + '.txt')
846 if (self
.NoDscFileChange (UpdTxtFile
)):
847 # DSC has not been modified yet
848 # So don't have to re-generate other files
849 self
.Error
= 'No DSC file change, skip to create UPD TXT file'
852 TxtFd
= open(UpdTxtFile
, "w")
853 TxtFd
.write("%s\n" % (__copyright_txt__
% date
.today().year
))
861 for Item
in self
._CfgItemList
:
862 if Item
['cname'] == 'Signature' and str(Item
['value'])[0:6] == SignatureList
[Index
]:
863 StartAddr
= Item
['offset']
864 NextOffset
= StartAddr
866 if Item
['cname'] == 'UpdTerminator' and InRange
== True:
867 EndAddr
= Item
['offset']
870 for Item
in self
._CfgItemList
:
871 if Item
['cname'] == 'Signature' and str(Item
['value'])[0:6] == SignatureList
[Index
]:
875 if Item
['cname'] == 'UpdTerminator':
877 if Item
['region'] != 'UPD':
879 Offset
= Item
['offset']
880 if StartAddr
> Offset
or EndAddr
< Offset
:
882 if NextOffset
< Offset
:
884 TxtFd
.write("%s.UnusedUpdSpace%d|%s0x%04X|0x%04X|{0}\n" % (Item
['space'], SpaceIdx
, Default
, NextOffset
- StartAddr
, Offset
- NextOffset
))
885 SpaceIdx
= SpaceIdx
+ 1
886 NextOffset
= Offset
+ Item
['length']
887 TxtFd
.write("%s.%s|%s0x%04X|%s|%s\n" % (Item
['space'],Item
['cname'],Default
,Item
['offset'] - StartAddr
,Item
['length'],Item
['value']))
891 def ProcessMultilines (self
, String
, MaxCharLength
):
893 StringLength
= len(String
)
894 CurrentStringStart
= 0
897 if len(String
) <= MaxCharLength
:
898 while (StringOffset
< StringLength
):
899 if StringOffset
>= 1:
900 if String
[StringOffset
- 1] == '\\' and String
[StringOffset
] == 'n':
901 BreakLineDict
.append (StringOffset
+ 1)
903 if BreakLineDict
!= []:
904 for Each
in BreakLineDict
:
905 Multilines
+= " %s\n" % String
[CurrentStringStart
:Each
].lstrip()
906 CurrentStringStart
= Each
907 if StringLength
- CurrentStringStart
> 0:
908 Multilines
+= " %s\n" % String
[CurrentStringStart
:].lstrip()
910 Multilines
= " %s\n" % String
914 FoundSpaceChar
= False
915 while (StringOffset
< StringLength
):
916 if StringOffset
>= 1:
917 if NewLineCount
>= MaxCharLength
- 1:
918 if String
[StringOffset
] == ' ' and StringLength
- StringOffset
> 10:
919 BreakLineDict
.append (NewLineStart
+ NewLineCount
)
920 NewLineStart
= NewLineStart
+ NewLineCount
922 FoundSpaceChar
= True
923 elif StringOffset
== StringLength
- 1 and FoundSpaceChar
== False:
924 BreakLineDict
.append (0)
925 if String
[StringOffset
- 1] == '\\' and String
[StringOffset
] == 'n':
926 BreakLineDict
.append (StringOffset
+ 1)
927 NewLineStart
= StringOffset
+ 1
931 if BreakLineDict
!= []:
932 BreakLineDict
.sort ()
933 for Each
in BreakLineDict
:
935 Multilines
+= " %s\n" % String
[CurrentStringStart
:Each
].lstrip()
936 CurrentStringStart
= Each
937 if StringLength
- CurrentStringStart
> 0:
938 Multilines
+= " %s\n" % String
[CurrentStringStart
:].lstrip()
941 def CreateField (self
, Item
, Name
, Length
, Offset
, Struct
, BsfName
, Help
, Option
):
949 if Length
in [1,2,4,8]:
950 Type
= "UINT%d" % (Length
* 8)
951 if Name
.startswith("UnusedUpdSpace") and Length
!= 1:
958 if Item
and Item
['value'].startswith('{'):
964 if Struct
in ['UINT8','UINT16','UINT32','UINT64']:
966 Unit
= int(Type
[4:]) / 8
967 Length
= Length
/ Unit
972 Name
= Name
+ '[%d]' % Length
974 if len(Type
) < PosName
:
975 Space1
= PosName
- len(Type
)
980 NameLine
=" - %s\n" % BsfName
985 HelpLine
= self
.ProcessMultilines (Help
, 80)
988 OptionLine
= self
.ProcessMultilines (Option
, 80)
993 OffsetStr
= '0x%04X' % Offset
995 return "\n/** Offset %s%s%s%s**/\n %s%s%s;\n" % (OffsetStr
, NameLine
, HelpLine
, OptionLine
, Type
, ' ' * Space1
, Name
,)
997 def PostProcessBody (self
, TextBody
):
1003 IsUpdHdrDefined
= False
1005 for Line
in TextBody
:
1006 SplitToLines
= Line
.splitlines()
1007 MatchComment
= re
.match("^/\*\sCOMMENT:(\w+):([\w|\W|\s]+)\s\*/\s([\s\S]*)", SplitToLines
[0])
1009 if MatchComment
.group(1) == 'FSP_UPD_HEADER':
1013 if IsUpdHdrDefined
!= True or IsUpdHeader
!= True:
1014 CommentLine
= " " + MatchComment
.group(2) + "\n"
1015 NewTextBody
.append("/**" + CommentLine
+ "**/\n")
1016 Line
= Line
[(len(SplitToLines
[0]) + 1):]
1018 Match
= re
.match("^/\*\sEMBED_STRUCT:(\w+):(\w+):(START|END)\s\*/\s([\s\S]*)", Line
)
1020 Line
= Match
.group(4)
1021 if Match
.group(1) == 'FSP_UPD_HEADER':
1026 if Match
and Match
.group(3) == 'START':
1027 if IsUpdHdrDefined
!= True or IsUpdHeader
!= True:
1028 NewTextBody
.append ('typedef struct {\n')
1029 StructName
= Match
.group(1)
1030 VariableName
= Match
.group(2)
1031 MatchOffset
= re
.search('/\*\*\sOffset\s0x([a-fA-F0-9]+)', Line
)
1033 Offset
= int(MatchOffset
.group(1), 16)
1038 OldTextBody
.append (self
.CreateField (None, VariableName
, 0, Offset
, StructName
, '', '', ''))
1040 if IsUpdHdrDefined
!= True or IsUpdHeader
!= True:
1041 NewTextBody
.append (Line
)
1043 OldTextBody
.append (Line
)
1045 if Match
and Match
.group(3) == 'END':
1046 if (StructName
!= Match
.group(1)) or (VariableName
!= Match
.group(2)):
1047 print ("Unmatched struct name '%s' and '%s' !" % (StructName
, Match
.group(1)))
1049 if IsUpdHdrDefined
!= True or IsUpdHeader
!= True:
1050 NewTextBody
.append ('} %s;\n\n' % StructName
)
1051 IsUpdHdrDefined
= True
1053 NewTextBody
.extend(OldTextBody
)
1056 def WriteLinesWithoutTailingSpace (self
, HeaderFd
, Line
):
1057 TxtBody2
= Line
.splitlines(True)
1058 for Line2
in TxtBody2
:
1059 Line2
= Line2
.rstrip()
1061 HeaderFd
.write (Line2
)
1063 def CreateHeaderFile (self
, InputHeaderFile
):
1066 HeaderFileName
= 'FspUpd.h'
1067 HeaderFile
= os
.path
.join(FvDir
, HeaderFileName
)
1069 # Check if header needs to be recreated
1070 if (self
.NoDscFileChange (HeaderFile
)):
1071 # DSC has not been modified yet
1072 # So don't have to re-generate other files
1073 self
.Error
= 'No DSC file change, skip to create UPD header file'
1077 for Item
in self
._CfgItemList
:
1078 if str(Item
['cname']) == 'Signature' and Item
['length'] == 8:
1079 Value
= int(Item
['value'], 16)
1082 Chars
.append(chr(Value
& 0xFF))
1084 SignatureStr
= ''.join(Chars
)
1085 # Signature will be _T / _M / _S for FSPT / FSPM / FSPS accordingly
1086 if '_T' in SignatureStr
[6:6+2]:
1087 TxtBody
.append("#define FSPT_UPD_SIGNATURE %s /* '%s' */\n\n" % (Item
['value'], SignatureStr
))
1088 elif '_M' in SignatureStr
[6:6+2]:
1089 TxtBody
.append("#define FSPM_UPD_SIGNATURE %s /* '%s' */\n\n" % (Item
['value'], SignatureStr
))
1090 elif '_S' in SignatureStr
[6:6+2]:
1091 TxtBody
.append("#define FSPS_UPD_SIGNATURE %s /* '%s' */\n\n" % (Item
['value'], SignatureStr
))
1092 TxtBody
.append("\n")
1094 for Region
in ['UPD']:
1096 UpdSignature
= ['0x545F', '0x4D5F', '0x535F'] #['_T', '_M', '_S'] signature for FSPT, FSPM, FSPS
1097 UpdStructure
= ['FSPT_UPD', 'FSPM_UPD', 'FSPS_UPD']
1098 for Item
in self
._CfgItemList
:
1099 if Item
["cname"] == 'Signature' and Item
["value"][0:6] in UpdSignature
:
1100 UpdOffsetTable
.append (Item
["offset"])
1102 for UpdIdx
in range(len(UpdOffsetTable
)):
1104 for Item
in self
._CfgItemList
:
1105 if Item
["comment"] != '' and Item
["offset"] >= UpdOffsetTable
[UpdIdx
]:
1106 MatchComment
= re
.match("^(U|V)PD_DATA_REGION:([\w|\W|\s]+)", Item
["comment"])
1107 if MatchComment
and MatchComment
.group(1) == Region
[0]:
1108 CommentLine
= " " + MatchComment
.group(2) + "\n"
1109 TxtBody
.append("/**" + CommentLine
+ "**/\n")
1110 elif Item
["offset"] >= UpdOffsetTable
[UpdIdx
] and Item
["comment"] == '':
1111 Match
= re
.match("^FSP([\w|\W|\s])_UPD", UpdStructure
[UpdIdx
])
1113 TxtBody
.append("/** Fsp " + Match
.group(1) + " UPD Configuration\n**/\n")
1114 TxtBody
.append("typedef struct {\n")
1124 for Item
in self
._CfgItemList
:
1125 if Item
['cname'] == 'Signature' and str(Item
['value'])[0:6] == UpdSignature
[UpdIdx
] or Region
[0] == 'V':
1129 if Item
['cname'] == 'UpdTerminator':
1132 if Item
['region'] != Region
:
1135 if Item
["offset"] < UpdOffsetTable
[UpdIdx
]:
1138 NextVisible
= LastVisible
1140 if LastVisible
and (Item
['header'] == 'OFF'):
1142 ResvOffset
= Item
['offset']
1143 elif (not LastVisible
) and Item
['header'] == 'ON':
1145 Name
= "Reserved" + Region
[0] + "pdSpace%d" % ResvIdx
1146 ResvIdx
= ResvIdx
+ 1
1147 TxtBody
.append(self
.CreateField (Item
, Name
, Item
["offset"] - ResvOffset
, ResvOffset
, '', '', '', ''))
1149 if Offset
< Item
["offset"]:
1151 Name
= "Unused" + Region
[0] + "pdSpace%d" % SpaceIdx
1152 LineBuffer
.append(self
.CreateField (Item
, Name
, Item
["offset"] - Offset
, Offset
, '', '', '', ''))
1153 SpaceIdx
= SpaceIdx
+ 1
1154 Offset
= Item
["offset"]
1156 LastVisible
= NextVisible
1158 Offset
= Offset
+ Item
["length"]
1160 for Each
in LineBuffer
:
1161 TxtBody
.append (Each
)
1163 Comment
= Item
["comment"]
1164 Embed
= Item
["embed"].upper()
1165 if Embed
.endswith(':START') or Embed
.endswith(':END'):
1166 if not Comment
== '' and Embed
.endswith(':START'):
1167 Marker
= '/* COMMENT:%s */ \n' % Item
["comment"]
1168 Marker
= Marker
+ '/* EMBED_STRUCT:%s */ ' % Item
["embed"]
1170 Marker
= '/* EMBED_STRUCT:%s */ ' % Item
["embed"]
1175 self
.Error
= "Invalid embedded structure format '%s'!\n" % Item
["embed"]
1177 Line
= Marker
+ self
.CreateField (Item
, Item
["cname"], Item
["length"], Item
["offset"], Item
['struct'], Item
['name'], Item
['help'], Item
['option'])
1178 TxtBody
.append(Line
)
1179 if Item
['cname'] == 'UpdTerminator':
1181 TxtBody
.append("} " + UpdStructure
[UpdIdx
] + ";\n\n")
1183 # Handle the embedded data structure
1184 TxtBody
= self
.PostProcessBody (TxtBody
)
1186 HeaderTFileName
= 'FsptUpd.h'
1187 HeaderMFileName
= 'FspmUpd.h'
1188 HeaderSFileName
= 'FspsUpd.h'
1190 UpdRegionCheck
= ['FSPT', 'FSPM', 'FSPS'] # FSPX_UPD_REGION
1191 UpdConfigCheck
= ['FSP_T', 'FSP_M', 'FSP_S'] # FSP_X_CONFIG, FSP_X_TEST_CONFIG, FSP_X_RESTRICTED_CONFIG
1192 UpdSignatureCheck
= ['FSPT_UPD_SIGNATURE', 'FSPM_UPD_SIGNATURE', 'FSPS_UPD_SIGNATURE']
1193 ExcludedSpecificUpd
= ['FSPT_ARCH_UPD', 'FSPM_ARCH_UPD', 'FSPS_ARCH_UPD']
1196 if InputHeaderFile
!= '':
1197 if not os
.path
.exists(InputHeaderFile
):
1198 self
.Error
= "Input header file '%s' does not exist" % InputHeaderFile
1201 InFd
= open(InputHeaderFile
, "r")
1202 IncLines
= InFd
.readlines()
1205 for item
in range(len(UpdRegionCheck
)):
1206 if UpdRegionCheck
[item
] == 'FSPT':
1207 HeaderFd
= open(os
.path
.join(FvDir
, HeaderTFileName
), "w")
1208 FileBase
= os
.path
.basename(os
.path
.join(FvDir
, HeaderTFileName
))
1209 elif UpdRegionCheck
[item
] == 'FSPM':
1210 HeaderFd
= open(os
.path
.join(FvDir
, HeaderMFileName
), "w")
1211 FileBase
= os
.path
.basename(os
.path
.join(FvDir
, HeaderMFileName
))
1212 elif UpdRegionCheck
[item
] == 'FSPS':
1213 HeaderFd
= open(os
.path
.join(FvDir
, HeaderSFileName
), "w")
1214 FileBase
= os
.path
.basename(os
.path
.join(FvDir
, HeaderSFileName
))
1215 FileName
= FileBase
.replace(".", "_").upper()
1216 HeaderFd
.write("%s\n" % (__copyright_h__
% date
.today().year
))
1217 HeaderFd
.write("#ifndef __%s__\n" % FileName
)
1218 HeaderFd
.write("#define __%s__\n\n" % FileName
)
1219 HeaderFd
.write("#include <%s>\n\n" % HeaderFileName
)
1220 HeaderFd
.write("#pragma pack(1)\n\n")
1223 for Line
in IncLines
:
1224 Match
= re
.search ("!EXPORT\s+([A-Z]+)\s+EXTERNAL_BOOTLOADER_STRUCT_(BEGIN|END)\s+", Line
)
1226 if Match
.group(2) == "BEGIN" and Match
.group(1) == UpdRegionCheck
[item
]:
1233 HeaderFd
.write(Line
)
1234 HeaderFd
.write("\n")
1240 StructStartWithComment
= []
1242 for Line
in TxtBody
:
1244 Match
= re
.match("(typedef struct {)", Line
)
1246 StartIndex
= Index
- 1
1247 Match
= re
.match("}\s([_A-Z0-9]+);", Line
)
1248 if Match
and (UpdRegionCheck
[item
] in Match
.group(1) or UpdConfigCheck
[item
] in Match
.group(1)) and (ExcludedSpecificUpd
[item
] not in Match
.group(1)):
1250 StructStart
.append(StartIndex
)
1251 StructEnd
.append(EndIndex
)
1253 for Line
in TxtBody
:
1255 for Item
in range(len(StructStart
)):
1256 if Index
== StructStart
[Item
]:
1257 Match
= re
.match("^(/\*\*\s*)", Line
)
1259 StructStartWithComment
.append(StructStart
[Item
])
1261 StructStartWithComment
.append(StructStart
[Item
] + 1)
1263 for Line
in TxtBody
:
1265 for Item
in range(len(StructStart
)):
1266 if Index
>= StructStartWithComment
[Item
] and Index
<= StructEnd
[Item
]:
1267 self
.WriteLinesWithoutTailingSpace(HeaderFd
, Line
)
1268 HeaderFd
.write("#pragma pack()\n\n")
1269 HeaderFd
.write("#endif\n")
1272 HeaderFd
= open(HeaderFile
, "w")
1273 FileBase
= os
.path
.basename(HeaderFile
)
1274 FileName
= FileBase
.replace(".", "_").upper()
1275 HeaderFd
.write("%s\n" % (__copyright_h__
% date
.today().year
))
1276 HeaderFd
.write("#ifndef __%s__\n" % FileName
)
1277 HeaderFd
.write("#define __%s__\n\n" % FileName
)
1278 HeaderFd
.write("#include <FspEas.h>\n\n")
1279 HeaderFd
.write("#pragma pack(1)\n\n")
1281 for item
in range(len(UpdRegionCheck
)):
1286 StructStartWithComment
= []
1288 for Line
in TxtBody
:
1290 Match
= re
.match("(typedef struct {)", Line
)
1292 StartIndex
= Index
- 1
1293 Match
= re
.match("#define\s([_A-Z0-9]+)\s*", Line
)
1294 if Match
and (UpdSignatureCheck
[item
] in Match
.group(1) or UpdSignatureCheck
[item
] in Match
.group(1)):
1295 StructStart
.append(Index
- 1)
1296 StructEnd
.append(Index
)
1298 for Line
in TxtBody
:
1300 for Item
in range(len(StructStart
)):
1301 if Index
== StructStart
[Item
]:
1302 Match
= re
.match("^(/\*\*\s*)", Line
)
1304 StructStartWithComment
.append(StructStart
[Item
])
1306 StructStartWithComment
.append(StructStart
[Item
] + 1)
1308 for Line
in TxtBody
:
1310 for Item
in range(len(StructStart
)):
1311 if Index
>= StructStartWithComment
[Item
] and Index
<= StructEnd
[Item
]:
1312 self
.WriteLinesWithoutTailingSpace(HeaderFd
, Line
)
1313 HeaderFd
.write("#pragma pack()\n\n")
1314 HeaderFd
.write("#endif\n")
1319 def WriteBsfStruct (self
, BsfFd
, Item
):
1320 LogExpr
= CLogicalExpression()
1321 if Item
['type'] == "None":
1322 Space
= "gPlatformFspPkgTokenSpaceGuid"
1324 Space
= Item
['space']
1325 Line
= " $%s_%s" % (Space
, Item
['cname'])
1326 Match
= re
.match("\s*\{([x0-9a-fA-F,\s]+)\}\s*", Item
['value'])
1328 DefaultValue
= Match
.group(1).strip()
1330 DefaultValue
= Item
['value'].strip()
1331 if 'bitlength' in Item
:
1332 BsfFd
.write(" %s%s%4d bits $_DEFAULT_ = %s\n" % (Line
, ' ' * (64 - len(Line
)), Item
['bitlength'], DefaultValue
))
1334 BsfFd
.write(" %s%s%4d bytes $_DEFAULT_ = %s\n" % (Line
, ' ' * (64 - len(Line
)), Item
['length'], DefaultValue
))
1336 if Item
['type'] == "Combo":
1337 if not Item
['option'] in self
._BuidinOption
:
1338 OptList
= Item
['option'].split(',')
1339 for Option
in OptList
:
1340 Option
= Option
.strip()
1341 (OpVal
, OpStr
) = Option
.split(':')
1342 test
= LogExpr
.getNumber (OpVal
)
1344 raise Exception("Selection Index '%s' is not a number" % OpVal
)
1345 TmpList
.append((OpVal
, OpStr
))
1348 def WriteBsfOption (self
, BsfFd
, Item
):
1349 PcdName
= Item
['space'] + '_' + Item
['cname']
1351 if Item
['type'] == "Combo":
1352 if Item
['option'] in self
._BuidinOption
:
1353 Options
= self
._BuidinOption
[Item
['option']]
1356 BsfFd
.write(' %s $%s, "%s", &%s,\n' % (Item
['type'], PcdName
, Item
['name'], Options
))
1358 elif Item
['type'].startswith("EditNum"):
1359 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'])
1361 BsfFd
.write(' EditNum $%s, "%s", %s,\n' % (PcdName
, Item
['name'], Match
.group(1)))
1363 elif Item
['type'].startswith("EditText"):
1364 BsfFd
.write(' %s $%s, "%s",\n' % (Item
['type'], PcdName
, Item
['name']))
1366 elif Item
['type'] == "Table":
1367 Columns
= Item
['option'].split(',')
1368 if len(Columns
) != 0:
1369 BsfFd
.write(' %s $%s "%s",' % (Item
['type'], PcdName
, Item
['name']))
1371 Fmt
= Col
.split(':')
1373 raise Exception("Column format '%s' is invalid !" % Fmt
)
1375 Dtype
= int(Fmt
[1].strip())
1377 raise Exception("Column size '%s' is invalid !" % Fmt
[1])
1378 BsfFd
.write('\n Column "%s", %d bytes, %s' % (Fmt
[0].strip(), Dtype
, Fmt
[2].strip()))
1383 HelpLines
= Item
['help'].split('\\n\\r')
1385 for HelpLine
in HelpLines
:
1388 BsfFd
.write(' Help "%s"\n' % (HelpLine
))
1390 BsfFd
.write(' "%s"\n' % (HelpLine
))
1392 BsfFd
.write(' "Valid range: %s ~ %s"\n' % (Match
.group(2), Match
.group(3)))
1394 def GenerateBsfFile (self
, BsfFile
):
1397 self
.Error
= "BSF output file '%s' is invalid" % BsfFile
1400 if (self
.NoDscFileChange (BsfFile
)):
1401 # DSC has not been modified yet
1402 # So don't have to re-generate other files
1403 self
.Error
= 'No DSC file change, skip to create UPD BSF file'
1408 BsfFd
= open(BsfFile
, "w")
1409 BsfFd
.write("%s\n" % (__copyright_bsf__
% date
.today().year
))
1410 BsfFd
.write("%s\n" % self
._GlobalDataDef
)
1411 BsfFd
.write("StructDef\n")
1413 for Item
in self
._CfgItemList
:
1414 if Item
['find'] != '':
1415 BsfFd
.write('\n Find "%s"\n' % Item
['find'])
1416 NextOffset
= Item
['offset'] + Item
['length']
1417 if Item
['name'] != '':
1418 if NextOffset
!= Item
['offset']:
1419 BsfFd
.write(" Skip %d bytes\n" % (Item
['offset'] - NextOffset
))
1420 if len(Item
['subreg']) > 0:
1421 NextOffset
= Item
['offset']
1422 BitsOffset
= NextOffset
* 8
1423 for SubItem
in Item
['subreg']:
1424 BitsOffset
+= SubItem
['bitlength']
1425 if SubItem
['name'] == '':
1426 if 'bitlength' in SubItem
:
1427 BsfFd
.write(" Skip %d bits\n" % (SubItem
['bitlength']))
1429 BsfFd
.write(" Skip %d bytes\n" % (SubItem
['length']))
1431 Options
= self
.WriteBsfStruct(BsfFd
, SubItem
)
1432 if len(Options
) > 0:
1433 OptionDict
[SubItem
['space']+'_'+SubItem
['cname']] = Options
1435 NextBitsOffset
= (Item
['offset'] + Item
['length']) * 8
1436 if NextBitsOffset
> BitsOffset
:
1437 BitsGap
= NextBitsOffset
- BitsOffset
1438 BitsRemain
= BitsGap
% 8
1440 BsfFd
.write(" Skip %d bits\n" % BitsRemain
)
1441 BitsGap
-= BitsRemain
1442 BytesRemain
= int(BitsGap
/ 8)
1444 BsfFd
.write(" Skip %d bytes\n" % BytesRemain
)
1445 NextOffset
= Item
['offset'] + Item
['length']
1447 NextOffset
= Item
['offset'] + Item
['length']
1448 Options
= self
.WriteBsfStruct(BsfFd
, Item
)
1449 if len(Options
) > 0:
1450 OptionDict
[Item
['space']+'_'+Item
['cname']] = Options
1451 BsfFd
.write("\nEndStruct\n\n")
1453 BsfFd
.write("%s" % self
._BuidinOptionTxt
)
1455 for Each
in OptionDict
:
1456 BsfFd
.write("List &%s\n" % Each
)
1457 for Item
in OptionDict
[Each
]:
1458 BsfFd
.write(' Selection %s , "%s"\n' % (Item
[0], Item
[1]))
1459 BsfFd
.write("EndList\n\n")
1461 BsfFd
.write("BeginInfoBlock\n")
1462 BsfFd
.write(' PPVer "%s"\n' % (self
._CfgBlkDict
['ver']))
1463 BsfFd
.write(' Description "%s"\n' % (self
._CfgBlkDict
['name']))
1464 BsfFd
.write("EndInfoBlock\n\n")
1466 for Each
in self
._CfgPageDict
:
1467 BsfFd
.write('Page "%s"\n' % self
._CfgPageDict
[Each
])
1469 for Item
in self
._CfgItemList
:
1470 if Item
['name'] != '':
1471 if Item
['page'] != Each
:
1473 if len(Item
['subreg']) > 0:
1474 for SubItem
in Item
['subreg']:
1475 if SubItem
['name'] != '':
1476 BsfItems
.append(SubItem
)
1478 BsfItems
.append(Item
)
1480 BsfItems
.sort(key
=lambda x
: x
['order'])
1482 for Item
in BsfItems
:
1483 self
.WriteBsfOption (BsfFd
, Item
)
1484 BsfFd
.write("EndPage\n\n")
1491 print ("GenCfgOpt Version 0.56")
1493 print (" GenCfgOpt UPDTXT PlatformDscFile BuildFvDir [-D Macros]")
1494 print (" GenCfgOpt HEADER PlatformDscFile BuildFvDir InputHFile [-D Macros]")
1495 print (" GenCfgOpt GENBSF PlatformDscFile BuildFvDir BsfOutFile [-D Macros]")
1499 # Parse the options and args
1503 GenCfgOpt
= CGenCfgOpt()
1504 while i
< len(sys
.argv
):
1505 if sys
.argv
[i
].strip().lower() == "--pcd":
1506 BuildOptionPcd
.append(sys
.argv
[i
+1])
1509 argc
= len(sys
.argv
)
1514 DscFile
= sys
.argv
[2]
1515 if not os
.path
.exists(DscFile
):
1516 print ("ERROR: Cannot open DSC file '%s' !" % DscFile
)
1521 if sys
.argv
[4][0] == '-':
1524 OutFile
= sys
.argv
[4]
1527 if GenCfgOpt
.ParseMacros(sys
.argv
[Start
:]) != 0:
1528 print ("ERROR: Macro parsing failed !")
1532 if not os
.path
.exists(FvDir
):
1535 if GenCfgOpt
.ParseDscFile(DscFile
, FvDir
) != 0:
1536 print ("ERROR: %s !" % GenCfgOpt
.Error
)
1539 if GenCfgOpt
.UpdateSubRegionDefaultValue() != 0:
1540 print ("ERROR: %s !" % GenCfgOpt
.Error
)
1543 if sys
.argv
[1] == "UPDTXT":
1544 Ret
= GenCfgOpt
.CreateSplitUpdTxt(OutFile
)
1546 # No change is detected
1548 print ("INFO: %s !" % (GenCfgOpt
.Error
))
1550 print ("ERROR: %s !" % (GenCfgOpt
.Error
))
1552 elif sys
.argv
[1] == "HEADER":
1553 Ret
= GenCfgOpt
.CreateHeaderFile(OutFile
)
1555 # No change is detected
1557 print ("INFO: %s !" % (GenCfgOpt
.Error
))
1559 print ("ERROR: %s !" % (GenCfgOpt
.Error
))
1562 elif sys
.argv
[1] == "GENBSF":
1563 Ret
= GenCfgOpt
.GenerateBsfFile(OutFile
)
1565 # No change is detected
1567 print ("INFO: %s !" % (GenCfgOpt
.Error
))
1569 print ("ERROR: %s !" % (GenCfgOpt
.Error
))
1576 print ("ERROR: Unknown command '%s' !" % sys
.argv
[1])
1583 if __name__
== '__main__':