]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFsp2Pkg/Tools/GenCfgOpt.py
04b61a5672c8554eeef3382216d683b4a02e09fb
[mirror_edk2.git] / IntelFsp2Pkg / Tools / GenCfgOpt.py
1 ## @ GenCfgOpt.py
2 #
3 # Copyright (c) 2014 - 2018, Intel Corporation. All rights reserved.<BR>
4 # This program and the accompanying materials are licensed and made available under
5 # the terms and conditions of the BSD License that accompanies this distribution.
6 # The full text of the license may be found at
7 # http://opensource.org/licenses/bsd-license.php.
8 #
9 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11 #
12 ##
13
14 import os
15 import re
16 import sys
17 import struct
18 from datetime import date
19
20 # Generated file copyright header
21
22 __copyright_txt__ = """## @file
23 #
24 # THIS IS AUTO-GENERATED FILE BY BUILD TOOLS AND PLEASE DO NOT MAKE MODIFICATION.
25 #
26 # This file lists all VPD informations for a platform collected by build.exe.
27 #
28 # Copyright (c) %4d, Intel Corporation. All rights reserved.<BR>
29 # This program and the accompanying materials
30 # are licensed and made available under the terms and conditions of the BSD License
31 # which accompanies this distribution. The full text of the license may be found at
32 # http://opensource.org/licenses/bsd-license.php
33 #
34 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
35 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
36 #
37 """
38
39 __copyright_bsf__ = """/** @file
40
41 Boot Setting File for Platform Configuration.
42
43 Copyright (c) %4d, Intel Corporation. All rights reserved.<BR>
44 This program and the accompanying materials
45 are licensed and made available under the terms and conditions of the BSD License
46 which accompanies this distribution. The full text of the license may be found at
47 http://opensource.org/licenses/bsd-license.php
48
49 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
50 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
51
52 This file is automatically generated. Please do NOT modify !!!
53
54 **/
55
56 """
57
58 __copyright_h__ = """/** @file
59
60 Copyright (c) %4d, Intel Corporation. All rights reserved.<BR>
61
62 Redistribution and use in source and binary forms, with or without modification,
63 are permitted provided that the following conditions are met:
64
65 * Redistributions of source code must retain the above copyright notice, this
66 list of conditions and the following disclaimer.
67 * Redistributions in binary form must reproduce the above copyright notice, this
68 list of conditions and the following disclaimer in the documentation and/or
69 other materials provided with the distribution.
70 * Neither the name of Intel Corporation nor the names of its contributors may
71 be used to endorse or promote products derived from this software without
72 specific prior written permission.
73
74 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
75 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
76 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
77 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
78 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
79 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
80 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
81 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
82 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
83 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
84 THE POSSIBILITY OF SUCH DAMAGE.
85
86 This file is automatically generated. Please do NOT modify !!!
87
88 **/
89 """
90
91 class CLogicalExpression:
92 def __init__(self):
93 self.index = 0
94 self.string = ''
95
96 def errExit(self, err = ''):
97 print "ERROR: Express parsing for:"
98 print " %s" % self.string
99 print " %s^" % (' ' * self.index)
100 if err:
101 print "INFO : %s" % err
102 raise SystemExit
103
104 def getNonNumber (self, n1, n2):
105 if not n1.isdigit():
106 return n1
107 if not n2.isdigit():
108 return n2
109 return None
110
111 def getCurr(self, lens = 1):
112 try:
113 if lens == -1:
114 return self.string[self.index :]
115 else:
116 if self.index + lens > len(self.string):
117 lens = len(self.string) - self.index
118 return self.string[self.index : self.index + lens]
119 except Exception:
120 return ''
121
122 def isLast(self):
123 return self.index == len(self.string)
124
125 def moveNext(self, len = 1):
126 self.index += len
127
128 def skipSpace(self):
129 while not self.isLast():
130 if self.getCurr() in ' \t':
131 self.moveNext()
132 else:
133 return
134
135 def normNumber (self, val):
136 return True if val else False
137
138 def getNumber(self, var):
139 var = var.strip()
140 if re.match('^0x[a-fA-F0-9]+$', var):
141 value = int(var, 16)
142 elif re.match('^[+-]?\d+$', var):
143 value = int(var, 10)
144 else:
145 value = None
146 return value
147
148 def parseValue(self):
149 self.skipSpace()
150 var = ''
151 while not self.isLast():
152 char = self.getCurr()
153 if re.match('^[\w.]', char):
154 var += char
155 self.moveNext()
156 else:
157 break
158 val = self.getNumber(var)
159 if val is None:
160 value = var
161 else:
162 value = "%d" % val
163 return value
164
165 def parseSingleOp(self):
166 self.skipSpace()
167 if re.match('^NOT\W', self.getCurr(-1)):
168 self.moveNext(3)
169 op = self.parseBrace()
170 val = self.getNumber (op)
171 if val is None:
172 self.errExit ("'%s' is not a number" % op)
173 return "%d" % (not self.normNumber(int(op)))
174 else:
175 return self.parseValue()
176
177 def parseBrace(self):
178 self.skipSpace()
179 char = self.getCurr()
180 if char == '(':
181 self.moveNext()
182 value = self.parseExpr()
183 self.skipSpace()
184 if self.getCurr() != ')':
185 self.errExit ("Expecting closing brace or operator")
186 self.moveNext()
187 return value
188 else:
189 value = self.parseSingleOp()
190 return value
191
192 def parseCompare(self):
193 value = self.parseBrace()
194 while True:
195 self.skipSpace()
196 char = self.getCurr()
197 if char in ['<', '>']:
198 self.moveNext()
199 next = self.getCurr()
200 if next == '=':
201 op = char + next
202 self.moveNext()
203 else:
204 op = char
205 result = self.parseBrace()
206 test = self.getNonNumber(result, value)
207 if test is None:
208 value = "%d" % self.normNumber(eval (value + op + result))
209 else:
210 self.errExit ("'%s' is not a valid number for comparision" % test)
211 elif char in ['=', '!']:
212 op = self.getCurr(2)
213 if op in ['==', '!=']:
214 self.moveNext(2)
215 result = self.parseBrace()
216 test = self.getNonNumber(result, value)
217 if test is None:
218 value = "%d" % self.normNumber((eval (value + op + result)))
219 else:
220 value = "%d" % self.normNumber(eval ("'" + value + "'" + op + "'" + result + "'"))
221 else:
222 break
223 else:
224 break
225 return value
226
227 def parseAnd(self):
228 value = self.parseCompare()
229 while True:
230 self.skipSpace()
231 if re.match('^AND\W', self.getCurr(-1)):
232 self.moveNext(3)
233 result = self.parseCompare()
234 test = self.getNonNumber(result, value)
235 if test is None:
236 value = "%d" % self.normNumber(int(value) & int(result))
237 else:
238 self.errExit ("'%s' is not a valid op number for AND" % test)
239 else:
240 break
241 return value
242
243 def parseOrXor(self):
244 value = self.parseAnd()
245 op = None
246 while True:
247 self.skipSpace()
248 op = None
249 if re.match('^XOR\W', self.getCurr(-1)):
250 self.moveNext(3)
251 op = '^'
252 elif re.match('^OR\W', self.getCurr(-1)):
253 self.moveNext(2)
254 op = '|'
255 else:
256 break
257 if op:
258 result = self.parseAnd()
259 test = self.getNonNumber(result, value)
260 if test is None:
261 value = "%d" % self.normNumber(eval (value + op + result))
262 else:
263 self.errExit ("'%s' is not a valid op number for XOR/OR" % test)
264 return value
265
266 def parseExpr(self):
267 return self.parseOrXor()
268
269 def getResult(self):
270 value = self.parseExpr()
271 self.skipSpace()
272 if not self.isLast():
273 self.errExit ("Unexpected character found '%s'" % self.getCurr())
274 test = self.getNumber(value)
275 if test is None:
276 self.errExit ("Result '%s' is not a number" % value)
277 return int(value)
278
279 def evaluateExpress (self, Expr):
280 self.index = 0
281 self.string = Expr
282 if self.getResult():
283 Result = True
284 else:
285 Result = False
286 return Result
287
288 class CGenCfgOpt:
289 def __init__(self):
290 self.Debug = False
291 self.Error = ''
292
293 self._GlobalDataDef = """
294 GlobalDataDef
295 SKUID = 0, "DEFAULT"
296 EndGlobalData
297
298 """
299 self._BuidinOptionTxt = """
300 List &EN_DIS
301 Selection 0x1 , "Enabled"
302 Selection 0x0 , "Disabled"
303 EndList
304
305 """
306
307 self._BsfKeyList = ['FIND','NAME','HELP','TYPE','PAGE','OPTION','ORDER']
308 self._HdrKeyList = ['HEADER','STRUCT', 'EMBED', 'COMMENT']
309 self._BuidinOption = {'$EN_DIS' : 'EN_DIS'}
310
311 self._MacroDict = {}
312 self._PcdsDict = {}
313 self._CfgBlkDict = {}
314 self._CfgPageDict = {}
315 self._CfgItemList = []
316 self._DscFile = ''
317 self._FvDir = ''
318 self._MapVer = 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):
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 Line = Line.replace(Each, Each[2:-1])
368 return Line
369
370 def ExpandPcds (self, Input):
371 Line = Input
372 Match = re.findall("(\w+\.\w+)", Input)
373 if Match:
374 for PcdName in Match:
375 if PcdName in self._PcdsDict:
376 Line = Line.replace(PcdName, self._PcdsDict[PcdName])
377 else:
378 if self.Debug:
379 print "WARN : %s is not defined" % PcdName
380 return Line
381
382 def EvaluateExpress (self, Expr):
383 ExpExpr = self.ExpandPcds(Expr)
384 ExpExpr = self.ExpandMacros(ExpExpr)
385 LogExpr = CLogicalExpression()
386 Result = LogExpr.evaluateExpress (ExpExpr)
387 if self.Debug:
388 print "INFO : Eval Express [%s] : %s" % (Expr, Result)
389 return Result
390
391 def FormatListValue(self, ConfigDict):
392 Struct = ConfigDict['struct']
393 if Struct not in ['UINT8','UINT16','UINT32','UINT64']:
394 return
395
396 dataarray = []
397 binlist = ConfigDict['value'][1:-1].split(',')
398 for each in binlist:
399 each = each.strip()
400 if each.startswith('0x'):
401 value = int(each, 16)
402 else:
403 value = int(each)
404 dataarray.append(value)
405
406 unit = int(Struct[4:]) / 8
407 if int(ConfigDict['length']) != unit * len(dataarray):
408 raise Exception("Array size is not proper for '%s' !" % ConfigDict['cname'])
409
410 bytearray = []
411 for each in dataarray:
412 value = each
413 for loop in xrange(unit):
414 bytearray.append("0x%02X" % (value & 0xFF))
415 value = value >> 8
416 newvalue = '{' + ','.join(bytearray) + '}'
417 ConfigDict['value'] = newvalue
418 return ""
419
420 def ParseDscFile (self, DscFile, FvDir):
421 Hardcode = False
422 AutoAlign = False
423 self._CfgItemList = []
424 self._CfgPageDict = {}
425 self._CfgBlkDict = {}
426 self._DscFile = DscFile
427 self._FvDir = FvDir
428
429 IsDefSect = False
430 IsPcdSect = False
431 IsUpdSect = False
432 IsVpdSect = False
433
434 IfStack = []
435 ElifStack = []
436 Error = 0
437 ConfigDict = {}
438
439 DscFd = open(DscFile, "r")
440 DscLines = DscFd.readlines()
441 DscFd.close()
442
443 MaxAlign = 32 #Default align to 32, but if there are 64 bit unit, align to 64
444 SizeAlign = 0 #record the struct max align
445 while len(DscLines):
446 DscLine = DscLines.pop(0).strip()
447 Handle = False
448 Match = re.match("^\[(.+)\]", DscLine)
449 if Match is not None:
450 IsDefSect = False
451 IsPcdSect = False
452 IsVpdSect = False
453 IsUpdSect = False
454 if Match.group(1).lower() == "Defines".lower():
455 IsDefSect = True
456 if (Match.group(1).lower() == "PcdsFeatureFlag".lower() or Match.group(1).lower() == "PcdsFixedAtBuild".lower()):
457 IsPcdSect = True
458 elif Match.group(1).lower() == "PcdsDynamicVpd.Upd".lower():
459 ConfigDict = {}
460 ConfigDict['header'] = 'ON'
461 ConfigDict['region'] = 'UPD'
462 ConfigDict['order'] = -1
463 ConfigDict['page'] = ''
464 ConfigDict['name'] = ''
465 ConfigDict['find'] = ''
466 ConfigDict['struct'] = ''
467 ConfigDict['embed'] = ''
468 ConfigDict['comment'] = ''
469 ConfigDict['subreg'] = []
470 IsUpdSect = True
471 Offset = 0
472 else:
473 if IsDefSect or IsPcdSect or IsUpdSect or IsVpdSect:
474 if re.match("^!else($|\s+#.+)", DscLine):
475 if IfStack:
476 IfStack[-1] = not IfStack[-1]
477 else:
478 print("ERROR: No paired '!if' found for '!else' for line '%s'" % DscLine)
479 raise SystemExit
480 elif re.match("^!endif($|\s+#.+)", DscLine):
481 if IfStack:
482 IfStack.pop()
483 Level = ElifStack.pop()
484 if Level > 0:
485 del IfStack[-Level:]
486 else:
487 print("ERROR: No paired '!if' found for '!endif' for line '%s'" % DscLine)
488 raise SystemExit
489 else:
490 Result = False
491 Match = re.match("!(ifdef|ifndef)\s+(.+)", DscLine)
492 if Match:
493 Result = self.EvaulateIfdef (Match.group(2))
494 if Match.group(1) == 'ifndef':
495 Result = not Result
496 IfStack.append(Result)
497 ElifStack.append(0)
498 else:
499 Match = re.match("!(if|elseif)\s+(.+)", DscLine.split("#")[0])
500 if Match:
501 Result = self.EvaluateExpress(Match.group(2))
502 if Match.group(1) == "if":
503 ElifStack.append(0)
504 IfStack.append(Result)
505 else: #elseif
506 if IfStack:
507 IfStack[-1] = not IfStack[-1]
508 IfStack.append(Result)
509 ElifStack[-1] = ElifStack[-1] + 1
510 else:
511 print("ERROR: No paired '!if' found for '!elif' for line '%s'" % DscLine)
512 raise SystemExit
513 else:
514 if IfStack:
515 Handle = reduce(lambda x,y: x and y, IfStack)
516 else:
517 Handle = True
518 if Handle:
519 Match = re.match("!include\s+(.+)", DscLine)
520 if Match:
521 IncludeFilePath = Match.group(1)
522 IncludeFilePath = self.ExpandMacros(IncludeFilePath)
523 PackagesPath = os.getenv("PACKAGES_PATH")
524 if PackagesPath:
525 for PackagePath in PackagesPath.split(os.pathsep):
526 IncludeFilePathAbs = os.path.join(os.path.normpath(PackagePath), os.path.normpath(IncludeFilePath))
527 if os.path.exists(IncludeFilePathAbs):
528 IncludeDsc = open(IncludeFilePathAbs, "r")
529 break
530 else:
531 IncludeDsc = open(IncludeFilePath, "r")
532 if IncludeDsc == None:
533 print("ERROR: Cannot open file '%s'" % IncludeFilePath)
534 raise SystemExit
535 NewDscLines = IncludeDsc.readlines()
536 IncludeDsc.close()
537 DscLines = NewDscLines + DscLines
538 Offset = 0
539 else:
540 if DscLine.startswith('!'):
541 print("ERROR: Unrecoginized directive for line '%s'" % DscLine)
542 raise SystemExit
543 if not Handle:
544 continue
545
546 if IsDefSect:
547 #DEFINE UPD_TOOL_GUID = 8C3D856A-9BE6-468E-850A-24F7A8D38E09
548 #DEFINE FSP_T_UPD_TOOL_GUID = 34686CA3-34F9-4901-B82A-BA630F0714C6
549 #DEFINE FSP_M_UPD_TOOL_GUID = 39A250DB-E465-4DD1-A2AC-E2BD3C0E2385
550 #DEFINE FSP_S_UPD_TOOL_GUID = CAE3605B-5B34-4C85-B3D7-27D54273C40F
551 Match = re.match("^\s*(?:DEFINE\s+)*(\w+)\s*=\s*([-.\w]+)", DscLine)
552 if Match:
553 self._MacroDict[Match.group(1)] = Match.group(2)
554 if self.Debug:
555 print "INFO : DEFINE %s = [ %s ]" % (Match.group(1), Match.group(2))
556 elif IsPcdSect:
557 #gSiPkgTokenSpaceGuid.PcdTxtEnable|FALSE
558 #gSiPkgTokenSpaceGuid.PcdOverclockEnable|TRUE
559 Match = re.match("^\s*([\w\.]+)\s*\|\s*(\w+)", DscLine)
560 if Match:
561 self._PcdsDict[Match.group(1)] = Match.group(2)
562 if self.Debug:
563 print "INFO : PCD %s = [ %s ]" % (Match.group(1), Match.group(2))
564 else:
565 Match = re.match("^\s*#\s+(!BSF|@Bsf|!HDR)\s+(.+)", DscLine)
566 if Match:
567 Remaining = Match.group(2)
568 if Match.group(1) == '!BSF' or Match.group(1) == '@Bsf':
569 Match = re.match("(?:^|.+\s+)PAGES:{(.+?)}", Remaining)
570 if Match:
571 # !BSF PAGES:{HSW:"Haswell System Agent", LPT:"Lynx Point PCH"}
572 PageList = Match.group(1).split(',')
573 for Page in PageList:
574 Page = Page.strip()
575 Match = re.match("(\w+):\"(.+)\"", Page)
576 self._CfgPageDict[Match.group(1)] = Match.group(2)
577
578 Match = re.match("(?:^|.+\s+)BLOCK:{NAME:\"(.+)\"\s*,\s*VER:\"(.+)\"\s*}", Remaining)
579 if Match:
580 self._CfgBlkDict['name'] = Match.group(1)
581 self._CfgBlkDict['ver'] = Match.group(2)
582
583 for Key in self._BsfKeyList:
584 Match = re.match("(?:^|.+\s+)%s:{(.+?)}" % Key, Remaining)
585 if Match:
586 if Key in ['NAME', 'HELP', 'OPTION'] and Match.group(1).startswith('+'):
587 ConfigDict[Key.lower()] += Match.group(1)[1:]
588 else:
589 ConfigDict[Key.lower()] = Match.group(1)
590 else:
591 for Key in self._HdrKeyList:
592 Match = re.match("(?:^|.+\s+)%s:{(.+?)}" % Key, Remaining)
593 if Match:
594 ConfigDict[Key.lower()] = Match.group(1)
595
596 Match = re.match("^\s*#\s+@Prompt\s+(.+)", DscLine)
597 if Match:
598 ConfigDict['name'] = Match.group(1)
599
600 Match = re.match("^\s*#\s*@ValidList\s*(.+)\s*\|\s*(.+)\s*\|\s*(.+)\s*", DscLine)
601 if Match:
602 if Match.group(2).strip() in self._BuidinOption:
603 ConfigDict['option'] = Match.group(2).strip()
604 else:
605 OptionValueList = Match.group(2).split(',')
606 OptionStringList = Match.group(3).split(',')
607 Index = 0
608 for Option in OptionValueList:
609 Option = Option.strip()
610 ConfigDict['option'] = ConfigDict['option'] + str(Option) + ':' + OptionStringList[Index].strip()
611 Index += 1
612 if Index in range(len(OptionValueList)):
613 ConfigDict['option'] += ', '
614 ConfigDict['type'] = "Combo"
615
616 Match = re.match("^\s*#\s*@ValidRange\s*(.+)\s*\|\s*(.+)\s*-\s*(.+)\s*", DscLine)
617 if Match:
618 if "0x" in Match.group(2) or "0x" in Match.group(3):
619 ConfigDict['type'] = "EditNum, HEX, (%s,%s)" % (Match.group(2), Match.group(3))
620 else:
621 ConfigDict['type'] = "EditNum, DEC, (%s,%s)" % (Match.group(2), Match.group(3))
622
623 Match = re.match("^\s*##\s+(.+)", DscLine)
624 if Match:
625 ConfigDict['help'] = Match.group(1)
626
627 # Check VPD/UPD
628 if IsUpdSect:
629 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)
630 else:
631 Match = re.match("^([_a-zA-Z0-9]+).([_a-zA-Z0-9]+)\s*\|\s*(0x[0-9A-F]+)(?:\s*\|\s*(.+))?", DscLine)
632 if Match:
633 ConfigDict['space'] = Match.group(1)
634 ConfigDict['cname'] = Match.group(2)
635 if Match.group(3) != '*':
636 Hardcode = True
637 Offset = int (Match.group(3), 16)
638 else:
639 AutoAlign = True
640
641 if Hardcode and AutoAlign:
642 print("Hardcode and auto-align mixed mode is not supported by GenCfgOpt")
643 raise SystemExit
644 ConfigDict['offset'] = Offset
645 if ConfigDict['order'] == -1:
646 ConfigDict['order'] = ConfigDict['offset'] << 8
647 else:
648 (Major, Minor) = ConfigDict['order'].split('.')
649 ConfigDict['order'] = (int (Major, 16) << 8 ) + int (Minor, 16)
650 if IsUpdSect:
651 Value = Match.group(5).strip()
652 if Match.group(4).startswith("0x"):
653 Length = int (Match.group(4), 16)
654 else :
655 Length = int (Match.group(4))
656 Offset += Length
657 else:
658 Value = Match.group(4)
659 if Value is None:
660 Value = ''
661 Value = Value.strip()
662 if '|' in Value:
663 Match = re.match("^.+\s*\|\s*(.+)", Value)
664 if Match:
665 Value = Match.group(1)
666 Length = -1
667
668 ConfigDict['length'] = Length
669 Match = re.match("\$\((\w+)\)", Value)
670 if Match:
671 if Match.group(1) in self._MacroDict:
672 Value = self._MacroDict[Match.group(1)]
673
674 ConfigDict['value'] = Value
675 if (len(Value) > 0) and (Value[0] == '{'):
676 Value = self.FormatListValue(ConfigDict)
677
678 if ConfigDict['name'] == '':
679 # Clear BSF specific items
680 ConfigDict['bsfname'] = ''
681 ConfigDict['help'] = ''
682 ConfigDict['type'] = ''
683 ConfigDict['option'] = ''
684 if IsUpdSect and AutoAlign:
685 ItemLength = int(ConfigDict['length'])
686 ItemOffset = int(ConfigDict['offset'])
687 ItemStruct = ConfigDict['struct']
688 Unit = 1
689 if ItemLength in [1, 2, 4, 8] and not ConfigDict['value'].startswith('{'):
690 Unit = ItemLength
691 # If there are 64 bit unit, align to 64
692 if Unit == 8:
693 MaxAlign = 64
694 SizeAlign = 8
695 if ItemStruct != '':
696 UnitDict = {'UINT8':1, 'UINT16':2, 'UINT32':4, 'UINT64':8}
697 if ItemStruct in ['UINT8', 'UINT16', 'UINT32', 'UINT64']:
698 Unit = UnitDict[ItemStruct]
699 # If there are 64 bit unit, align to 64
700 if Unit == 8:
701 MaxAlign = 64
702 SizeAlign = max(SizeAlign, Unit)
703 if (ConfigDict['embed'].find(':START') != -1):
704 Base = ItemOffset
705 SubOffset = ItemOffset - Base
706 SubRemainder = SubOffset % Unit
707 if SubRemainder:
708 Diff = Unit - SubRemainder
709 Offset = Offset + Diff
710 ItemOffset = ItemOffset + Diff
711
712 if (ConfigDict['embed'].find(':END') != -1):
713 Remainder = Offset % (MaxAlign/8) # MaxAlign is either 32 or 64
714 if Remainder:
715 Diff = (MaxAlign/8) - Remainder
716 Offset = Offset + Diff
717 ItemOffset = ItemOffset + Diff
718 MaxAlign = 32 # Reset to default 32 align when struct end
719 if (ConfigDict['cname'] == 'UpdTerminator'):
720 # ItemLength is the size of UpdTerminator
721 # Itemlength might be 16, 32, or 64
722 # Struct align to 64 if UpdTerminator
723 # or struct size is 64 bit, else align to 32
724 Remainder = Offset % max(ItemLength/8, 4, SizeAlign)
725 Offset = Offset + ItemLength
726 if Remainder:
727 Diff = max(ItemLength/8, 4, SizeAlign) - Remainder
728 ItemOffset = ItemOffset + Diff
729 ConfigDict['offset'] = ItemOffset
730
731 self._CfgItemList.append(ConfigDict.copy())
732 ConfigDict['name'] = ''
733 ConfigDict['find'] = ''
734 ConfigDict['struct'] = ''
735 ConfigDict['embed'] = ''
736 ConfigDict['comment'] = ''
737 ConfigDict['order'] = -1
738 ConfigDict['subreg'] = []
739 ConfigDict['option'] = ''
740 else:
741 # It could be a virtual item as below
742 # !BSF FIELD:{SerialDebugPortAddress0:1}
743 # or
744 # @Bsf FIELD:{SerialDebugPortAddress0:1b}
745 Match = re.match("^\s*#\s+(!BSF|@Bsf)\s+FIELD:{(.+):(\d+)([Bb])?}", DscLine)
746 if Match:
747 SubCfgDict = ConfigDict.copy()
748 if (Match.group(4) == None) or (Match.group(4) == 'B'):
749 UnitBitLen = 8
750 elif Match.group(4) == 'b':
751 UnitBitLen = 1
752 else:
753 print("ERROR: Invalide BSF FIELD length for line '%s'" % DscLine)
754 raise SystemExit
755 SubCfgDict['cname'] = Match.group(2)
756 SubCfgDict['bitlength'] = int (Match.group(3)) * UnitBitLen
757 if SubCfgDict['bitlength'] > 0:
758 LastItem = self._CfgItemList[-1]
759 if len(LastItem['subreg']) == 0:
760 SubOffset = 0
761 else:
762 SubOffset = LastItem['subreg'][-1]['bitoffset'] + LastItem['subreg'][-1]['bitlength']
763 SubCfgDict['bitoffset'] = SubOffset
764 LastItem['subreg'].append (SubCfgDict.copy())
765 ConfigDict['name'] = ''
766 return Error
767
768 def GetBsfBitFields (self, subitem, bytes):
769 start = subitem['bitoffset']
770 end = start + subitem['bitlength']
771 bitsvalue = ''.join('{0:08b}'.format(i) for i in bytes[::-1])
772 bitsvalue = bitsvalue[::-1]
773 bitslen = len(bitsvalue)
774 if start > bitslen or end > bitslen:
775 print "Invalid bits offset [%d,%d] for %s" % (start, end, subitem['name'])
776 raise SystemExit
777 return hex(int(bitsvalue[start:end][::-1], 2))
778
779 def UpdateSubRegionDefaultValue (self):
780 Error = 0
781 for Item in self._CfgItemList:
782 if len(Item['subreg']) == 0:
783 continue
784 bytearray = []
785 if Item['value'][0] == '{':
786 binlist = Item['value'][1:-1].split(',')
787 for each in binlist:
788 each = each.strip()
789 if each.startswith('0x'):
790 value = int(each, 16)
791 else:
792 value = int(each)
793 bytearray.append(value)
794 else:
795 if Item['value'].startswith('0x'):
796 value = int(Item['value'], 16)
797 else:
798 value = int(Item['value'])
799 idx = 0
800 while idx < Item['length']:
801 bytearray.append(value & 0xFF)
802 value = value >> 8
803 idx = idx + 1
804 for SubItem in Item['subreg']:
805 valuestr = self.GetBsfBitFields(SubItem, bytearray)
806 SubItem['value'] = valuestr
807 return Error
808
809 def CreateSplitUpdTxt (self, UpdTxtFile):
810 GuidList = ['FSP_T_UPD_TOOL_GUID','FSP_M_UPD_TOOL_GUID','FSP_S_UPD_TOOL_GUID']
811 SignatureList = ['0x545F', '0x4D5F','0x535F'] # _T, _M, and _S signature for FSPT, FSPM, FSPS
812 for Index in range(len(GuidList)):
813 UpdTxtFile = ''
814 FvDir = self._FvDir
815 if GuidList[Index] not in self._MacroDict:
816 self.Error = "%s definition is missing in DSC file" % (GuidList[Index])
817 return 1
818
819 if UpdTxtFile == '':
820 UpdTxtFile = os.path.join(FvDir, self._MacroDict[GuidList[Index]] + '.txt')
821
822 ReCreate = False
823 if not os.path.exists(UpdTxtFile):
824 ReCreate = True
825 else:
826 DscTime = os.path.getmtime(self._DscFile)
827 TxtTime = os.path.getmtime(UpdTxtFile)
828 if DscTime > TxtTime:
829 ReCreate = True
830
831 if not ReCreate:
832 # DSC has not been modified yet
833 # So don't have to re-generate other files
834 self.Error = 'No DSC file change, skip to create UPD TXT file'
835 return 256
836
837 TxtFd = open(UpdTxtFile, "w")
838 TxtFd.write("%s\n" % (__copyright_txt__ % date.today().year))
839
840 NextOffset = 0
841 SpaceIdx = 0
842 StartAddr = 0
843 EndAddr = 0
844 Default = 'DEFAULT|'
845 InRange = False
846 for Item in self._CfgItemList:
847 if Item['cname'] == 'Signature' and str(Item['value'])[0:6] == SignatureList[Index]:
848 StartAddr = Item['offset']
849 NextOffset = StartAddr
850 InRange = True
851 if Item['cname'] == 'UpdTerminator' and InRange == True:
852 EndAddr = Item['offset']
853 InRange = False
854 InRange = False
855 for Item in self._CfgItemList:
856 if Item['cname'] == 'Signature' and str(Item['value'])[0:6] == SignatureList[Index]:
857 InRange = True
858 if InRange != True:
859 continue
860 if Item['cname'] == 'UpdTerminator':
861 InRange = False
862 if Item['region'] != 'UPD':
863 continue
864 Offset = Item['offset']
865 if StartAddr > Offset or EndAddr < Offset:
866 continue
867 if NextOffset < Offset:
868 # insert one line
869 TxtFd.write("%s.UnusedUpdSpace%d|%s0x%04X|0x%04X|{0}\n" % (Item['space'], SpaceIdx, Default, NextOffset - StartAddr, Offset - NextOffset))
870 SpaceIdx = SpaceIdx + 1
871 NextOffset = Offset + Item['length']
872 TxtFd.write("%s.%s|%s0x%04X|%s|%s\n" % (Item['space'],Item['cname'],Default,Item['offset'] - StartAddr,Item['length'],Item['value']))
873 TxtFd.close()
874 return 0
875
876 def ProcessMultilines (self, String, MaxCharLength):
877 Multilines = ''
878 StringLength = len(String)
879 CurrentStringStart = 0
880 StringOffset = 0
881 BreakLineDict = []
882 if len(String) <= MaxCharLength:
883 while (StringOffset < StringLength):
884 if StringOffset >= 1:
885 if String[StringOffset - 1] == '\\' and String[StringOffset] == 'n':
886 BreakLineDict.append (StringOffset + 1)
887 StringOffset += 1
888 if BreakLineDict != []:
889 for Each in BreakLineDict:
890 Multilines += " %s\n" % String[CurrentStringStart:Each].lstrip()
891 CurrentStringStart = Each
892 if StringLength - CurrentStringStart > 0:
893 Multilines += " %s\n" % String[CurrentStringStart:].lstrip()
894 else:
895 Multilines = " %s\n" % String
896 else:
897 NewLineStart = 0
898 NewLineCount = 0
899 FoundSpaceChar = False
900 while (StringOffset < StringLength):
901 if StringOffset >= 1:
902 if NewLineCount >= MaxCharLength - 1:
903 if String[StringOffset] == ' ' and StringLength - StringOffset > 10:
904 BreakLineDict.append (NewLineStart + NewLineCount)
905 NewLineStart = NewLineStart + NewLineCount
906 NewLineCount = 0
907 FoundSpaceChar = True
908 elif StringOffset == StringLength - 1 and FoundSpaceChar == False:
909 BreakLineDict.append (0)
910 if String[StringOffset - 1] == '\\' and String[StringOffset] == 'n':
911 BreakLineDict.append (StringOffset + 1)
912 NewLineStart = StringOffset + 1
913 NewLineCount = 0
914 StringOffset += 1
915 NewLineCount += 1
916 if BreakLineDict != []:
917 BreakLineDict.sort ()
918 for Each in BreakLineDict:
919 if Each > 0:
920 Multilines += " %s\n" % String[CurrentStringStart:Each].lstrip()
921 CurrentStringStart = Each
922 if StringLength - CurrentStringStart > 0:
923 Multilines += " %s\n" % String[CurrentStringStart:].lstrip()
924 return Multilines
925
926 def CreateField (self, Item, Name, Length, Offset, Struct, BsfName, Help, Option):
927 PosName = 28
928 PosComment = 30
929 NameLine=''
930 HelpLine=''
931 OptionLine=''
932
933 IsArray = False
934 if Length in [1,2,4,8]:
935 Type = "UINT%d" % (Length * 8)
936 if Name.startswith("UnusedUpdSpace") and Length != 1:
937 IsArray = True
938 Type = "UINT8"
939 else:
940 IsArray = True
941 Type = "UINT8"
942
943 if Item and Item['value'].startswith('{'):
944 Type = "UINT8"
945 IsArray = True
946
947 if Struct != '':
948 Type = Struct
949 if Struct in ['UINT8','UINT16','UINT32','UINT64']:
950 IsArray = True
951 Unit = int(Type[4:]) / 8
952 Length = Length / Unit
953 else:
954 IsArray = False
955
956 if IsArray:
957 Name = Name + '[%d]' % Length
958
959 if len(Type) < PosName:
960 Space1 = PosName - len(Type)
961 else:
962 Space1 = 1
963
964 if BsfName != '':
965 NameLine=" - %s\n" % BsfName
966 else:
967 NameLine="\n"
968
969 if Help != '':
970 HelpLine = self.ProcessMultilines (Help, 80)
971
972 if Option != '':
973 OptionLine = self.ProcessMultilines (Option, 80)
974
975 if Offset is None:
976 OffsetStr = '????'
977 else:
978 OffsetStr = '0x%04X' % Offset
979
980 return "\n/** Offset %s%s%s%s**/\n %s%s%s;\n" % (OffsetStr, NameLine, HelpLine, OptionLine, Type, ' ' * Space1, Name,)
981
982 def PostProcessBody (self, TextBody):
983 NewTextBody = []
984 OldTextBody = []
985 IncludeLine = False
986 StructName = ''
987 VariableName = ''
988 IsUpdHdrDefined = False
989 IsUpdHeader = False
990 for Line in TextBody:
991 SplitToLines = Line.splitlines()
992 MatchComment = re.match("^/\*\sCOMMENT:(\w+):([\w|\W|\s]+)\s\*/\s([\s\S]*)", SplitToLines[0])
993 if MatchComment:
994 if MatchComment.group(1) == 'FSP_UPD_HEADER':
995 IsUpdHeader = True
996 else:
997 IsUpdHeader = False
998 if IsUpdHdrDefined != True or IsUpdHeader != True:
999 CommentLine = " " + MatchComment.group(2) + "\n"
1000 NewTextBody.append("/**" + CommentLine + "**/\n")
1001 Line = Line[(len(SplitToLines[0]) + 1):]
1002
1003 Match = re.match("^/\*\sEMBED_STRUCT:(\w+):(\w+):(START|END)\s\*/\s([\s\S]*)", Line)
1004 if Match:
1005 Line = Match.group(4)
1006 if Match.group(1) == 'FSP_UPD_HEADER':
1007 IsUpdHeader = True
1008 else:
1009 IsUpdHeader = False
1010
1011 if Match and Match.group(3) == 'START':
1012 if IsUpdHdrDefined != True or IsUpdHeader != True:
1013 NewTextBody.append ('typedef struct {\n')
1014 StructName = Match.group(1)
1015 VariableName = Match.group(2)
1016 MatchOffset = re.search('/\*\*\sOffset\s0x([a-fA-F0-9]+)', Line)
1017 if MatchOffset:
1018 Offset = int(MatchOffset.group(1), 16)
1019 else:
1020 Offset = None
1021 Line
1022 IncludeLine = True
1023 OldTextBody.append (self.CreateField (None, VariableName, 0, Offset, StructName, '', '', ''))
1024 if IncludeLine:
1025 if IsUpdHdrDefined != True or IsUpdHeader != True:
1026 NewTextBody.append (Line)
1027 else:
1028 OldTextBody.append (Line)
1029
1030 if Match and Match.group(3) == 'END':
1031 if (StructName != Match.group(1)) or (VariableName != Match.group(2)):
1032 print "Unmatched struct name '%s' and '%s' !" % (StructName, Match.group(1))
1033 else:
1034 if IsUpdHdrDefined != True or IsUpdHeader != True:
1035 NewTextBody.append ('} %s;\n\n' % StructName)
1036 IsUpdHdrDefined = True
1037 IncludeLine = False
1038 NewTextBody.extend(OldTextBody)
1039 return NewTextBody
1040
1041 def CreateHeaderFile (self, InputHeaderFile):
1042 FvDir = self._FvDir
1043
1044 HeaderFileName = 'FspUpd.h'
1045 HeaderFile = os.path.join(FvDir, HeaderFileName)
1046
1047 # Check if header needs to be recreated
1048 ReCreate = False
1049
1050 TxtBody = []
1051 for Item in self._CfgItemList:
1052 if str(Item['cname']) == 'Signature' and Item['length'] == 8:
1053 Value = int(Item['value'], 16)
1054 Chars = []
1055 while Value != 0x0:
1056 Chars.append(chr(Value & 0xFF))
1057 Value = Value >> 8
1058 SignatureStr = ''.join(Chars)
1059 # Signature will be _T / _M / _S for FSPT / FSPM / FSPS accordingly
1060 if '_T' in SignatureStr[6:6+2]:
1061 TxtBody.append("#define FSPT_UPD_SIGNATURE %s /* '%s' */\n\n" % (Item['value'], SignatureStr))
1062 elif '_M' in SignatureStr[6:6+2]:
1063 TxtBody.append("#define FSPM_UPD_SIGNATURE %s /* '%s' */\n\n" % (Item['value'], SignatureStr))
1064 elif '_S' in SignatureStr[6:6+2]:
1065 TxtBody.append("#define FSPS_UPD_SIGNATURE %s /* '%s' */\n\n" % (Item['value'], SignatureStr))
1066 TxtBody.append("\n")
1067
1068 for Region in ['UPD']:
1069 UpdOffsetTable = []
1070 UpdSignature = ['0x545F', '0x4D5F', '0x535F'] #['_T', '_M', '_S'] signature for FSPT, FSPM, FSPS
1071 UpdStructure = ['FSPT_UPD', 'FSPM_UPD', 'FSPS_UPD']
1072 for Item in self._CfgItemList:
1073 if Item["cname"] == 'Signature' and Item["value"][0:6] in UpdSignature:
1074 UpdOffsetTable.append (Item["offset"])
1075
1076 for UpdIdx in range(len(UpdOffsetTable)):
1077 CommentLine = ""
1078 for Item in self._CfgItemList:
1079 if Item["comment"] != '' and Item["offset"] >= UpdOffsetTable[UpdIdx]:
1080 MatchComment = re.match("^(U|V)PD_DATA_REGION:([\w|\W|\s]+)", Item["comment"])
1081 if MatchComment and MatchComment.group(1) == Region[0]:
1082 CommentLine = " " + MatchComment.group(2) + "\n"
1083 TxtBody.append("/**" + CommentLine + "**/\n")
1084 elif Item["offset"] >= UpdOffsetTable[UpdIdx] and Item["comment"] == '':
1085 Match = re.match("^FSP([\w|\W|\s])_UPD", UpdStructure[UpdIdx])
1086 if Match:
1087 TxtBody.append("/** Fsp " + Match.group(1) + " UPD Configuration\n**/\n")
1088 TxtBody.append("typedef struct {\n")
1089 NextOffset = 0
1090 SpaceIdx = 0
1091 Offset = 0
1092
1093 LastVisible = True
1094 ResvOffset = 0
1095 ResvIdx = 0
1096 LineBuffer = []
1097 InRange = False
1098 for Item in self._CfgItemList:
1099 if Item['cname'] == 'Signature' and str(Item['value'])[0:6] == UpdSignature[UpdIdx] or Region[0] == 'V':
1100 InRange = True
1101 if InRange != True:
1102 continue
1103 if Item['cname'] == 'UpdTerminator':
1104 InRange = False
1105
1106 if Item['region'] != Region:
1107 continue
1108
1109 if Item["offset"] < UpdOffsetTable[UpdIdx]:
1110 continue
1111
1112 NextVisible = LastVisible
1113
1114 if LastVisible and (Item['header'] == 'OFF'):
1115 NextVisible = False
1116 ResvOffset = Item['offset']
1117 elif (not LastVisible) and Item['header'] == 'ON':
1118 NextVisible = True
1119 Name = "Reserved" + Region[0] + "pdSpace%d" % ResvIdx
1120 ResvIdx = ResvIdx + 1
1121 TxtBody.append(self.CreateField (Item, Name, Item["offset"] - ResvOffset, ResvOffset, '', '', '', ''))
1122
1123 if Offset < Item["offset"]:
1124 if LastVisible:
1125 Name = "Unused" + Region[0] + "pdSpace%d" % SpaceIdx
1126 LineBuffer.append(self.CreateField (Item, Name, Item["offset"] - Offset, Offset, '', '', '', ''))
1127 SpaceIdx = SpaceIdx + 1
1128 Offset = Item["offset"]
1129
1130 LastVisible = NextVisible
1131
1132 Offset = Offset + Item["length"]
1133 if LastVisible:
1134 for Each in LineBuffer:
1135 TxtBody.append (Each)
1136 LineBuffer = []
1137 Comment = Item["comment"]
1138 Embed = Item["embed"].upper()
1139 if Embed.endswith(':START') or Embed.endswith(':END'):
1140 if not Comment == '' and Embed.endswith(':START'):
1141 Marker = '/* COMMENT:%s */ \n' % Item["comment"]
1142 Marker = Marker + '/* EMBED_STRUCT:%s */ ' % Item["embed"]
1143 else:
1144 Marker = '/* EMBED_STRUCT:%s */ ' % Item["embed"]
1145 else:
1146 if Embed == '':
1147 Marker = ''
1148 else:
1149 self.Error = "Invalid embedded structure format '%s'!\n" % Item["embed"]
1150 return 4
1151 Line = Marker + self.CreateField (Item, Item["cname"], Item["length"], Item["offset"], Item['struct'], Item['name'], Item['help'], Item['option'])
1152 TxtBody.append(Line)
1153 if Item['cname'] == 'UpdTerminator':
1154 break
1155 TxtBody.append("} " + UpdStructure[UpdIdx] + ";\n\n")
1156
1157 # Handle the embedded data structure
1158 TxtBody = self.PostProcessBody (TxtBody)
1159
1160 HeaderTFileName = 'FsptUpd.h'
1161 HeaderMFileName = 'FspmUpd.h'
1162 HeaderSFileName = 'FspsUpd.h'
1163
1164 UpdRegionCheck = ['FSPT', 'FSPM', 'FSPS'] # FSPX_UPD_REGION
1165 UpdConfigCheck = ['FSP_T', 'FSP_M', 'FSP_S'] # FSP_X_CONFIG, FSP_X_TEST_CONFIG, FSP_X_RESTRICTED_CONFIG
1166 UpdSignatureCheck = ['FSPT_UPD_SIGNATURE', 'FSPM_UPD_SIGNATURE', 'FSPS_UPD_SIGNATURE']
1167 ExcludedSpecificUpd = 'FSPM_ARCH_UPD'
1168
1169 if InputHeaderFile != '':
1170 if not os.path.exists(InputHeaderFile):
1171 self.Error = "Input header file '%s' does not exist" % InputHeaderFile
1172 return 6
1173
1174 InFd = open(InputHeaderFile, "r")
1175 IncLines = InFd.readlines()
1176 InFd.close()
1177
1178 for item in range(len(UpdRegionCheck)):
1179 if UpdRegionCheck[item] == 'FSPT':
1180 HeaderFd = open(os.path.join(FvDir, HeaderTFileName), "w")
1181 FileBase = os.path.basename(os.path.join(FvDir, HeaderTFileName))
1182 elif UpdRegionCheck[item] == 'FSPM':
1183 HeaderFd = open(os.path.join(FvDir, HeaderMFileName), "w")
1184 FileBase = os.path.basename(os.path.join(FvDir, HeaderMFileName))
1185 elif UpdRegionCheck[item] == 'FSPS':
1186 HeaderFd = open(os.path.join(FvDir, HeaderSFileName), "w")
1187 FileBase = os.path.basename(os.path.join(FvDir, HeaderSFileName))
1188 FileName = FileBase.replace(".", "_").upper()
1189 HeaderFd.write("%s\n" % (__copyright_h__ % date.today().year))
1190 HeaderFd.write("#ifndef __%s__\n" % FileName)
1191 HeaderFd.write("#define __%s__\n\n" % FileName)
1192 HeaderFd.write("#include <%s>\n\n" % HeaderFileName)
1193 HeaderFd.write("#pragma pack(1)\n\n")
1194
1195 Export = False
1196 for Line in IncLines:
1197 Match = re.search ("!EXPORT\s+([A-Z]+)\s+EXTERNAL_BOOTLOADER_STRUCT_(BEGIN|END)\s+", Line)
1198 if Match:
1199 if Match.group(2) == "BEGIN" and Match.group(1) == UpdRegionCheck[item]:
1200 Export = True
1201 continue
1202 else:
1203 Export = False
1204 continue
1205 if Export:
1206 HeaderFd.write(Line)
1207 HeaderFd.write("\n")
1208
1209 Index = 0
1210 StartIndex = 0
1211 EndIndex = 0
1212 StructStart = []
1213 StructStartWithComment = []
1214 StructEnd = []
1215 for Line in TxtBody:
1216 Index += 1
1217 Match = re.match("(typedef struct {)", Line)
1218 if Match:
1219 StartIndex = Index - 1
1220 Match = re.match("}\s([_A-Z0-9]+);", Line)
1221 if Match and (UpdRegionCheck[item] in Match.group(1) or UpdConfigCheck[item] in Match.group(1)) and (ExcludedSpecificUpd not in Match.group(1)):
1222 EndIndex = Index
1223 StructStart.append(StartIndex)
1224 StructEnd.append(EndIndex)
1225 Index = 0
1226 for Line in TxtBody:
1227 Index += 1
1228 for Item in range(len(StructStart)):
1229 if Index == StructStart[Item]:
1230 Match = re.match("^(/\*\*\s*)", Line)
1231 if Match:
1232 StructStartWithComment.append(StructStart[Item])
1233 else:
1234 StructStartWithComment.append(StructStart[Item] + 1)
1235 Index = 0
1236 for Line in TxtBody:
1237 Index += 1
1238 for Item in range(len(StructStart)):
1239 if Index >= StructStartWithComment[Item] and Index <= StructEnd[Item]:
1240 HeaderFd.write (Line)
1241 HeaderFd.write("#pragma pack()\n\n")
1242 HeaderFd.write("#endif\n")
1243 HeaderFd.close()
1244
1245 HeaderFd = open(HeaderFile, "w")
1246 FileBase = os.path.basename(HeaderFile)
1247 FileName = FileBase.replace(".", "_").upper()
1248 HeaderFd.write("%s\n" % (__copyright_h__ % date.today().year))
1249 HeaderFd.write("#ifndef __%s__\n" % FileName)
1250 HeaderFd.write("#define __%s__\n\n" % FileName)
1251 HeaderFd.write("#include <FspEas.h>\n\n")
1252 HeaderFd.write("#pragma pack(1)\n\n")
1253
1254 for item in range(len(UpdRegionCheck)):
1255 Index = 0
1256 StartIndex = 0
1257 EndIndex = 0
1258 StructStart = []
1259 StructStartWithComment = []
1260 StructEnd = []
1261 for Line in TxtBody:
1262 Index += 1
1263 Match = re.match("(typedef struct {)", Line)
1264 if Match:
1265 StartIndex = Index - 1
1266 Match = re.match("#define\s([_A-Z0-9]+)\s*", Line)
1267 if Match and (UpdSignatureCheck[item] in Match.group(1) or UpdSignatureCheck[item] in Match.group(1)):
1268 StructStart.append(Index - 1)
1269 StructEnd.append(Index)
1270 Index = 0
1271 for Line in TxtBody:
1272 Index += 1
1273 for Item in range(len(StructStart)):
1274 if Index == StructStart[Item]:
1275 Match = re.match("^(/\*\*\s*)", Line)
1276 if Match:
1277 StructStartWithComment.append(StructStart[Item])
1278 else:
1279 StructStartWithComment.append(StructStart[Item] + 1)
1280 Index = 0
1281 for Line in TxtBody:
1282 Index += 1
1283 for Item in range(len(StructStart)):
1284 if Index >= StructStartWithComment[Item] and Index <= StructEnd[Item]:
1285 HeaderFd.write (Line)
1286 HeaderFd.write("#pragma pack()\n\n")
1287 HeaderFd.write("#endif\n")
1288 HeaderFd.close()
1289
1290 return 0
1291
1292 def WriteBsfStruct (self, BsfFd, Item):
1293 LogExpr = CLogicalExpression()
1294 if Item['type'] == "None":
1295 Space = "gPlatformFspPkgTokenSpaceGuid"
1296 else:
1297 Space = Item['space']
1298 Line = " $%s_%s" % (Space, Item['cname'])
1299 Match = re.match("\s*\{([x0-9a-fA-F,\s]+)\}\s*", Item['value'])
1300 if Match:
1301 DefaultValue = Match.group(1).strip()
1302 else:
1303 DefaultValue = Item['value'].strip()
1304 if 'bitlength' in Item:
1305 BsfFd.write(" %s%s%4d bits $_DEFAULT_ = %s\n" % (Line, ' ' * (64 - len(Line)), Item['bitlength'], DefaultValue))
1306 else:
1307 BsfFd.write(" %s%s%4d bytes $_DEFAULT_ = %s\n" % (Line, ' ' * (64 - len(Line)), Item['length'], DefaultValue))
1308 TmpList = []
1309 if Item['type'] == "Combo":
1310 if not Item['option'] in self._BuidinOption:
1311 OptList = Item['option'].split(',')
1312 for Option in OptList:
1313 Option = Option.strip()
1314 (OpVal, OpStr) = Option.split(':')
1315 test = LogExpr.getNumber (OpVal)
1316 if test is None:
1317 raise Exception("Selection Index '%s' is not a number" % OpVal)
1318 TmpList.append((OpVal, OpStr))
1319 return TmpList
1320
1321 def WriteBsfOption (self, BsfFd, Item):
1322 PcdName = Item['space'] + '_' + Item['cname']
1323 WriteHelp = 0
1324 if Item['type'] == "Combo":
1325 if Item['option'] in self._BuidinOption:
1326 Options = self._BuidinOption[Item['option']]
1327 else:
1328 Options = PcdName
1329 BsfFd.write(' %s $%s, "%s", &%s,\n' % (Item['type'], PcdName, Item['name'], Options))
1330 WriteHelp = 1
1331 elif Item['type'].startswith("EditNum"):
1332 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'])
1333 if Match:
1334 BsfFd.write(' EditNum $%s, "%s", %s,\n' % (PcdName, Item['name'], Match.group(1)))
1335 WriteHelp = 2
1336 elif Item['type'].startswith("EditText"):
1337 BsfFd.write(' %s $%s, "%s",\n' % (Item['type'], PcdName, Item['name']))
1338 WriteHelp = 1
1339 elif Item['type'] == "Table":
1340 Columns = Item['option'].split(',')
1341 if len(Columns) != 0:
1342 BsfFd.write(' %s $%s "%s",' % (Item['type'], PcdName, Item['name']))
1343 for Col in Columns:
1344 Fmt = Col.split(':')
1345 if len(Fmt) != 3:
1346 raise Exception("Column format '%s' is invalid !" % Fmt)
1347 try:
1348 Dtype = int(Fmt[1].strip())
1349 except:
1350 raise Exception("Column size '%s' is invalid !" % Fmt[1])
1351 BsfFd.write('\n Column "%s", %d bytes, %s' % (Fmt[0].strip(), Dtype, Fmt[2].strip()))
1352 BsfFd.write(',\n')
1353 WriteHelp = 1
1354
1355 if WriteHelp > 0:
1356 HelpLines = Item['help'].split('\\n\\r')
1357 FirstLine = True
1358 for HelpLine in HelpLines:
1359 if FirstLine:
1360 FirstLine = False
1361 BsfFd.write(' Help "%s"\n' % (HelpLine))
1362 else:
1363 BsfFd.write(' "%s"\n' % (HelpLine))
1364 if WriteHelp == 2:
1365 BsfFd.write(' "Valid range: %s ~ %s"\n' % (Match.group(2), Match.group(3)))
1366
1367 def GenerateBsfFile (self, BsfFile):
1368
1369 if BsfFile == '':
1370 self.Error = "BSF output file '%s' is invalid" % BsfFile
1371 return 1
1372
1373 Error = 0
1374 OptionDict = {}
1375 BsfFd = open(BsfFile, "w")
1376 BsfFd.write("%s\n" % (__copyright_bsf__ % date.today().year))
1377 BsfFd.write("%s\n" % self._GlobalDataDef)
1378 BsfFd.write("StructDef\n")
1379 NextOffset = -1
1380 for Item in self._CfgItemList:
1381 if Item['find'] != '':
1382 BsfFd.write('\n Find "%s"\n' % Item['find'])
1383 NextOffset = Item['offset'] + Item['length']
1384 if Item['name'] != '':
1385 if NextOffset != Item['offset']:
1386 BsfFd.write(" Skip %d bytes\n" % (Item['offset'] - NextOffset))
1387 if len(Item['subreg']) > 0:
1388 NextOffset = Item['offset']
1389 BitsOffset = NextOffset * 8
1390 for SubItem in Item['subreg']:
1391 BitsOffset += SubItem['bitlength']
1392 if SubItem['name'] == '':
1393 if 'bitlength' in SubItem:
1394 BsfFd.write(" Skip %d bits\n" % (SubItem['bitlength']))
1395 else:
1396 BsfFd.write(" Skip %d bytes\n" % (SubItem['length']))
1397 else:
1398 Options = self.WriteBsfStruct(BsfFd, SubItem)
1399 if len(Options) > 0:
1400 OptionDict[SubItem['space']+'_'+SubItem['cname']] = Options
1401
1402 NextBitsOffset = (Item['offset'] + Item['length']) * 8
1403 if NextBitsOffset > BitsOffset:
1404 BitsGap = NextBitsOffset - BitsOffset
1405 BitsRemain = BitsGap % 8
1406 if BitsRemain:
1407 BsfFd.write(" Skip %d bits\n" % BitsRemain)
1408 BitsGap -= BitsRemain
1409 BytesRemain = BitsGap / 8
1410 if BytesRemain:
1411 BsfFd.write(" Skip %d bytes\n" % BytesRemain)
1412 NextOffset = Item['offset'] + Item['length']
1413 else:
1414 NextOffset = Item['offset'] + Item['length']
1415 Options = self.WriteBsfStruct(BsfFd, Item)
1416 if len(Options) > 0:
1417 OptionDict[Item['space']+'_'+Item['cname']] = Options
1418 BsfFd.write("\nEndStruct\n\n")
1419
1420 BsfFd.write("%s" % self._BuidinOptionTxt)
1421
1422 for Each in OptionDict:
1423 BsfFd.write("List &%s\n" % Each)
1424 for Item in OptionDict[Each]:
1425 BsfFd.write(' Selection %s , "%s"\n' % (Item[0], Item[1]))
1426 BsfFd.write("EndList\n\n")
1427
1428 BsfFd.write("BeginInfoBlock\n")
1429 BsfFd.write(' PPVer "%s"\n' % (self._CfgBlkDict['ver']))
1430 BsfFd.write(' Description "%s"\n' % (self._CfgBlkDict['name']))
1431 BsfFd.write("EndInfoBlock\n\n")
1432
1433 for Each in self._CfgPageDict:
1434 BsfFd.write('Page "%s"\n' % self._CfgPageDict[Each])
1435 BsfItems = []
1436 for Item in self._CfgItemList:
1437 if Item['name'] != '':
1438 if Item['page'] != Each:
1439 continue
1440 if len(Item['subreg']) > 0:
1441 for SubItem in Item['subreg']:
1442 if SubItem['name'] != '':
1443 BsfItems.append(SubItem)
1444 else:
1445 BsfItems.append(Item)
1446
1447 BsfItems.sort(key=lambda x: x['order'])
1448
1449 for Item in BsfItems:
1450 self.WriteBsfOption (BsfFd, Item)
1451 BsfFd.write("EndPage\n\n")
1452
1453 BsfFd.close()
1454 return Error
1455
1456
1457 def Usage():
1458 print "GenCfgOpt Version 0.52"
1459 print "Usage:"
1460 print " GenCfgOpt UPDTXT PlatformDscFile BuildFvDir [-D Macros]"
1461 print " GenCfgOpt HEADER PlatformDscFile BuildFvDir InputHFile [-D Macros]"
1462 print " GenCfgOpt GENBSF PlatformDscFile BuildFvDir BsfOutFile [-D Macros]"
1463
1464 def Main():
1465 #
1466 # Parse the options and args
1467 #
1468 GenCfgOpt = CGenCfgOpt()
1469 argc = len(sys.argv)
1470 if argc < 4:
1471 Usage()
1472 return 1
1473 else:
1474 DscFile = sys.argv[2]
1475 if not os.path.exists(DscFile):
1476 print "ERROR: Cannot open DSC file '%s' !" % DscFile
1477 return 2
1478
1479 OutFile = ''
1480 if argc > 4:
1481 if sys.argv[4][0] == '-':
1482 Start = 4
1483 else:
1484 OutFile = sys.argv[4]
1485 Start = 5
1486 if argc > Start:
1487 if GenCfgOpt.ParseMacros(sys.argv[Start:]) != 0:
1488 print "ERROR: Macro parsing failed !"
1489 return 3
1490
1491 FvDir = sys.argv[3]
1492 if not os.path.exists(FvDir):
1493 os.makedirs(FvDir)
1494
1495 if GenCfgOpt.ParseDscFile(DscFile, FvDir) != 0:
1496 print "ERROR: %s !" % GenCfgOpt.Error
1497 return 5
1498
1499 if GenCfgOpt.UpdateSubRegionDefaultValue() != 0:
1500 print "ERROR: %s !" % GenCfgOpt.Error
1501 return 7
1502
1503 if sys.argv[1] == "UPDTXT":
1504 Ret = GenCfgOpt.CreateSplitUpdTxt(OutFile)
1505 if Ret != 0:
1506 # No change is detected
1507 if Ret == 256:
1508 print "INFO: %s !" % (GenCfgOpt.Error)
1509 else :
1510 print "ERROR: %s !" % (GenCfgOpt.Error)
1511 return Ret
1512 elif sys.argv[1] == "HEADER":
1513 if GenCfgOpt.CreateHeaderFile(OutFile) != 0:
1514 print "ERROR: %s !" % GenCfgOpt.Error
1515 return 8
1516 elif sys.argv[1] == "GENBSF":
1517 if GenCfgOpt.GenerateBsfFile(OutFile) != 0:
1518 print "ERROR: %s !" % GenCfgOpt.Error
1519 return 9
1520 else:
1521 if argc < 5:
1522 Usage()
1523 return 1
1524 print "ERROR: Unknown command '%s' !" % sys.argv[1]
1525 Usage()
1526 return 1
1527 return 0
1528 return 0
1529
1530
1531 if __name__ == '__main__':
1532 sys.exit(Main())