]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFsp2Pkg/Tools/GenCfgOpt.py
128b8965926caf390c8a0aca8297c6e65a42773e
[mirror_edk2.git] / IntelFsp2Pkg / Tools / GenCfgOpt.py
1 ## @ GenCfgOpt.py
2 #
3 # Copyright (c) 2014 - 2022, Intel Corporation. All rights reserved.<BR>
4 # SPDX-License-Identifier: BSD-2-Clause-Patent
5 #
6 ##
7
8 import os
9 import re
10 import sys
11 import struct
12 from datetime import date
13 from functools import reduce
14
15 # Generated file copyright header
16
17 __copyright_txt__ = """## @file
18 #
19 # THIS IS AUTO-GENERATED FILE BY BUILD TOOLS AND PLEASE DO NOT MAKE MODIFICATION.
20 #
21 # This file lists all VPD informations for a platform collected by build.exe.
22 #
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
28 #
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.
31 #
32 """
33
34 __copyright_bsf__ = """/** @file
35
36 Boot Setting File for Platform Configuration.
37
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
43
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.
46
47 This file is automatically generated. Please do NOT modify !!!
48
49 **/
50
51 """
52
53 __copyright_h__ = """/** @file
54
55 Copyright (c) %4d, Intel Corporation. All rights reserved.<BR>
56
57 Redistribution and use in source and binary forms, with or without modification,
58 are permitted provided that the following conditions are met:
59
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.
68
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.
80
81 This file is automatically generated. Please do NOT modify !!!
82
83 **/
84 """
85
86 BuildOptionPcd = []
87
88 class CLogicalExpression:
89 def __init__(self):
90 self.index = 0
91 self.string = ''
92
93 def errExit(self, err = ''):
94 print ("ERROR: Express parsing for:")
95 print (" %s" % self.string)
96 print (" %s^" % (' ' * self.index))
97 if err:
98 print ("INFO : %s" % err)
99 raise SystemExit
100
101 def getNonNumber (self, n1, n2):
102 if not n1.isdigit():
103 return n1
104 if not n2.isdigit():
105 return n2
106 return None
107
108 def getCurr(self, lens = 1):
109 try:
110 if lens == -1:
111 return self.string[self.index :]
112 else:
113 if self.index + lens > len(self.string):
114 lens = len(self.string) - self.index
115 return self.string[self.index : self.index + lens]
116 except Exception:
117 return ''
118
119 def isLast(self):
120 return self.index == len(self.string)
121
122 def moveNext(self, len = 1):
123 self.index += len
124
125 def skipSpace(self):
126 while not self.isLast():
127 if self.getCurr() in ' \t':
128 self.moveNext()
129 else:
130 return
131
132 def normNumber (self, val):
133 return True if val else False
134
135 def getNumber(self, var):
136 var = var.strip()
137 if re.match('^0x[a-fA-F0-9]+$', var):
138 value = int(var, 16)
139 elif re.match('^[+-]?\d+$', var):
140 value = int(var, 10)
141 else:
142 value = None
143 return value
144
145 def parseValue(self):
146 self.skipSpace()
147 var = ''
148 while not self.isLast():
149 char = self.getCurr()
150 if re.match('^[\w.]', char):
151 var += char
152 self.moveNext()
153 else:
154 break
155 val = self.getNumber(var)
156 if val is None:
157 value = var
158 else:
159 value = "%d" % val
160 return value
161
162 def parseSingleOp(self):
163 self.skipSpace()
164 if re.match('^NOT\W', self.getCurr(-1)):
165 self.moveNext(3)
166 op = self.parseBrace()
167 val = self.getNumber (op)
168 if val is None:
169 self.errExit ("'%s' is not a number" % op)
170 return "%d" % (not self.normNumber(int(op)))
171 else:
172 return self.parseValue()
173
174 def parseBrace(self):
175 self.skipSpace()
176 char = self.getCurr()
177 if char == '(':
178 self.moveNext()
179 value = self.parseExpr()
180 self.skipSpace()
181 if self.getCurr() != ')':
182 self.errExit ("Expecting closing brace or operator")
183 self.moveNext()
184 return value
185 else:
186 value = self.parseSingleOp()
187 return value
188
189 def parseCompare(self):
190 value = self.parseBrace()
191 while True:
192 self.skipSpace()
193 char = self.getCurr()
194 if char in ['<', '>']:
195 self.moveNext()
196 next = self.getCurr()
197 if next == '=':
198 op = char + next
199 self.moveNext()
200 else:
201 op = char
202 result = self.parseBrace()
203 test = self.getNonNumber(result, value)
204 if test is None:
205 value = "%d" % self.normNumber(eval (value + op + result))
206 else:
207 self.errExit ("'%s' is not a valid number for comparision" % test)
208 elif char in ['=', '!']:
209 op = self.getCurr(2)
210 if op in ['==', '!=']:
211 self.moveNext(2)
212 result = self.parseBrace()
213 test = self.getNonNumber(result, value)
214 if test is None:
215 value = "%d" % self.normNumber((eval (value + op + result)))
216 else:
217 value = "%d" % self.normNumber(eval ("'" + value + "'" + op + "'" + result + "'"))
218 else:
219 break
220 else:
221 break
222 return value
223
224 def parseAnd(self):
225 value = self.parseCompare()
226 while True:
227 self.skipSpace()
228 if re.match('^AND\W', self.getCurr(-1)):
229 self.moveNext(3)
230 result = self.parseCompare()
231 test = self.getNonNumber(result, value)
232 if test is None:
233 value = "%d" % self.normNumber(int(value) & int(result))
234 else:
235 self.errExit ("'%s' is not a valid op number for AND" % test)
236 else:
237 break
238 return value
239
240 def parseOrXor(self):
241 value = self.parseAnd()
242 op = None
243 while True:
244 self.skipSpace()
245 op = None
246 if re.match('^XOR\W', self.getCurr(-1)):
247 self.moveNext(3)
248 op = '^'
249 elif re.match('^OR\W', self.getCurr(-1)):
250 self.moveNext(2)
251 op = '|'
252 else:
253 break
254 if op:
255 result = self.parseAnd()
256 test = self.getNonNumber(result, value)
257 if test is None:
258 value = "%d" % self.normNumber(eval (value + op + result))
259 else:
260 self.errExit ("'%s' is not a valid op number for XOR/OR" % test)
261 return value
262
263 def parseExpr(self):
264 return self.parseOrXor()
265
266 def getResult(self):
267 value = self.parseExpr()
268 self.skipSpace()
269 if not self.isLast():
270 self.errExit ("Unexpected character found '%s'" % self.getCurr())
271 test = self.getNumber(value)
272 if test is None:
273 self.errExit ("Result '%s' is not a number" % value)
274 return int(value)
275
276 def evaluateExpress (self, Expr):
277 self.index = 0
278 self.string = Expr
279 if self.getResult():
280 Result = True
281 else:
282 Result = False
283 return Result
284
285 class CGenCfgOpt:
286 def __init__(self, Mode = ''):
287 self.Debug = False
288 self.Error = ''
289 self.Mode = Mode
290 self._GlobalDataDef = """
291 GlobalDataDef
292 SKUID = 0, "DEFAULT"
293 EndGlobalData
294
295 """
296 self._BuidinOptionTxt = """
297 List &EN_DIS
298 Selection 0x1 , "Enabled"
299 Selection 0x0 , "Disabled"
300 EndList
301
302 """
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'}
306
307 self._MacroDict = {}
308 self._VarDict = {}
309 self._PcdsDict = {}
310 self._CfgBlkDict = {}
311 self._CfgPageDict = {}
312 self._BsfTempDict = {}
313 self._CfgItemList = []
314 self._DscLines = []
315 self._DscFile = ''
316
317 self._MapVer = 0
318 self._DscTime = 0
319
320 def ParseMacros (self, MacroDefStr):
321 # ['-DABC=1', '-D', 'CFG_DEBUG=1', '-D', 'CFG_OUTDIR=Build']
322 self._MacroDict = {}
323 IsExpression = False
324 for Macro in MacroDefStr:
325 if Macro.startswith('-D'):
326 IsExpression = True
327 if len(Macro) > 2:
328 Macro = Macro[2:]
329 else :
330 continue
331 if IsExpression:
332 IsExpression = False
333 Match = re.match("(\w+)=(.+)", Macro)
334 if Match:
335 self._MacroDict[Match.group(1)] = Match.group(2)
336 else:
337 Match = re.match("(\w+)", Macro)
338 if Match:
339 self._MacroDict[Match.group(1)] = ''
340 if len(self._MacroDict) == 0:
341 Error = 1
342 else:
343 Error = 0
344 if self.Debug:
345 print ("INFO : Macro dictionary:")
346 for Each in self._MacroDict:
347 print (" $(%s) = [ %s ]" % (Each , self._MacroDict[Each]))
348 return Error
349
350 def EvaulateIfdef (self, Macro):
351 Result = Macro in self._MacroDict
352 if self.Debug:
353 print ("INFO : Eval Ifdef [%s] : %s" % (Macro, Result))
354 return Result
355
356 def ExpandMacros (self, Input, Preserve = False):
357 Line = Input
358 Match = re.findall("\$\(\w+\)", Input)
359 if Match:
360 for Each in Match:
361 Variable = Each[2:-1]
362 if Variable in self._MacroDict:
363 Line = Line.replace(Each, self._MacroDict[Variable])
364 else:
365 if self.Debug:
366 print ("WARN : %s is not defined" % Each)
367 if not Preserve:
368 Line = Line.replace(Each, Each[2:-1])
369 return Line
370
371 def ExpandPcds (self, Input):
372 Line = Input
373 Match = re.findall("(\w+\.\w+)", Input)
374 if Match:
375 for PcdName in Match:
376 if PcdName in self._PcdsDict:
377 Line = Line.replace(PcdName, self._PcdsDict[PcdName])
378 else:
379 if self.Debug:
380 print ("WARN : %s is not defined" % PcdName)
381 return Line
382
383 def EvaluateExpress (self, Expr):
384 ExpExpr = self.ExpandPcds(Expr)
385 ExpExpr = self.ExpandMacros(ExpExpr)
386 LogExpr = CLogicalExpression()
387 Result = LogExpr.evaluateExpress (ExpExpr)
388 if self.Debug:
389 print ("INFO : Eval Express [%s] : %s" % (Expr, Result))
390 return Result
391
392 def ValueToByteArray (self, ValueStr, Length):
393 Match = re.match("\{\s*FILE:(.+)\}", ValueStr)
394 if Match:
395 FileList = Match.group(1).split(',')
396 Result = bytearray()
397 for File in FileList:
398 File = File.strip()
399 BinPath = os.path.join(os.path.dirname(self._DscFile), File)
400 Result.extend(bytearray(open(BinPath, 'rb').read()))
401 else:
402 try:
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))
410
411 return Result[:Length]
412
413 def ValueToList (self, ValueStr, Length):
414 if ValueStr[0] == '{':
415 Result = []
416 BinList = ValueStr[1:-1].split(',')
417 InBitField = False
418 LastInBitField = False
419 Value = 0
420 BitLen = 0
421 for Element in BinList:
422 InBitField = False
423 Each = Element.strip()
424 if len(Each) == 0:
425 pass
426 else:
427 if Each[0] in ['"', "'"]:
428 Result.extend(list(bytearray(Each[1:-1], 'utf-8')))
429 elif ':' in Each:
430 Match = re.match("(.+):(\d+)b", Each)
431 if Match is None:
432 raise Exception("Invald value list format '%s' !" % Each)
433 InBitField = True
434 CurrentBitLen = int(Match.group(2))
435 CurrentValue = ((self.EvaluateExpress(Match.group(1)) & (1<<CurrentBitLen) - 1)) << BitLen
436 else:
437 Result.append(self.EvaluateExpress(Each.strip()))
438 if InBitField:
439 Value += CurrentValue
440 BitLen += CurrentBitLen
441 if LastInBitField and ((not InBitField) or (Element == BinList[-1])):
442 if BitLen % 8 != 0:
443 raise Exception("Invald bit field length!")
444 Result.extend(Val2Bytes(Value, BitLen // 8))
445 Value = 0
446 BitLen = 0
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)
452 else:
453 Result = Val2Bytes (self.EvaluateExpress(ValueStr), Length)
454 return Result
455
456 def FormatListValue(self, ConfigDict):
457 Struct = ConfigDict['struct']
458 if Struct not in ['UINT8','UINT16','UINT32','UINT64']:
459 return
460
461 dataarray = []
462 binlist = ConfigDict['value'][1:-1].split(',')
463 for each in binlist:
464 each = each.strip()
465 if each.startswith('0x'):
466 value = int(each, 16)
467 else:
468 value = int(each)
469 dataarray.append(value)
470
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'])
474
475 bytearray = []
476 for each in dataarray:
477 value = each
478 for loop in range(int(unit)):
479 bytearray.append("0x%02X" % (value & 0xFF))
480 value = value >> 8
481 newvalue = '{' + ','.join(bytearray) + '}'
482 ConfigDict['value'] = newvalue
483 return ""
484
485 def ParseDscFile (self, DscFile, FvDir):
486 Hardcode = False
487 AutoAlign = False
488 self._CfgItemList = []
489 self._CfgPageDict = {}
490 self._CfgBlkDict = {}
491 self._DscFile = DscFile
492 self._FvDir = FvDir
493
494 self._DscLines = []
495 self._BsfTempDict = {}
496
497 # Initial DSC time is parent DSC time.
498 self._DscTime = os.path.getmtime(DscFile)
499
500 CfgDict = {}
501
502 IsDefSect = False
503 IsPcdSect = False
504 IsUpdSect = False
505 IsVpdSect = False
506 IsTmpSect = False
507
508 TemplateName = ''
509
510 IfStack = []
511 ElifStack = []
512 Error = 0
513 ConfigDict = {}
514
515
516 if type(DscFile) is list:
517 # it is DSC lines already
518 DscLines = DscFile
519 self._DscFile = '.'
520 else:
521 DscFd = open(DscFile, "r")
522 DscLines = DscFd.readlines()
523 DscFd.close()
524 self._DscFile = DscFile
525
526 SkipLines = 0
527
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.
531
532 while len(DscLines):
533 DscLine = DscLines.pop(0).strip()
534 if SkipLines == 0:
535 self._DscLines.append (DscLine)
536 else:
537 SkipLines = SkipLines - 1
538 if len(DscLine) == 0:
539 continue
540
541 Handle = False
542 Match = re.match("^\[(.+)\]", DscLine)
543 if Match is not None:
544 IsDefSect = False
545 IsPcdSect = False
546 IsVpdSect = False
547 IsUpdSect = False
548 IsTmpSect = False
549 SectionName = Match.group(1).lower()
550 if SectionName == "Defines".lower():
551 IsDefSect = True
552 if (SectionName == "PcdsFeatureFlag".lower() or SectionName == "PcdsFixedAtBuild".lower()):
553 IsPcdSect = True
554 elif SectionName == "PcdsDynamicVpd.Tmp".lower():
555 IsTmpSect = True
556 elif SectionName == "PcdsDynamicVpd.Upd".lower():
557 ConfigDict = {}
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'] = ''
571 IsUpdSect = True
572 Offset = 0
573 else:
574 if IsDefSect or IsPcdSect or IsUpdSect or IsVpdSect or IsTmpSect:
575
576 Match = False if DscLine[0] != '!' else True
577 if Match:
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()
582
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)
585
586 if Keyword == 'else':
587 if IfStack:
588 IfStack[-1] = not IfStack[-1]
589 else:
590 raise Exception ("ERROR: No paired '!if' found for '!else' for line '%s'" % DscLine)
591 elif Keyword == 'endif':
592 if IfStack:
593 IfStack.pop()
594 Level = ElifStack.pop()
595 if Level > 0:
596 del IfStack[-Level:]
597 else:
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':
602 Result = not Result
603 IfStack.append(Result)
604 ElifStack.append(0)
605 elif Keyword == 'if' or Keyword == 'elseif':
606 Result = self.EvaluateExpress(Remaining)
607 if Keyword == "if":
608 ElifStack.append(0)
609 IfStack.append(Result)
610 else: #elseif
611 if IfStack:
612 IfStack[-1] = not IfStack[-1]
613 IfStack.append(Result)
614 ElifStack[-1] = ElifStack[-1] + 1
615 else:
616 raise Exception ("ERROR: No paired '!if' found for '!elif' for line '%s'" % DscLine)
617 else:
618 if IfStack:
619 Handle = reduce(lambda x,y: x and y, IfStack)
620 else:
621 Handle = True
622 if Handle:
623 Match = re.match("!include\s+(.+)", DscLine)
624 if Match:
625 IncludeFilePath = Match.group(1)
626 IncludeFilePath = self.ExpandMacros(IncludeFilePath)
627 PackagesPath = os.getenv("PACKAGES_PATH")
628 if PackagesPath:
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")
633 break
634 else:
635 IncludeDsc = open(IncludeFilePath, "r")
636 if IncludeDsc == None:
637 print("ERROR: Cannot open file '%s'" % IncludeFilePath)
638 raise SystemExit
639
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
644
645 NewDscLines = IncludeDsc.readlines()
646 IncludeDsc.close()
647 DscLines = NewDscLines + DscLines
648 del self._DscLines[-1]
649 Offset = 0
650 else:
651 if DscLine.startswith('!'):
652 print("ERROR: Unrecognized directive for line '%s'" % DscLine)
653 raise SystemExit
654 if not Handle:
655 del self._DscLines[-1]
656 continue
657
658 if IsDefSect:
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)
664 if Match:
665 self._MacroDict[Match.group(1)] = self.ExpandMacros(Match.group(2))
666 if self.Debug:
667 print ("INFO : DEFINE %s = [ %s ]" % (Match.group(1), self.ExpandMacros(Match.group(2))))
668 elif IsPcdSect:
669 #gSiPkgTokenSpaceGuid.PcdTxtEnable|FALSE
670 #gSiPkgTokenSpaceGuid.PcdOverclockEnable|TRUE
671 Match = re.match("^\s*([\w\.]+)\s*\|\s*(\w+)", DscLine)
672 if Match:
673 self._PcdsDict[Match.group(1)] = Match.group(2)
674 if self.Debug:
675 print ("INFO : PCD %s = [ %s ]" % (Match.group(1), Match.group(2)))
676 i = 0
677 while i < len(BuildOptionPcd):
678 Match = re.match("\s*([\w\.]+)\s*\=\s*(\w+)", BuildOptionPcd[i])
679 if Match:
680 self._PcdsDict[Match.group(1)] = Match.group(2)
681 i += 1
682
683 elif IsTmpSect:
684 # !BSF DEFT:{GPIO_TMPL:START}
685 Match = re.match("^\s*#\s+(!BSF)\s+DEFT:{(.+?):(START|END)}", DscLine)
686 if Match:
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:
691 TemplateName = ''
692 else:
693 if TemplateName:
694 Match = re.match("^!include\s*(.+)?$", DscLine)
695 if Match:
696 continue
697 self._BsfTempDict[TemplateName].append(DscLine)
698
699 else:
700 Match = re.match("^\s*#\s+(!BSF|@Bsf|!HDR)\s+(.+)", DscLine)
701 if Match:
702 Remaining = Match.group(2)
703 if Match.group(1) == '!BSF' or Match.group(1) == '@Bsf':
704 Match = re.match("(?:^|.+\s+)PAGES:{(.+?)}", Remaining)
705 if Match:
706 # !BSF PAGES:{HSW:"Haswell System Agent", LPT:"Lynx Point PCH"}
707 PageList = Match.group(1).split(',')
708 for Page in PageList:
709 Page = Page.strip()
710 Match = re.match("(\w+):\"(.+)\"", Page)
711 if Match != None:
712 self._CfgPageDict[Match.group(1)] = Match.group(2)
713
714 Match = re.match("(?:^|.+\s+)BLOCK:{NAME:\"(.+)\"\s*,\s*VER:\"(.+)\"\s*}", Remaining)
715 if Match:
716 self._CfgBlkDict['name'] = Match.group(1)
717 self._CfgBlkDict['ver'] = Match.group(2)
718
719 for Key in self._BsfKeyList:
720 Match = re.match("(?:^|.+\s+)%s:{(.+?)}" % Key, Remaining)
721 if Match:
722 if Key in ['NAME', 'HELP', 'OPTION'] and Match.group(1).startswith('+'):
723 ConfigDict[Key.lower()] += Match.group(1)[1:]
724 else:
725 ConfigDict[Key.lower()] = Match.group(1)
726 else:
727 for Key in self._HdrKeyList:
728 Match = re.match("(?:^|.+\s+)%s:{(.+?)}" % Key, Remaining)
729 if Match:
730 ConfigDict[Key.lower()] = Match.group(1)
731
732 Match = re.match("^\s*#\s+@Prompt\s+(.+)", DscLine)
733 if Match:
734 ConfigDict['name'] = Match.group(1)
735
736 Match = re.match("^\s*#\s*@ValidList\s*(.+)\s*\|\s*(.+)\s*\|\s*(.+)\s*", DscLine)
737 if Match:
738 if Match.group(2).strip() in self._BuidinOption:
739 ConfigDict['option'] = Match.group(2).strip()
740 else:
741 OptionValueList = Match.group(2).split(',')
742 OptionStringList = Match.group(3).split(',')
743 Index = 0
744 for Option in OptionValueList:
745 Option = Option.strip()
746 ConfigDict['option'] = ConfigDict['option'] + str(Option) + ':' + OptionStringList[Index].strip()
747 Index += 1
748 if Index in range(len(OptionValueList)):
749 ConfigDict['option'] += ', '
750 ConfigDict['type'] = "Combo"
751
752 Match = re.match("^\s*#\s*@ValidRange\s*(.+)\s*\|\s*(.+)\s*-\s*(.+)\s*", DscLine)
753 if Match:
754 if "0x" in Match.group(2) or "0x" in Match.group(3):
755 ConfigDict['type'] = "EditNum, HEX, (%s,%s)" % (Match.group(2), Match.group(3))
756 else:
757 ConfigDict['type'] = "EditNum, DEC, (%s,%s)" % (Match.group(2), Match.group(3))
758
759 Match = re.match("^\s*##\s+(.+)", DscLine)
760 if Match:
761 ConfigDict['help'] = Match.group(1)
762
763 # Check VPD/UPD
764 if IsUpdSect:
765 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 else:
767 Match = re.match("^([_a-zA-Z0-9]+).([_a-zA-Z0-9]+)\s*\|\s*(0x[0-9A-F]+)(?:\s*\|\s*(.+))?", DscLine)
768 if Match:
769 ConfigDict['space'] = Match.group(1)
770 ConfigDict['cname'] = Match.group(2)
771 if Match.group(3) != '*':
772 Hardcode = True
773 Offset = int (Match.group(3), 16)
774 else:
775 AutoAlign = True
776
777 if Hardcode and AutoAlign:
778 print("Hardcode and auto-align mixed mode is not supported by GenCfgOpt")
779 raise SystemExit
780 ConfigDict['offset'] = Offset
781 if ConfigDict['order'] == -1:
782 ConfigDict['order'] = ConfigDict['offset'] << 8
783 else:
784 (Major, Minor) = ConfigDict['order'].split('.')
785 ConfigDict['order'] = (int (Major, 16) << 8 ) + int (Minor, 16)
786 if IsUpdSect:
787 Value = Match.group(5).strip()
788 if Match.group(4).startswith("0x"):
789 Length = int (Match.group(4), 16)
790 else :
791 Length = int (Match.group(4))
792 Offset += Length
793 else:
794 Value = Match.group(4)
795 if Value is None:
796 Value = ''
797 Value = Value.strip()
798 if '|' in Value:
799 Match = re.match("^.+\s*\|\s*(.+)", Value)
800 if Match:
801 Value = Match.group(1)
802 Length = -1
803
804 ConfigDict['length'] = Length
805 Match = re.match("\$\((\w+)\)", Value)
806 if Match:
807 if Match.group(1) in self._MacroDict:
808 Value = self._MacroDict[Match.group(1)]
809
810 ConfigDict['value'] = Value
811 if (len(Value) > 0) and (Value[0] == '{'):
812 Value = self.FormatListValue(ConfigDict)
813
814 if ConfigDict['name'] == '':
815 # Clear BSF specific items
816 ConfigDict['bsfname'] = ''
817 ConfigDict['help'] = ''
818 ConfigDict['type'] = ''
819 ConfigDict['option'] = ''
820 if IsUpdSect and AutoAlign:
821 ItemLength = int(ConfigDict['length'])
822 ItemOffset = int(ConfigDict['offset'])
823 ItemStruct = ConfigDict['struct']
824 Unit = 1
825 if ItemLength in [1, 2, 4, 8] and not ConfigDict['value'].startswith('{'):
826 Unit = ItemLength
827 # If there are 64 bit unit, align to 64
828 if Unit == 8:
829 MaxAlign = 64
830 SizeAlign = 8
831 if ItemStruct != '':
832 UnitDict = {'UINT8':1, 'UINT16':2, 'UINT32':4, 'UINT64':8}
833 if ItemStruct in ['UINT8', 'UINT16', 'UINT32', 'UINT64']:
834 Unit = UnitDict[ItemStruct]
835 # If there are 64 bit unit, align to 64
836 if Unit == 8:
837 MaxAlign = 64
838 SizeAlign = max(SizeAlign, Unit)
839 if (ConfigDict['embed'].find(':START') != -1):
840 Base = ItemOffset
841 SubOffset = ItemOffset - Base
842 SubRemainder = SubOffset % Unit
843 if SubRemainder:
844 Diff = Unit - SubRemainder
845 Offset = Offset + Diff
846 ItemOffset = ItemOffset + Diff
847
848 if (ConfigDict['embed'].find(':END') != -1):
849 Remainder = Offset % (MaxAlign/8) # MaxAlign is either 32 or 64
850 if Remainder:
851 Diff = int((MaxAlign/8) - Remainder)
852 Offset = Offset + Diff
853 ItemOffset = ItemOffset + Diff
854 MaxAlign = 32 # Reset to default 32 align when struct end
855 if (ConfigDict['cname'] == 'UpdTerminator'):
856 # ItemLength is the size of UpdTerminator
857 # Itemlength might be 16, 32, or 64
858 # Struct align to 64 if UpdTerminator
859 # or struct size is 64 bit, else align to 32
860 Remainder = Offset % max(ItemLength/8, 4, SizeAlign)
861 Offset = Offset + ItemLength
862 if Remainder:
863 Diff = int(max(ItemLength/8, 4, SizeAlign) - Remainder)
864 ItemOffset = ItemOffset + Diff
865 ConfigDict['offset'] = ItemOffset
866
867 self._CfgItemList.append(ConfigDict.copy())
868 ConfigDict['name'] = ''
869 ConfigDict['find'] = ''
870 ConfigDict['struct'] = ''
871 ConfigDict['embed'] = ''
872 ConfigDict['comment'] = ''
873 ConfigDict['marker'] = ''
874 ConfigDict['order'] = -1
875 ConfigDict['subreg'] = []
876 ConfigDict['option'] = ''
877 else:
878 # It could be a virtual item as below
879 # !BSF FIELD:{SerialDebugPortAddress0:1}
880 # or
881 # @Bsf FIELD:{SerialDebugPortAddress0:1b}
882 Match = re.match("^\s*#\s+(!BSF|@Bsf)\s+FIELD:{(.+):(\d+)([Bb])?}", DscLine)
883 if Match:
884 SubCfgDict = ConfigDict.copy()
885 if (Match.group(4) == None) or (Match.group(4) == 'B'):
886 UnitBitLen = 8
887 elif Match.group(4) == 'b':
888 UnitBitLen = 1
889 else:
890 print("ERROR: Invalide BSF FIELD length for line '%s'" % DscLine)
891 raise SystemExit
892 SubCfgDict['cname'] = Match.group(2)
893 SubCfgDict['bitlength'] = int (Match.group(3)) * UnitBitLen
894 if SubCfgDict['bitlength'] > 0:
895 LastItem = self._CfgItemList[-1]
896 if len(LastItem['subreg']) == 0:
897 SubOffset = 0
898 else:
899 SubOffset = LastItem['subreg'][-1]['bitoffset'] + LastItem['subreg'][-1]['bitlength']
900 SubCfgDict['bitoffset'] = SubOffset
901 LastItem['subreg'].append (SubCfgDict.copy())
902 ConfigDict['name'] = ''
903 return Error
904
905 def GetBsfBitFields (self, subitem, bytes):
906 start = subitem['bitoffset']
907 end = start + subitem['bitlength']
908 bitsvalue = ''.join('{0:08b}'.format(i) for i in bytes[::-1])
909 bitsvalue = bitsvalue[::-1]
910 bitslen = len(bitsvalue)
911 if start > bitslen or end > bitslen:
912 raise Exception ("Invalid bits offset [%d,%d] %d for %s" % (start, end, bitslen, subitem['name']))
913 return '0x%X' % (int(bitsvalue[start:end][::-1], 2))
914
915 def UpdateSubRegionDefaultValue (self):
916 Error = 0
917 for Item in self._CfgItemList:
918 if len(Item['subreg']) == 0:
919 continue
920 bytearray = []
921 if Item['value'][0] == '{':
922 binlist = Item['value'][1:-1].split(',')
923 for each in binlist:
924 each = each.strip()
925 if each.startswith('0x'):
926 value = int(each, 16)
927 else:
928 value = int(each)
929 bytearray.append(value)
930 else:
931 if Item['value'].startswith('0x'):
932 value = int(Item['value'], 16)
933 else:
934 value = int(Item['value'])
935 idx = 0
936 while idx < Item['length']:
937 bytearray.append(value & 0xFF)
938 value = value >> 8
939 idx = idx + 1
940 for SubItem in Item['subreg']:
941 valuestr = self.GetBsfBitFields(SubItem, bytearray)
942 SubItem['value'] = valuestr
943 return Error
944
945 def NoDscFileChange (self, OutPutFile):
946 NoFileChange = True
947 if not os.path.exists(OutPutFile):
948 NoFileChange = False
949 else:
950 OutputTime = os.path.getmtime(OutPutFile)
951 if self._DscTime > OutputTime:
952 NoFileChange = False
953 return NoFileChange
954
955 def CreateSplitUpdTxt (self, UpdTxtFile):
956 GuidList = ['FSP_T_UPD_TOOL_GUID','FSP_M_UPD_TOOL_GUID','FSP_S_UPD_TOOL_GUID','FSP_I_UPD_TOOL_GUID']
957 SignatureList = ['0x545F', '0x4D5F','0x535F','0x495F'] # _T, _M, _S and _I signature for FSPT, FSPM, FSPS, FSPI
958 for Index in range(len(GuidList)):
959 UpdTxtFile = ''
960 FvDir = self._FvDir
961 if GuidList[Index] not in self._MacroDict:
962 self.Error = "%s definition is missing in DSC file" % (GuidList[Index])
963 return 1
964
965 if UpdTxtFile == '':
966 UpdTxtFile = os.path.join(FvDir, self._MacroDict[GuidList[Index]] + '.txt')
967
968 if (self.NoDscFileChange (UpdTxtFile)):
969 # DSC has not been modified yet
970 # So don't have to re-generate other files
971 self.Error = 'No DSC file change, skip to create UPD TXT file'
972 return 256
973
974 TxtFd = open(UpdTxtFile, "w")
975 TxtFd.write("%s\n" % (__copyright_txt__ % date.today().year))
976
977 NextOffset = 0
978 SpaceIdx = 0
979 StartAddr = 0
980 EndAddr = 0
981 Default = 'DEFAULT|'
982 InRange = False
983 for Item in self._CfgItemList:
984 if Item['cname'] == 'Signature' and str(Item['value'])[0:6] == SignatureList[Index]:
985 StartAddr = Item['offset']
986 NextOffset = StartAddr
987 InRange = True
988 if Item['cname'] == 'UpdTerminator' and InRange == True:
989 EndAddr = Item['offset']
990 InRange = False
991 InRange = False
992 for Item in self._CfgItemList:
993 if Item['cname'] == 'Signature' and str(Item['value'])[0:6] == SignatureList[Index]:
994 InRange = True
995 if InRange != True:
996 continue
997 if Item['cname'] == 'UpdTerminator':
998 InRange = False
999 if Item['region'] != 'UPD':
1000 continue
1001 Offset = Item['offset']
1002 if StartAddr > Offset or EndAddr < Offset:
1003 continue
1004 if NextOffset < Offset:
1005 # insert one line
1006 TxtFd.write("%s.UnusedUpdSpace%d|%s0x%04X|0x%04X|{0}\n" % (Item['space'], SpaceIdx, Default, NextOffset - StartAddr, Offset - NextOffset))
1007 SpaceIdx = SpaceIdx + 1
1008 NextOffset = Offset + Item['length']
1009 TxtFd.write("%s.%s|%s0x%04X|%s|%s\n" % (Item['space'],Item['cname'],Default,Item['offset'] - StartAddr,Item['length'],Item['value']))
1010 TxtFd.close()
1011 return 0
1012
1013 def CreateVarDict (self):
1014 Error = 0
1015 self._VarDict = {}
1016 if len(self._CfgItemList) > 0:
1017 Item = self._CfgItemList[-1]
1018 self._VarDict['_LENGTH_'] = '%d' % (Item['offset'] + Item['length'])
1019 for Item in self._CfgItemList:
1020 Embed = Item['embed']
1021 Match = re.match("^(\w+):(\w+):(START|END)", Embed)
1022 if Match:
1023 StructName = Match.group(1)
1024 VarName = '_%s_%s_' % (Match.group(3), StructName)
1025 if Match.group(3) == 'END':
1026 self._VarDict[VarName] = Item['offset'] + Item['length']
1027 self._VarDict['_LENGTH_%s_' % StructName] = \
1028 self._VarDict['_END_%s_' % StructName] - self._VarDict['_START_%s_' % StructName]
1029 if Match.group(2).startswith('TAG_'):
1030 if (self.Mode != 'FSP') and (self._VarDict['_LENGTH_%s_' % StructName] % 4):
1031 raise Exception("Size of structure '%s' is %d, not DWORD aligned !" % (StructName, self._VarDict['_LENGTH_%s_' % StructName]))
1032 self._VarDict['_TAG_%s_' % StructName] = int (Match.group(2)[4:], 16) & 0xFFF
1033 else:
1034 self._VarDict[VarName] = Item['offset']
1035 if Item['marker']:
1036 self._VarDict['_OFFSET_%s_' % Item['marker'].strip()] = Item['offset']
1037 return Error
1038
1039 def UpdateBsfBitUnit (self, Item):
1040 BitTotal = 0
1041 BitOffset = 0
1042 StartIdx = 0
1043 Unit = None
1044 UnitDec = {1:'BYTE', 2:'WORD', 4:'DWORD', 8:'QWORD'}
1045 for Idx, SubItem in enumerate(Item['subreg']):
1046 if Unit is None:
1047 Unit = SubItem['bitunit']
1048 BitLength = SubItem['bitlength']
1049 BitTotal += BitLength
1050 BitOffset += BitLength
1051
1052 if BitOffset > 64 or BitOffset > Unit * 8:
1053 break
1054
1055 if BitOffset == Unit * 8:
1056 for SubIdx in range (StartIdx, Idx + 1):
1057 Item['subreg'][SubIdx]['bitunit'] = Unit
1058 BitOffset = 0
1059 StartIdx = Idx + 1
1060 Unit = None
1061
1062 if BitOffset > 0:
1063 raise Exception ("Bit fields cannot fit into %s for '%s.%s' !" % (UnitDec[Unit], Item['cname'], SubItem['cname']))
1064
1065 ExpectedTotal = Item['length'] * 8
1066 if Item['length'] * 8 != BitTotal:
1067 raise Exception ("Bit fields total length (%d) does not match length (%d) of '%s' !" % (BitTotal, ExpectedTotal, Item['cname']))
1068
1069 def UpdateDefaultValue (self):
1070 Error = 0
1071 for Idx, Item in enumerate(self._CfgItemList):
1072 if len(Item['subreg']) == 0:
1073 Value = Item['value']
1074 if (len(Value) > 0) and (Value[0] == '{' or Value[0] == "'" or Value[0] == '"'):
1075 # {XXX} or 'XXX' strings
1076 self.FormatListValue(self._CfgItemList[Idx])
1077 else:
1078 Match = re.match("(0x[0-9a-fA-F]+|[0-9]+)", Value)
1079 if not Match:
1080 NumValue = self.EvaluateExpress (Value)
1081 Item['value'] = '0x%X' % NumValue
1082 else:
1083 ValArray = self.ValueToByteArray (Item['value'], Item['length'])
1084 for SubItem in Item['subreg']:
1085 SubItem['value'] = self.GetBsfBitFields(SubItem, ValArray)
1086 self.UpdateBsfBitUnit (Item)
1087 return Error
1088
1089 def ProcessMultilines (self, String, MaxCharLength):
1090 Multilines = ''
1091 StringLength = len(String)
1092 CurrentStringStart = 0
1093 StringOffset = 0
1094 BreakLineDict = []
1095 if len(String) <= MaxCharLength:
1096 while (StringOffset < StringLength):
1097 if StringOffset >= 1:
1098 if String[StringOffset - 1] == '\\' and String[StringOffset] == 'n':
1099 BreakLineDict.append (StringOffset + 1)
1100 StringOffset += 1
1101 if BreakLineDict != []:
1102 for Each in BreakLineDict:
1103 Multilines += " %s\n" % String[CurrentStringStart:Each].lstrip()
1104 CurrentStringStart = Each
1105 if StringLength - CurrentStringStart > 0:
1106 Multilines += " %s\n" % String[CurrentStringStart:].lstrip()
1107 else:
1108 Multilines = " %s\n" % String
1109 else:
1110 NewLineStart = 0
1111 NewLineCount = 0
1112 FoundSpaceChar = False
1113 while (StringOffset < StringLength):
1114 if StringOffset >= 1:
1115 if NewLineCount >= MaxCharLength - 1:
1116 if String[StringOffset] == ' ' and StringLength - StringOffset > 10:
1117 BreakLineDict.append (NewLineStart + NewLineCount)
1118 NewLineStart = NewLineStart + NewLineCount
1119 NewLineCount = 0
1120 FoundSpaceChar = True
1121 elif StringOffset == StringLength - 1 and FoundSpaceChar == False:
1122 BreakLineDict.append (0)
1123 if String[StringOffset - 1] == '\\' and String[StringOffset] == 'n':
1124 BreakLineDict.append (StringOffset + 1)
1125 NewLineStart = StringOffset + 1
1126 NewLineCount = 0
1127 StringOffset += 1
1128 NewLineCount += 1
1129 if BreakLineDict != []:
1130 BreakLineDict.sort ()
1131 for Each in BreakLineDict:
1132 if Each > 0:
1133 Multilines += " %s\n" % String[CurrentStringStart:Each].lstrip()
1134 CurrentStringStart = Each
1135 if StringLength - CurrentStringStart > 0:
1136 Multilines += " %s\n" % String[CurrentStringStart:].lstrip()
1137 return Multilines
1138
1139 def CreateField (self, Item, Name, Length, Offset, Struct, BsfName, Help, Option, BitsLength = None):
1140 PosName = 28
1141 PosComment = 30
1142 NameLine=''
1143 HelpLine=''
1144 OptionLine=''
1145
1146 if Length == 0 and Name == 'Dummy':
1147 return '\n'
1148
1149 IsArray = False
1150 if Length in [1,2,4,8]:
1151 Type = "UINT%d" % (Length * 8)
1152 if Name.startswith("UnusedUpdSpace") and Length != 1:
1153 IsArray = True
1154 Type = "UINT8"
1155 else:
1156 IsArray = True
1157 Type = "UINT8"
1158
1159 if Item and Item['value'].startswith('{'):
1160 Type = "UINT8"
1161 IsArray = True
1162
1163 if Struct != '':
1164 Type = Struct
1165 if Struct in ['UINT8','UINT16','UINT32','UINT64']:
1166 IsArray = True
1167 Unit = int(Type[4:]) / 8
1168 Length = Length / Unit
1169 else:
1170 IsArray = False
1171
1172 if IsArray:
1173 Name = Name + '[%d]' % Length
1174
1175 if len(Type) < PosName:
1176 Space1 = PosName - len(Type)
1177 else:
1178 Space1 = 1
1179
1180 if BsfName != '':
1181 NameLine=" - %s\n" % BsfName
1182 else:
1183 NameLine="\n"
1184
1185 if Help != '':
1186 HelpLine = self.ProcessMultilines (Help, 80)
1187
1188 if Option != '':
1189 OptionLine = self.ProcessMultilines (Option, 80)
1190
1191 if Offset is None:
1192 OffsetStr = '????'
1193 else:
1194 OffsetStr = '0x%04X' % Offset
1195
1196 if BitsLength is None:
1197 BitsLength = ''
1198 else:
1199 BitsLength = ' : %d' % BitsLength
1200
1201 return "\n/** Offset %s%s%s%s**/\n %s%s%s%s;\n" % (OffsetStr, NameLine, HelpLine, OptionLine, Type, ' ' * Space1, Name, BitsLength)
1202
1203 def PostProcessBody (self, TextBody):
1204 NewTextBody = []
1205 OldTextBody = []
1206 IncludeLine = False
1207 StructName = ''
1208 VariableName = ''
1209 IsUpdHdrDefined = False
1210 IsUpdHeader = False
1211 for Line in TextBody:
1212 SplitToLines = Line.splitlines()
1213 MatchComment = re.match("^/\*\sCOMMENT:(\w+):([\w|\W|\s]+)\s\*/\s([\s\S]*)", SplitToLines[0])
1214 if MatchComment:
1215 if MatchComment.group(1) == 'FSP_UPD_HEADER':
1216 IsUpdHeader = True
1217 else:
1218 IsUpdHeader = False
1219 if IsUpdHdrDefined != True or IsUpdHeader != True:
1220 CommentLine = " " + MatchComment.group(2) + "\n"
1221 NewTextBody.append("/**" + CommentLine + "**/\n")
1222 Line = Line[(len(SplitToLines[0]) + 1):]
1223
1224 Match = re.match("^/\*\sEMBED_STRUCT:(\w+):(\w+):(START|END)\s\*/\s([\s\S]*)", Line)
1225 if Match:
1226 Line = Match.group(4)
1227 if Match.group(1) == 'FSP_UPD_HEADER':
1228 IsUpdHeader = True
1229 else:
1230 IsUpdHeader = False
1231
1232 if Match and Match.group(3) == 'START':
1233 if IsUpdHdrDefined != True or IsUpdHeader != True:
1234 NewTextBody.append ('typedef struct {\n')
1235 StructName = Match.group(1)
1236 VariableName = Match.group(2)
1237 MatchOffset = re.search('/\*\*\sOffset\s0x([a-fA-F0-9]+)', Line)
1238 if MatchOffset:
1239 Offset = int(MatchOffset.group(1), 16)
1240 else:
1241 Offset = None
1242 Line
1243 IncludeLine = True
1244 OldTextBody.append (self.CreateField (None, VariableName, 0, Offset, StructName, '', '', ''))
1245 if IncludeLine:
1246 if IsUpdHdrDefined != True or IsUpdHeader != True:
1247 NewTextBody.append (Line)
1248 else:
1249 OldTextBody.append (Line)
1250
1251 if Match and Match.group(3) == 'END':
1252 if (StructName != Match.group(1)) or (VariableName != Match.group(2)):
1253 print ("Unmatched struct name '%s' and '%s' !" % (StructName, Match.group(1)))
1254 else:
1255 if IsUpdHdrDefined != True or IsUpdHeader != True:
1256 NewTextBody.append ('} %s;\n\n' % StructName)
1257 IsUpdHdrDefined = True
1258 IncludeLine = False
1259 NewTextBody.extend(OldTextBody)
1260 return NewTextBody
1261
1262 def WriteLinesWithoutTailingSpace (self, HeaderFd, Line):
1263 TxtBody2 = Line.splitlines(True)
1264 for Line2 in TxtBody2:
1265 Line2 = Line2.rstrip()
1266 Line2 += '\n'
1267 HeaderFd.write (Line2)
1268 return 0
1269 def CreateHeaderFile (self, InputHeaderFile):
1270 FvDir = self._FvDir
1271
1272 HeaderFileName = 'FspUpd.h'
1273 HeaderFile = os.path.join(FvDir, HeaderFileName)
1274
1275 # Check if header needs to be recreated
1276 if (self.NoDscFileChange (HeaderFile)):
1277 # DSC has not been modified yet
1278 # So don't have to re-generate other files
1279 self.Error = 'No DSC file change, skip to create UPD header file'
1280 return 256
1281
1282 TxtBody = []
1283 for Item in self._CfgItemList:
1284 if str(Item['cname']) == 'Signature' and Item['length'] == 8:
1285 Value = int(Item['value'], 16)
1286 Chars = []
1287 while Value != 0x0:
1288 Chars.append(chr(Value & 0xFF))
1289 Value = Value >> 8
1290 SignatureStr = ''.join(Chars)
1291 # Signature will be _T / _M / _S / _I for FSPT / FSPM / FSPS /FSPI accordingly
1292 if '_T' in SignatureStr[6:6+2]:
1293 TxtBody.append("#define FSPT_UPD_SIGNATURE %s /* '%s' */\n\n" % (Item['value'], SignatureStr))
1294 elif '_M' in SignatureStr[6:6+2]:
1295 TxtBody.append("#define FSPM_UPD_SIGNATURE %s /* '%s' */\n\n" % (Item['value'], SignatureStr))
1296 elif '_S' in SignatureStr[6:6+2]:
1297 TxtBody.append("#define FSPS_UPD_SIGNATURE %s /* '%s' */\n\n" % (Item['value'], SignatureStr))
1298 elif '_I' in SignatureStr[6:6+2]:
1299 TxtBody.append("#define FSPI_UPD_SIGNATURE %s /* '%s' */\n\n" % (Item['value'], SignatureStr))
1300 TxtBody.append("\n")
1301
1302 for Region in ['UPD']:
1303 UpdOffsetTable = []
1304 UpdSignature = ['0x545F', '0x4D5F', '0x535F', '0x495F'] #['_T', '_M', '_S', '_I'] signature for FSPT, FSPM, FSPS, FSPI
1305 UpdStructure = ['FSPT_UPD', 'FSPM_UPD', 'FSPS_UPD', 'FSPI_UPD']
1306 for Item in self._CfgItemList:
1307 if Item["cname"] == 'Signature' and Item["value"][0:6] in UpdSignature:
1308 Item["offset"] = 0 # re-initialize offset to 0 when new UPD structure starting
1309 UpdOffsetTable.append (Item["offset"])
1310
1311 for UpdIdx in range(len(UpdOffsetTable)):
1312 CommentLine = ""
1313 for Item in self._CfgItemList:
1314 if Item["comment"] != '' and Item["offset"] >= UpdOffsetTable[UpdIdx]:
1315 MatchComment = re.match("^(U|V)PD_DATA_REGION:([\w|\W|\s]+)", Item["comment"])
1316 if MatchComment and MatchComment.group(1) == Region[0]:
1317 CommentLine = " " + MatchComment.group(2) + "\n"
1318 TxtBody.append("/**" + CommentLine + "**/\n")
1319 elif Item["offset"] >= UpdOffsetTable[UpdIdx] and Item["comment"] == '':
1320 Match = re.match("^FSP([\w|\W|\s])_UPD", UpdStructure[UpdIdx])
1321 if Match:
1322 TxtBody.append("/** Fsp " + Match.group(1) + " UPD Configuration\n**/\n")
1323 TxtBody.append("typedef struct {\n")
1324 NextOffset = 0
1325 SpaceIdx = 0
1326 Offset = 0
1327
1328 LastVisible = True
1329 ResvOffset = 0
1330 ResvIdx = 0
1331 LineBuffer = []
1332 InRange = False
1333 for Item in self._CfgItemList:
1334 if Item['cname'] == 'Signature' and str(Item['value'])[0:6] == UpdSignature[UpdIdx] or Region[0] == 'V':
1335 InRange = True
1336 if InRange != True:
1337 continue
1338 if Item['cname'] == 'UpdTerminator':
1339 InRange = False
1340
1341 if Item['region'] != Region:
1342 continue
1343
1344 if Item["offset"] < UpdOffsetTable[UpdIdx]:
1345 continue
1346
1347 NextVisible = LastVisible
1348
1349 if LastVisible and (Item['header'] == 'OFF'):
1350 NextVisible = False
1351 ResvOffset = Item['offset']
1352 elif (not LastVisible) and Item['header'] == 'ON':
1353 NextVisible = True
1354 Name = "Reserved" + Region[0] + "pdSpace%d" % ResvIdx
1355 ResvIdx = ResvIdx + 1
1356 TxtBody.append(self.CreateField (Item, Name, Item["offset"] - ResvOffset, ResvOffset, '', '', '', ''))
1357
1358 if Offset < Item["offset"]:
1359 if LastVisible:
1360 Name = "Unused" + Region[0] + "pdSpace%d" % SpaceIdx
1361 LineBuffer.append(self.CreateField (Item, Name, Item["offset"] - Offset, Offset, '', '', '', ''))
1362 SpaceIdx = SpaceIdx + 1
1363 Offset = Item["offset"]
1364
1365 LastVisible = NextVisible
1366
1367 Offset = Offset + Item["length"]
1368 if LastVisible:
1369 for Each in LineBuffer:
1370 TxtBody.append (Each)
1371 LineBuffer = []
1372 Comment = Item["comment"]
1373 Embed = Item["embed"].upper()
1374 if Embed.endswith(':START') or Embed.endswith(':END'):
1375 if not Comment == '' and Embed.endswith(':START'):
1376 Marker = '/* COMMENT:%s */ \n' % Item["comment"]
1377 Marker = Marker + '/* EMBED_STRUCT:%s */ ' % Item["embed"]
1378 else:
1379 Marker = '/* EMBED_STRUCT:%s */ ' % Item["embed"]
1380 else:
1381 if Embed == '':
1382 Marker = ''
1383 else:
1384 self.Error = "Invalid embedded structure format '%s'!\n" % Item["embed"]
1385 return 4
1386 Line = Marker + self.CreateField (Item, Item["cname"], Item["length"], Item["offset"], Item['struct'], Item['name'], Item['help'], Item['option'])
1387 TxtBody.append(Line)
1388 if Item['cname'] == 'UpdTerminator':
1389 break
1390 TxtBody.append("} " + UpdStructure[UpdIdx] + ";\n\n")
1391
1392 # Handle the embedded data structure
1393 TxtBody = self.PostProcessBody (TxtBody)
1394
1395 HeaderTFileName = 'FsptUpd.h'
1396 HeaderMFileName = 'FspmUpd.h'
1397 HeaderSFileName = 'FspsUpd.h'
1398 HeaderIFileName = 'FspiUpd.h'
1399
1400 UpdRegionCheck = ['FSPT', 'FSPM', 'FSPS', 'FSPI'] # FSPX_UPD_REGION
1401 UpdConfigCheck = ['FSP_T', 'FSP_M', 'FSP_S', 'FSP_I'] # FSP_X_CONFIG, FSP_X_TEST_CONFIG, FSP_X_RESTRICTED_CONFIG
1402 UpdSignatureCheck = ['FSPT_UPD_SIGNATURE', 'FSPM_UPD_SIGNATURE', 'FSPS_UPD_SIGNATURE', 'FSPI_UPD_SIGNATURE']
1403 ExcludedSpecificUpd = ['FSPT_ARCH_UPD', 'FSPM_ARCH_UPD', 'FSPS_ARCH_UPD', 'FSPI_ARCH_UPD']
1404 ExcludedSpecificUpd1 = ['FSPT_ARCH2_UPD', 'FSPM_ARCH2_UPD', 'FSPS_ARCH2_UPD']
1405
1406 IncLines = []
1407 if InputHeaderFile != '':
1408 if not os.path.exists(InputHeaderFile):
1409 self.Error = "Input header file '%s' does not exist" % InputHeaderFile
1410 return 6
1411
1412 InFd = open(InputHeaderFile, "r")
1413 IncLines = InFd.readlines()
1414 InFd.close()
1415
1416 for item in range(len(UpdRegionCheck)):
1417 if UpdRegionCheck[item] == 'FSPT':
1418 HeaderFd = open(os.path.join(FvDir, HeaderTFileName), "w")
1419 FileBase = os.path.basename(os.path.join(FvDir, HeaderTFileName))
1420 elif UpdRegionCheck[item] == 'FSPM':
1421 HeaderFd = open(os.path.join(FvDir, HeaderMFileName), "w")
1422 FileBase = os.path.basename(os.path.join(FvDir, HeaderMFileName))
1423 elif UpdRegionCheck[item] == 'FSPS':
1424 HeaderFd = open(os.path.join(FvDir, HeaderSFileName), "w")
1425 FileBase = os.path.basename(os.path.join(FvDir, HeaderSFileName))
1426 elif UpdRegionCheck[item] == 'FSPI':
1427 HeaderFd = open(os.path.join(FvDir, HeaderIFileName), "w")
1428 FileBase = os.path.basename(os.path.join(FvDir, HeaderIFileName))
1429 FileName = FileBase.replace(".", "_").upper()
1430 HeaderFd.write("%s\n" % (__copyright_h__ % date.today().year))
1431 HeaderFd.write("#ifndef __%s__\n" % FileName)
1432 HeaderFd.write("#define __%s__\n\n" % FileName)
1433 HeaderFd.write("#include <%s>\n\n" % HeaderFileName)
1434 HeaderFd.write("#pragma pack(1)\n\n")
1435
1436 Export = False
1437 for Line in IncLines:
1438 Match = re.search ("!EXPORT\s+([A-Z]+)\s+EXTERNAL_BOOTLOADER_STRUCT_(BEGIN|END)\s+", Line)
1439 if Match:
1440 if Match.group(2) == "BEGIN" and Match.group(1) == UpdRegionCheck[item]:
1441 Export = True
1442 continue
1443 else:
1444 Export = False
1445 continue
1446 if Export:
1447 HeaderFd.write(Line)
1448 HeaderFd.write("\n")
1449
1450 Index = 0
1451 StartIndex = 0
1452 EndIndex = 0
1453 StructStart = []
1454 StructStartWithComment = []
1455 StructEnd = []
1456 for Line in TxtBody:
1457 Index += 1
1458 Match = re.match("(typedef struct {)", Line)
1459 if Match:
1460 StartIndex = Index - 1
1461 Match = re.match("}\s([_A-Z0-9]+);", Line)
1462 if Match and (UpdRegionCheck[item] in Match.group(1) or UpdConfigCheck[item] in Match.group(1)) and (ExcludedSpecificUpd[item] not in Match.group(1)) and (ExcludedSpecificUpd1[item] not in Match.group(1)):
1463 EndIndex = Index
1464 StructStart.append(StartIndex)
1465 StructEnd.append(EndIndex)
1466 Index = 0
1467 for Line in TxtBody:
1468 Index += 1
1469 for Item in range(len(StructStart)):
1470 if Index == StructStart[Item]:
1471 Match = re.match("^(/\*\*\s*)", Line)
1472 if Match:
1473 StructStartWithComment.append(StructStart[Item])
1474 else:
1475 StructStartWithComment.append(StructStart[Item] + 1)
1476 Index = 0
1477 for Line in TxtBody:
1478 Index += 1
1479 for Item in range(len(StructStart)):
1480 if Index >= StructStartWithComment[Item] and Index <= StructEnd[Item]:
1481 self.WriteLinesWithoutTailingSpace(HeaderFd, Line)
1482 HeaderFd.write("#pragma pack()\n\n")
1483 HeaderFd.write("#endif\n")
1484 HeaderFd.close()
1485
1486 HeaderFd = open(HeaderFile, "w")
1487 FileBase = os.path.basename(HeaderFile)
1488 FileName = FileBase.replace(".", "_").upper()
1489 HeaderFd.write("%s\n" % (__copyright_h__ % date.today().year))
1490 HeaderFd.write("#ifndef __%s__\n" % FileName)
1491 HeaderFd.write("#define __%s__\n\n" % FileName)
1492 HeaderFd.write("#include <FspEas.h>\n\n")
1493 HeaderFd.write("#pragma pack(1)\n\n")
1494
1495 for item in range(len(UpdRegionCheck)):
1496 Index = 0
1497 StartIndex = 0
1498 EndIndex = 0
1499 StructStart = []
1500 StructStartWithComment = []
1501 StructEnd = []
1502 for Line in TxtBody:
1503 Index += 1
1504 Match = re.match("(typedef struct {)", Line)
1505 if Match:
1506 StartIndex = Index - 1
1507 Match = re.match("#define\s([_A-Z0-9]+)\s*", Line)
1508 if Match and (UpdSignatureCheck[item] in Match.group(1) or UpdSignatureCheck[item] in Match.group(1)):
1509 StructStart.append(Index - 1)
1510 StructEnd.append(Index)
1511 Index = 0
1512 for Line in TxtBody:
1513 Index += 1
1514 for Item in range(len(StructStart)):
1515 if Index == StructStart[Item]:
1516 Match = re.match("^(/\*\*\s*)", Line)
1517 if Match:
1518 StructStartWithComment.append(StructStart[Item])
1519 else:
1520 StructStartWithComment.append(StructStart[Item] + 1)
1521 Index = 0
1522 for Line in TxtBody:
1523 Index += 1
1524 for Item in range(len(StructStart)):
1525 if Index >= StructStartWithComment[Item] and Index <= StructEnd[Item]:
1526 self.WriteLinesWithoutTailingSpace(HeaderFd, Line)
1527 HeaderFd.write("#pragma pack()\n\n")
1528 HeaderFd.write("#endif\n")
1529 HeaderFd.close()
1530
1531 return 0
1532
1533 def WriteBsfStruct (self, BsfFd, Item):
1534 LogExpr = CLogicalExpression()
1535 if Item['type'] == "None":
1536 Space = "gPlatformFspPkgTokenSpaceGuid"
1537 else:
1538 Space = Item['space']
1539 Line = " $%s_%s" % (Space, Item['cname'])
1540 Match = re.match("\s*\{([x0-9a-fA-F,\s]+)\}\s*", Item['value'])
1541 if Match:
1542 DefaultValue = Match.group(1).strip()
1543 else:
1544 DefaultValue = Item['value'].strip()
1545 if 'bitlength' in Item:
1546 BsfFd.write(" %s%s%4d bits $_DEFAULT_ = %s\n" % (Line, ' ' * (64 - len(Line)), Item['bitlength'], DefaultValue))
1547 else:
1548 BsfFd.write(" %s%s%4d bytes $_DEFAULT_ = %s\n" % (Line, ' ' * (64 - len(Line)), Item['length'], DefaultValue))
1549 TmpList = []
1550 if Item['type'] == "Combo":
1551 if not Item['option'] in self._BuidinOption:
1552 OptList = Item['option'].split(',')
1553 for Option in OptList:
1554 Option = Option.strip()
1555 (OpVal, OpStr) = Option.split(':')
1556 test = LogExpr.getNumber (OpVal)
1557 if test is None:
1558 raise Exception("Selection Index '%s' is not a number" % OpVal)
1559 TmpList.append((OpVal, OpStr))
1560 return TmpList
1561
1562 def WriteBsfOption (self, BsfFd, Item):
1563 PcdName = Item['space'] + '_' + Item['cname']
1564 WriteHelp = 0
1565 if Item['type'] == "Combo":
1566 if Item['option'] in self._BuidinOption:
1567 Options = self._BuidinOption[Item['option']]
1568 else:
1569 Options = PcdName
1570 BsfFd.write(' %s $%s, "%s", &%s,\n' % (Item['type'], PcdName, Item['name'], Options))
1571 WriteHelp = 1
1572 elif Item['type'].startswith("EditNum"):
1573 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'])
1574 if Match:
1575 BsfFd.write(' EditNum $%s, "%s", %s,\n' % (PcdName, Item['name'], Match.group(1)))
1576 WriteHelp = 2
1577 elif Item['type'].startswith("EditText"):
1578 BsfFd.write(' %s $%s, "%s",\n' % (Item['type'], PcdName, Item['name']))
1579 WriteHelp = 1
1580 elif Item['type'] == "Table":
1581 Columns = Item['option'].split(',')
1582 if len(Columns) != 0:
1583 BsfFd.write(' %s $%s "%s",' % (Item['type'], PcdName, Item['name']))
1584 for Col in Columns:
1585 Fmt = Col.split(':')
1586 if len(Fmt) != 3:
1587 raise Exception("Column format '%s' is invalid !" % Fmt)
1588 try:
1589 Dtype = int(Fmt[1].strip())
1590 except:
1591 raise Exception("Column size '%s' is invalid !" % Fmt[1])
1592 BsfFd.write('\n Column "%s", %d bytes, %s' % (Fmt[0].strip(), Dtype, Fmt[2].strip()))
1593 BsfFd.write(',\n')
1594 WriteHelp = 1
1595
1596 if WriteHelp > 0:
1597 HelpLines = Item['help'].split('\\n\\r')
1598 FirstLine = True
1599 for HelpLine in HelpLines:
1600 if FirstLine:
1601 FirstLine = False
1602 BsfFd.write(' Help "%s"\n' % (HelpLine))
1603 else:
1604 BsfFd.write(' "%s"\n' % (HelpLine))
1605 if WriteHelp == 2:
1606 BsfFd.write(' "Valid range: %s ~ %s"\n' % (Match.group(2), Match.group(3)))
1607
1608 def GenerateBsfFile (self, BsfFile):
1609
1610 if BsfFile == '':
1611 self.Error = "BSF output file '%s' is invalid" % BsfFile
1612 return 1
1613
1614 if (self.NoDscFileChange (BsfFile)):
1615 # DSC has not been modified yet
1616 # So don't have to re-generate other files
1617 self.Error = 'No DSC file change, skip to create UPD BSF file'
1618 return 256
1619
1620 Error = 0
1621 OptionDict = {}
1622 BsfFd = open(BsfFile, "w")
1623 BsfFd.write("%s\n" % (__copyright_bsf__ % date.today().year))
1624 BsfFd.write("%s\n" % self._GlobalDataDef)
1625 BsfFd.write("StructDef\n")
1626 NextOffset = -1
1627 for Item in self._CfgItemList:
1628 if Item['find'] != '':
1629 BsfFd.write('\n Find "%s"\n' % Item['find'])
1630 NextOffset = Item['offset'] + Item['length']
1631 if Item['name'] != '':
1632 if NextOffset != Item['offset']:
1633 BsfFd.write(" Skip %d bytes\n" % (Item['offset'] - NextOffset))
1634 if len(Item['subreg']) > 0:
1635 NextOffset = Item['offset']
1636 BitsOffset = NextOffset * 8
1637 for SubItem in Item['subreg']:
1638 BitsOffset += SubItem['bitlength']
1639 if SubItem['name'] == '':
1640 if 'bitlength' in SubItem:
1641 BsfFd.write(" Skip %d bits\n" % (SubItem['bitlength']))
1642 else:
1643 BsfFd.write(" Skip %d bytes\n" % (SubItem['length']))
1644 else:
1645 Options = self.WriteBsfStruct(BsfFd, SubItem)
1646 if len(Options) > 0:
1647 OptionDict[SubItem['space']+'_'+SubItem['cname']] = Options
1648
1649 NextBitsOffset = (Item['offset'] + Item['length']) * 8
1650 if NextBitsOffset > BitsOffset:
1651 BitsGap = NextBitsOffset - BitsOffset
1652 BitsRemain = BitsGap % 8
1653 if BitsRemain:
1654 BsfFd.write(" Skip %d bits\n" % BitsRemain)
1655 BitsGap -= BitsRemain
1656 BytesRemain = int(BitsGap / 8)
1657 if BytesRemain:
1658 BsfFd.write(" Skip %d bytes\n" % BytesRemain)
1659 NextOffset = Item['offset'] + Item['length']
1660 else:
1661 NextOffset = Item['offset'] + Item['length']
1662 Options = self.WriteBsfStruct(BsfFd, Item)
1663 if len(Options) > 0:
1664 OptionDict[Item['space']+'_'+Item['cname']] = Options
1665 BsfFd.write("\nEndStruct\n\n")
1666
1667 BsfFd.write("%s" % self._BuidinOptionTxt)
1668
1669 for Each in OptionDict:
1670 BsfFd.write("List &%s\n" % Each)
1671 for Item in OptionDict[Each]:
1672 BsfFd.write(' Selection %s , "%s"\n' % (Item[0], Item[1]))
1673 BsfFd.write("EndList\n\n")
1674
1675 BsfFd.write("BeginInfoBlock\n")
1676 BsfFd.write(' PPVer "%s"\n' % (self._CfgBlkDict['ver']))
1677 BsfFd.write(' Description "%s"\n' % (self._CfgBlkDict['name']))
1678 BsfFd.write("EndInfoBlock\n\n")
1679
1680 for Each in self._CfgPageDict:
1681 BsfFd.write('Page "%s"\n' % self._CfgPageDict[Each])
1682 BsfItems = []
1683 for Item in self._CfgItemList:
1684 if Item['name'] != '':
1685 if Item['page'] != Each:
1686 continue
1687 if len(Item['subreg']) > 0:
1688 for SubItem in Item['subreg']:
1689 if SubItem['name'] != '':
1690 BsfItems.append(SubItem)
1691 else:
1692 BsfItems.append(Item)
1693
1694 BsfItems.sort(key=lambda x: x['order'])
1695
1696 for Item in BsfItems:
1697 self.WriteBsfOption (BsfFd, Item)
1698 BsfFd.write("EndPage\n\n")
1699
1700 BsfFd.close()
1701 return Error
1702
1703
1704 def Usage():
1705 print ("GenCfgOpt Version 0.58")
1706 print ("Usage:")
1707 print (" GenCfgOpt UPDTXT PlatformDscFile BuildFvDir [-D Macros]")
1708 print (" GenCfgOpt HEADER PlatformDscFile BuildFvDir InputHFile [-D Macros]")
1709 print (" GenCfgOpt GENBSF PlatformDscFile BuildFvDir BsfOutFile [-D Macros]")
1710
1711 def Main():
1712 #
1713 # Parse the options and args
1714 #
1715 i = 1
1716
1717 GenCfgOpt = CGenCfgOpt()
1718 while i < len(sys.argv):
1719 if sys.argv[i].strip().lower() == "--pcd":
1720 BuildOptionPcd.append(sys.argv[i+1])
1721 i += 1
1722 i += 1
1723 argc = len(sys.argv)
1724 if argc < 4:
1725 Usage()
1726 return 1
1727 else:
1728 DscFile = sys.argv[2]
1729 if not os.path.exists(DscFile):
1730 print ("ERROR: Cannot open DSC file '%s' !" % DscFile)
1731 return 2
1732
1733 OutFile = ''
1734 if argc > 4:
1735 if sys.argv[4][0] == '-':
1736 Start = 4
1737 else:
1738 OutFile = sys.argv[4]
1739 Start = 5
1740 if argc > Start:
1741 if GenCfgOpt.ParseMacros(sys.argv[Start:]) != 0:
1742 print ("ERROR: Macro parsing failed !")
1743 return 3
1744
1745 FvDir = sys.argv[3]
1746 if not os.path.exists(FvDir):
1747 os.makedirs(FvDir)
1748
1749 if GenCfgOpt.ParseDscFile(DscFile, FvDir) != 0:
1750 print ("ERROR: %s !" % GenCfgOpt.Error)
1751 return 5
1752
1753 if GenCfgOpt.UpdateSubRegionDefaultValue() != 0:
1754 print ("ERROR: %s !" % GenCfgOpt.Error)
1755 return 7
1756
1757 if sys.argv[1] == "UPDTXT":
1758 Ret = GenCfgOpt.CreateSplitUpdTxt(OutFile)
1759 if Ret != 0:
1760 # No change is detected
1761 if Ret == 256:
1762 print ("INFO: %s !" % (GenCfgOpt.Error))
1763 else :
1764 print ("ERROR: %s !" % (GenCfgOpt.Error))
1765 return Ret
1766 elif sys.argv[1] == "HEADER":
1767 Ret = GenCfgOpt.CreateHeaderFile(OutFile)
1768 if Ret != 0:
1769 # No change is detected
1770 if Ret == 256:
1771 print ("INFO: %s !" % (GenCfgOpt.Error))
1772 else :
1773 print ("ERROR: %s !" % (GenCfgOpt.Error))
1774 return 8
1775 return Ret
1776 elif sys.argv[1] == "GENBSF":
1777 Ret = GenCfgOpt.GenerateBsfFile(OutFile)
1778 if Ret != 0:
1779 # No change is detected
1780 if Ret == 256:
1781 print ("INFO: %s !" % (GenCfgOpt.Error))
1782 else :
1783 print ("ERROR: %s !" % (GenCfgOpt.Error))
1784 return 9
1785 return Ret
1786 else:
1787 if argc < 5:
1788 Usage()
1789 return 1
1790 print ("ERROR: Unknown command '%s' !" % sys.argv[1])
1791 Usage()
1792 return 1
1793 return 0
1794 return 0
1795
1796
1797 if __name__ == '__main__':
1798 sys.exit(Main())