1## @ GenCfgOpt.py
2#
3# Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR>
4# SPDX-License-Identifier: BSD-2-Clause-Patent
5#
6##
7
8import os
9import re
10import sys
11import struct
12from   datetime import date
13
14# Generated file copyright header
15
16__copyright_txt__ = """## @file
17#
18#  THIS IS AUTO-GENERATED FILE BY BUILD TOOLS AND PLEASE DO NOT MAKE MODIFICATION.
19#
20#  This file lists all VPD informations for a platform collected by build.exe.
21#
22# Copyright (c) %4d, Intel Corporation. All rights reserved.<BR>
23# This program and the accompanying materials
24# are licensed and made available under the terms and conditions of the BSD License
25# which accompanies this distribution.  The full text of the license may be found at
26# http://opensource.org/licenses/bsd-license.php
27#
28# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
29# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
30#
31"""
32
33__copyright_bsf__ = """/** @file
34
35  Boot Setting File for Platform Configuration.
36
37  Copyright (c) %4d, Intel Corporation. All rights reserved.<BR>
38  This program and the accompanying materials
39  are licensed and made available under the terms and conditions of the BSD License
40  which accompanies this distribution.  The full text of the license may be found at
41  http://opensource.org/licenses/bsd-license.php
42
43  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
44  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
45
46  This file is automatically generated. Please do NOT modify !!!
47
48**/
49
50"""
51
52__copyright_h__ = """/** @file
53
54Copyright (c) %4d, Intel Corporation. All rights reserved.<BR>
55
56Redistribution and use in source and binary forms, with or without modification,
57are permitted provided that the following conditions are met:
58
59* Redistributions of source code must retain the above copyright notice, this
60  list of conditions and the following disclaimer.
61* Redistributions in binary form must reproduce the above copyright notice, this
62  list of conditions and the following disclaimer in the documentation and/or
63  other materials provided with the distribution.
64* Neither the name of Intel Corporation nor the names of its contributors may
65  be used to endorse or promote products derived from this software without
66  specific prior written permission.
67
68  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
69  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
70  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
71  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
72  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
73  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
74  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
75  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
76  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
77  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
78  THE POSSIBILITY OF SUCH DAMAGE.
79
80  This file is automatically generated. Please do NOT modify !!!
81
82**/
83"""
84
85def UpdateMemSiUpdInitOffsetValue (DscFile):
86    DscFd        = open(DscFile, "r")
87    DscLines     = DscFd.readlines()
88    DscFd.close()
89
90    DscContent = []
91    MemUpdInitOffset = 0
92    SiUpdInitOffset = 0
93    MemUpdInitOffsetValue = 0
94    SiUpdInitOffsetValue = 0
95
96    while len(DscLines):
97        DscLine  = DscLines.pop(0)
98        DscContent.append(DscLine)
99        DscLine = DscLine.strip()
100        Match = re.match("^([_a-zA-Z0-9]+).(MemoryInitUpdOffset)\s*\|\s*(0x[0-9A-F]+)\s*\|\s*(\d+|0x[0-9a-fA-F]+)\s*\|\s*(.+)",DscLine)
101        if Match:
102            MemUpdInitOffsetValue = int(Match.group(5), 0)
103        Match = re.match("^\s*([_a-zA-Z0-9]+).(SiliconInitUpdOffset)\s*\|\s*(0x[0-9A-F]+)\s*\|\s*(\d+|0x[0-9a-fA-F]+)\s*\|\s*(.+)",DscLine)
104        if Match:
105            SiUpdInitOffsetValue = int(Match.group(5), 0)
106        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*(0x244450554D454D24)",DscLine)
107        if Match:
108            MemUpdInitOffset = int(Match.group(3), 0)
109        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*(0x244450555F495324)",DscLine)
110        if Match:
111            SiUpdInitOffset = int(Match.group(3), 0)
112
113    if MemUpdInitOffsetValue != MemUpdInitOffset or SiUpdInitOffsetValue != SiUpdInitOffset:
114        MemUpdInitOffsetStr = "0x%08X" % MemUpdInitOffset
115        SiUpdInitOffsetStr = "0x%08X" % SiUpdInitOffset
116        DscFd = open(DscFile,"w")
117        for DscLine in DscContent:
118            Match = re.match("^\s*([_a-zA-Z0-9]+).(MemoryInitUpdOffset)\s*\|\s*(0x[0-9A-F]+)\s*\|\s*(\d+|0x[0-9a-fA-F]+)\s*\|\s*(.+)",DscLine)
119            if Match:
120                 DscLine = re.sub(r'(?:[^\s]+\s*$)', MemUpdInitOffsetStr + '\n', DscLine)
121            Match = re.match("^\s*([_a-zA-Z0-9]+).(SiliconInitUpdOffset)\s*\|\s*(0x[0-9A-F]+)\s*\|\s*(\d+|0x[0-9a-fA-F]+)\s*\|\s*(.+)",DscLine)
122            if Match:
123                 DscLine = re.sub(r'(?:[^\s]+\s*$)', SiUpdInitOffsetStr + '\n', line)
124            DscFd.writelines(DscLine)
125        DscFd.close()
126
127class CLogicalExpression:
128    def __init__(self):
129        self.index    = 0
130        self.string   = ''
131
132    def errExit(self, err = ''):
133        print "ERROR: Express parsing for:"
134        print "       %s" % self.string
135        print "       %s^" % (' ' * self.index)
136        if err:
137            print "INFO : %s" % err
138        raise SystemExit
139
140    def getNonNumber (self, n1, n2):
141        if not n1.isdigit():
142            return n1
143        if not n2.isdigit():
144            return n2
145        return None
146
147    def getCurr(self, lens = 1):
148        try:
149            if lens == -1:
150                return self.string[self.index :]
151            else:
152                if self.index + lens > len(self.string):
153                    lens = len(self.string) - self.index
154                return self.string[self.index : self.index + lens]
155        except Exception:
156            return ''
157
158    def isLast(self):
159        return self.index == len(self.string)
160
161    def moveNext(self, len = 1):
162        self.index += len
163
164    def skipSpace(self):
165        while not self.isLast():
166            if self.getCurr() in ' \t':
167                self.moveNext()
168            else:
169                return
170
171    def normNumber (self, val):
172        return True if val else False
173
174    def getNumber(self, var):
175        var = var.strip()
176        if   re.match('^0x[a-fA-F0-9]+$', var):
177            value = int(var, 16)
178        elif re.match('^[+-]?\d+$', var):
179            value = int(var, 10)
180        else:
181            value = None
182        return value
183
184    def parseValue(self):
185        self.skipSpace()
186        var = ''
187        while not self.isLast():
188            char = self.getCurr()
189            if re.match('^[\w.]', char):
190                var += char
191                self.moveNext()
192            else:
193                break
194        val = self.getNumber(var)
195        if val is None:
196            value = var
197        else:
198            value = "%d" % val
199        return value
200
201    def parseSingleOp(self):
202        self.skipSpace()
203        if re.match('^NOT\W', self.getCurr(-1)):
204            self.moveNext(3)
205            op  = self.parseBrace()
206            val = self.getNumber (op)
207            if val is None:
208                self.errExit ("'%s' is not a number" % op)
209            return "%d" % (not self.normNumber(int(op)))
210        else:
211            return self.parseValue()
212
213    def parseBrace(self):
214        self.skipSpace()
215        char = self.getCurr()
216        if char == '(':
217            self.moveNext()
218            value = self.parseExpr()
219            self.skipSpace()
220            if self.getCurr() != ')':
221                self.errExit ("Expecting closing brace or operator")
222            self.moveNext()
223            return value
224        else:
225            value = self.parseSingleOp()
226            return value
227
228    def parseCompare(self):
229        value = self.parseBrace()
230        while True:
231            self.skipSpace()
232            char = self.getCurr()
233            if char in ['<', '>']:
234                self.moveNext()
235                next = self.getCurr()
236                if next == '=':
237                    op = char + next
238                    self.moveNext()
239                else:
240                    op = char
241                result = self.parseBrace()
242                test = self.getNonNumber(result, value)
243                if test is None:
244                    value = "%d" % self.normNumber(eval (value + op + result))
245                else:
246                    self.errExit ("'%s' is not a valid number for comparision" % test)
247            elif char in ['=', '!']:
248                op = self.getCurr(2)
249                if op in ['==', '!=']:
250                    self.moveNext(2)
251                    result = self.parseBrace()
252                    test = self.getNonNumber(result, value)
253                    if test is None:
254                        value = "%d" % self.normNumber((eval (value + op + result)))
255                    else:
256                        value = "%d" % self.normNumber(eval ("'" + value + "'" + op + "'" + result + "'"))
257                else:
258                    break
259            else:
260                break
261        return value
262
263    def parseAnd(self):
264        value = self.parseCompare()
265        while True:
266            self.skipSpace()
267            if re.match('^AND\W', self.getCurr(-1)):
268                self.moveNext(3)
269                result = self.parseCompare()
270                test = self.getNonNumber(result, value)
271                if test is None:
272                    value = "%d" % self.normNumber(int(value) & int(result))
273                else:
274                    self.errExit ("'%s' is not a valid op number for AND" % test)
275            else:
276                break
277        return value
278
279    def parseOrXor(self):
280        value  = self.parseAnd()
281        op     = None
282        while True:
283            self.skipSpace()
284            op = None
285            if re.match('^XOR\W', self.getCurr(-1)):
286                self.moveNext(3)
287                op = '^'
288            elif re.match('^OR\W', self.getCurr(-1)):
289                self.moveNext(2)
290                op = '|'
291            else:
292                break
293            if op:
294                result = self.parseAnd()
295                test = self.getNonNumber(result, value)
296                if test is None:
297                    value = "%d" % self.normNumber(eval (value + op + result))
298                else:
299                    self.errExit ("'%s' is not a valid op number for XOR/OR" % test)
300        return value
301
302    def parseExpr(self):
303        return self.parseOrXor()
304
305    def getResult(self):
306        value = self.parseExpr()
307        self.skipSpace()
308        if not self.isLast():
309            self.errExit ("Unexpected character found '%s'" % self.getCurr())
310        test = self.getNumber(value)
311        if test is None:
312            self.errExit ("Result '%s' is not a number" % value)
313        return int(value)
314
315    def evaluateExpress (self, Expr):
316        self.index     = 0
317        self.string    = Expr
318        if self.getResult():
319            Result = True
320        else:
321            Result = False
322        return Result
323
324class CGenCfgOpt:
325    def __init__(self):
326        self.Debug          = False
327        self.Error          = ''
328
329        self._GlobalDataDef = """
330GlobalDataDef
331    SKUID = 0, "DEFAULT"
332EndGlobalData
333
334"""
335        self._BuidinOptionTxt = """
336List &EN_DIS
337    Selection 0x1 , "Enabled"
338    Selection 0x0 , "Disabled"
339EndList
340
341"""
342
343        self._BsfKeyList    = ['FIND','NAME','HELP','TYPE','PAGE','OPTION','ORDER']
344        self._HdrKeyList    = ['HEADER','STRUCT', 'EMBED']
345        self._BuidinOption  = {'$EN_DIS' : 'EN_DIS'}
346
347        self._MacroDict   = {}
348        self._CfgBlkDict  = {}
349        self._CfgPageDict = {}
350        self._CfgItemList = []
351        self._DscFile     = ''
352        self._FvDir       = ''
353        self._MapVer      = 0
354
355    def ParseMacros (self, MacroDefStr):
356        # ['-DABC=1', '-D', 'CFG_DEBUG=1', '-D', 'CFG_OUTDIR=Build']
357        self._MacroDict = {}
358        IsExpression = False
359        for Macro in MacroDefStr:
360            if Macro.startswith('-D'):
361                IsExpression = True
362                if len(Macro) > 2:
363                    Macro = Macro[2:]
364                else :
365                    continue
366            if IsExpression:
367                IsExpression = False
368                Match = re.match("(\w+)=(.+)", Macro)
369                if Match:
370                    self._MacroDict[Match.group(1)] = Match.group(2)
371                else:
372                    Match = re.match("(\w+)", Macro)
373                    if Match:
374                        self._MacroDict[Match.group(1)] = ''
375        if len(self._MacroDict) == 0:
376            Error = 1
377        else:
378            Error = 0
379            if self.Debug:
380                print "INFO : Macro dictionary:"
381                for Each in self._MacroDict:
382                    print "       $(%s) = [ %s ]" % (Each , self._MacroDict[Each])
383        return Error
384
385    def EvaulateIfdef   (self, Macro):
386        Result = Macro in self._MacroDict
387        if self.Debug:
388            print "INFO : Eval Ifdef [%s] : %s" % (Macro, Result)
389        return  Result
390
391    def ExpandMacros (self, Input):
392        Line = Input
393        Match = re.findall("\$\(\w+\)", Input)
394        if Match:
395            for Each in Match:
396              Variable = Each[2:-1]
397              if Variable in self._MacroDict:
398                  Line = Line.replace(Each, self._MacroDict[Variable])
399              else:
400                  if self.Debug:
401                      print "WARN : %s is not defined" % Each
402                  Line = Line.replace(Each, Each[2:-1])
403        return Line
404
405    def EvaluateExpress (self, Expr):
406        ExpExpr = self.ExpandMacros(Expr)
407        LogExpr = CLogicalExpression()
408        Result  = LogExpr.evaluateExpress (ExpExpr)
409        if self.Debug:
410            print "INFO : Eval Express [%s] : %s" % (Expr, Result)
411        return Result
412
413    def FormatListValue(self, ConfigDict):
414        Struct = ConfigDict['struct']
415        if Struct not in ['UINT8','UINT16','UINT32','UINT64']:
416            return
417
418        dataarray = []
419        binlist = ConfigDict['value'][1:-1].split(',')
420        for each in binlist:
421            each = each.strip()
422            if each.startswith('0x'):
423                value = int(each, 16)
424            else:
425                value = int(each)
426            dataarray.append(value)
427
428        unit = int(Struct[4:]) / 8
429        if int(ConfigDict['length']) != unit * len(dataarray):
430            raise Exception("Array size is not proper for '%s' !" % ConfigDict['cname'])
431
432        bytearray = []
433        for each in dataarray:
434            value = each
435            for loop in xrange(unit):
436                bytearray.append("0x%02X" % (value & 0xFF))
437                value = value >> 8
438        newvalue  = '{'  + ','.join(bytearray) + '}'
439        ConfigDict['value'] = newvalue
440        return ""
441
442    def ParseDscFile (self, DscFile, FvDir):
443        self._CfgItemList = []
444        self._CfgPageDict = {}
445        self._CfgBlkDict  = {}
446        self._DscFile     = DscFile
447        self._FvDir       = FvDir
448
449        IsDefSect       = False
450        IsUpdSect       = False
451        IsVpdSect       = False
452        Found           = False
453
454        IfStack         = []
455        ElifStack       = []
456        Error           = 0
457        ConfigDict      = {}
458
459        DscFd        = open(DscFile, "r")
460        DscLines     = DscFd.readlines()
461        DscFd.close()
462
463        while len(DscLines):
464            DscLine  = DscLines.pop(0).strip()
465            Handle   = False
466            Match    = re.match("^\[(.+)\]", DscLine)
467            if Match is not None:
468                if  Match.group(1).lower() == "Defines".lower():
469                    IsDefSect = True
470                    IsVpdSect = False
471                    IsUpdSect = False
472                elif Match.group(1).lower() == "PcdsDynamicVpd".lower():
473                    ConfigDict = {}
474                    ConfigDict['header']  = 'ON'
475                    ConfigDict['region']  = 'VPD'
476                    ConfigDict['order']   = -1
477                    ConfigDict['page']    = ''
478                    ConfigDict['name']    = ''
479                    ConfigDict['find']    = ''
480                    ConfigDict['struct']  = ''
481                    ConfigDict['embed']   = ''
482                    ConfigDict['subreg']  = []
483                    IsDefSect = False
484                    IsVpdSect = True
485                    IsUpdSect = False
486                elif Match.group(1).lower() == "PcdsDynamicVpd.Upd".lower():
487                    ConfigDict = {}
488                    ConfigDict['header']  = 'ON'
489                    ConfigDict['region']  = 'UPD'
490                    ConfigDict['order']   = -1
491                    ConfigDict['page']    = ''
492                    ConfigDict['name']    = ''
493                    ConfigDict['find']    = ''
494                    ConfigDict['struct']  = ''
495                    ConfigDict['embed']   = ''
496                    ConfigDict['subreg']  = []
497                    IsDefSect = False
498                    IsUpdSect = True
499                    IsVpdSect = False
500                    Found     = True
501                else:
502                    IsDefSect = False
503                    IsUpdSect = False
504                    IsVpdSect = False
505            else:
506                if IsDefSect or IsUpdSect or IsVpdSect:
507                    if re.match("^!else($|\s+#.+)", DscLine):
508                        if IfStack:
509                            IfStack[-1] = not IfStack[-1]
510                        else:
511                            print("ERROR: No paired '!if' found for '!else' for line '%s'" % DscLine)
512                            raise SystemExit
513                    elif re.match("^!endif($|\s+#.+)", DscLine):
514                        if IfStack:
515                            IfStack.pop()
516                            Level = ElifStack.pop()
517                            if Level > 0:
518                                del IfStack[-Level:]
519                        else:
520                            print("ERROR: No paired '!if' found for '!endif' for line '%s'" % DscLine)
521                            raise SystemExit
522                    else:
523                        Result = False
524                        Match = re.match("!(ifdef|ifndef)\s+(.+)", DscLine)
525                        if Match:
526                            Result = self.EvaulateIfdef (Match.group(2))
527                            if Match.group(1) == 'ifndef':
528                                Result = not Result
529                            IfStack.append(Result)
530                            ElifStack.append(0)
531                        else:
532                            Match  = re.match("!(if|elseif)\s+(.+)", DscLine)
533                            if Match:
534                                Result = self.EvaluateExpress(Match.group(2))
535                                if Match.group(1) == "if":
536                                    ElifStack.append(0)
537                                    IfStack.append(Result)
538                                else:   #elseif
539                                    if IfStack:
540                                        IfStack[-1] = not IfStack[-1]
541                                        IfStack.append(Result)
542                                        ElifStack[-1] = ElifStack[-1] + 1
543                                    else:
544                                        print("ERROR: No paired '!if' found for '!elif' for line '%s'" % DscLine)
545                                        raise SystemExit
546                            else:
547                                if IfStack:
548                                    Handle = reduce(lambda x,y: x and y, IfStack)
549                                else:
550                                    Handle = True
551                                if Handle:
552                                    Match = re.match("!include\s+(.+)", DscLine)
553                                    if Match:
554                                        IncludeFilePath = Match.group(1)
555                                        IncludeFilePath = self.ExpandMacros(IncludeFilePath)
556                                        try:
557                                            IncludeDsc  = open(IncludeFilePath, "r")
558                                        except:
559                                            print("ERROR: Cannot open file '%s'" % IncludeFilePath)
560                                            raise SystemExit
561                                        NewDscLines = IncludeDsc.readlines()
562                                        IncludeDsc.close()
563                                        DscLines = NewDscLines + DscLines
564                                    else:
565                                        if DscLine.startswith('!'):
566                                            print("ERROR: Unrecoginized directive for line '%s'" % DscLine)
567                                            raise SystemExit
568            if not Handle:
569                continue
570
571            if IsDefSect:
572                #DEFINE UPD_TOOL_GUID = 8C3D856A-9BE6-468E-850A-24F7A8D38E09
573                Match = re.match("^\s*(?:DEFINE\s+)*(\w+)\s*=\s*([-.\w]+)", DscLine)
574                if Match:
575                    self._MacroDict[Match.group(1)] = Match.group(2)
576                    if self.Debug:
577                        print "INFO : DEFINE %s = [ %s ]" % (Match.group(1), Match.group(2))
578            else:
579                Match = re.match("^\s*#\s+!(BSF|HDR)\s+(.+)", DscLine)
580                if Match:
581                    Remaining = Match.group(2)
582                    if Match.group(1) == 'BSF':
583                        Match = re.match("(?:^|.+\s+)PAGES:{(.+?)}", Remaining)
584                        if Match:
585                            # !BSF PAGES:{HSW:"Haswell System Agent", LPT:"Lynx Point PCH"}
586                            PageList = Match.group(1).split(',')
587                            for Page in PageList:
588                                Page  = Page.strip()
589                                Match = re.match("(\w+):\"(.+)\"", Page)
590                                self._CfgPageDict[Match.group(1)] = Match.group(2)
591
592                        Match = re.match("(?:^|.+\s+)BLOCK:{NAME:\"(.+)\"\s*,\s*VER:\"(.+)\"\s*}", Remaining)
593                        if Match:
594                            self._CfgBlkDict['name'] = Match.group(1)
595                            self._CfgBlkDict['ver']  = Match.group(2)
596
597                        for Key in self._BsfKeyList:
598                            Match = re.match("(?:^|.+\s+)%s:{(.+?)}" % Key, Remaining)
599                            if Match:
600                                if Key in ['NAME', 'HELP', 'OPTION'] and Match.group(1).startswith('+'):
601                                    ConfigDict[Key.lower()] += Match.group(1)[1:]
602                                else:
603                                    ConfigDict[Key.lower()]  = Match.group(1)
604                    else:
605                        for Key in self._HdrKeyList:
606                            Match = re.match("(?:^|.+\s+)%s:{(.+?)}" % Key, Remaining)
607                            if Match:
608                                ConfigDict[Key.lower()]  = Match.group(1)
609
610                # Check VPD/UPD
611                if IsUpdSect:
612                    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)
613                else:
614                    Match = re.match("^([_a-zA-Z0-9]+).([_a-zA-Z0-9]+)\s*\|\s*(0x[0-9A-F]+)(?:\s*\|\s*(.+))?",  DscLine)
615                if Match:
616                    ConfigDict['space']  = Match.group(1)
617                    ConfigDict['cname']  = Match.group(2)
618                    ConfigDict['offset'] = int (Match.group(3), 16)
619                    if ConfigDict['order'] == -1:
620                        ConfigDict['order'] = ConfigDict['offset'] << 8
621                    else:
622                        (Major, Minor) = ConfigDict['order'].split('.')
623                        ConfigDict['order'] = (int (Major, 16) << 8 ) +  int (Minor, 16)
624                    if IsUpdSect:
625                        Value = Match.group(5).strip()
626                        if Match.group(4).startswith("0x"):
627                            Length  = int (Match.group(4), 16)
628                        else :
629                            Length  = int (Match.group(4))
630                    else:
631                        Value = Match.group(4)
632                        if Value is None:
633                            Value = ''
634                        Value = Value.strip()
635                        if '|' in Value:
636                            Match = re.match("^.+\s*\|\s*(.+)", Value)
637                            if Match:
638                                Value = Match.group(1)
639                        Length = -1
640
641                    ConfigDict['length'] = Length
642                    Match = re.match("\$\((\w+)\)", Value)
643                    if Match:
644                        if Match.group(1) in self._MacroDict:
645                            Value = self._MacroDict[Match.group(1)]
646
647                    ConfigDict['value']  = Value
648                    if (len(Value) > 0)  and (Value[0] == '{'):
649                        Value = self.FormatListValue(ConfigDict)
650
651                    if ConfigDict['name']  == '':
652                        # Clear BSF specific items
653                        ConfigDict['bsfname']   = ''
654                        ConfigDict['help']   = ''
655                        ConfigDict['type']   = ''
656                        ConfigDict['option'] = ''
657
658                    self._CfgItemList.append(ConfigDict.copy())
659                    ConfigDict['name']   = ''
660                    ConfigDict['find']   = ''
661                    ConfigDict['struct'] = ''
662                    ConfigDict['embed']  = ''
663                    ConfigDict['order']  = -1
664                    ConfigDict['subreg'] = []
665                else:
666                    # It could be a virtual item as below
667                    # !BSF FIELD:{1:SerialDebugPortAddress0}
668                    Match = re.match("^\s*#\s+!BSF\s+FIELD:{(.+):(\d+)}", DscLine)
669                    if Match:
670                        SubCfgDict = ConfigDict
671                        SubCfgDict['cname']  = Match.group(1)
672                        SubCfgDict['length'] = int (Match.group(2))
673                        if SubCfgDict['length'] > 0:
674                            LastItem =  self._CfgItemList[-1]
675                            if len(LastItem['subreg']) == 0:
676                                SubOffset  = 0
677                            else:
678                                SubOffset += LastItem['subreg'][-1]['length']
679                            SubCfgDict['offset'] = SubOffset
680                            LastItem['subreg'].append (SubCfgDict.copy())
681                        ConfigDict['name']   = ''
682        return Error
683
684    def UpdateSubRegionDefaultValue (self):
685        Error = 0
686        for Item in self._CfgItemList:
687            if len(Item['subreg']) == 0:
688                continue
689            bytearray = []
690            if Item['value'][0] == '{':
691                binlist = Item['value'][1:-1].split(',')
692                for each in binlist:
693                    each = each.strip()
694                    if each.startswith('0x'):
695                        value = int(each, 16)
696                    else:
697                        value = int(each)
698                    bytearray.append(value)
699            else:
700                if Item['value'].startswith('0x'):
701                    value = int(Item['value'], 16)
702                else:
703                    value = int(Item['value'])
704                idx = 0;
705                while  idx < Item['length']:
706                    bytearray.append(value & 0xFF)
707                    value = value >> 8
708                    idx = idx + 1
709            for SubItem in Item['subreg']:
710                if SubItem['length'] in (1,2,4,8):
711                    valuelist = [b for b in bytearray[SubItem['offset']:SubItem['offset']+SubItem['length']]]
712                    valuelist.reverse()
713                    valuestr = "".join('%02X' % b for b in valuelist)
714                    SubItem['value'] = '0x%s' % valuestr
715                else:
716                    valuestr = ",".join('0x%02X' % b for b in bytearray[SubItem['offset']:SubItem['offset']+SubItem['length']])
717                    SubItem['value'] = '{%s}' % valuestr
718        return Error
719
720    def UpdateVpdSizeField (self):
721        FvDir = self._FvDir;
722
723        if 'VPD_TOOL_GUID' not in self._MacroDict:
724            self.Error = "VPD_TOOL_GUID definition is missing in DSC file"
725            return 1
726
727        VpdMapFile = os.path.join(FvDir, self._MacroDict['VPD_TOOL_GUID'] + '.map')
728        if not os.path.exists(VpdMapFile):
729            self.Error = "VPD MAP file '%s' does not exist" % VpdMapFile
730            return 2
731
732        MapFd       = open(VpdMapFile, "r")
733        MapLines    = MapFd.readlines()
734        MapFd.close()
735
736        VpdDict  = {}
737        PcdDict  = {}
738        for MapLine in MapLines:
739            #gPlatformFspPkgTokenSpaceGuid.PcdVpdRegionSign | DEFAULT | 0x0000 | 8 | 0x534450565F425346
740            #gPlatformFspPkgTokenSpaceGuid.PcdVpdRegionSign | 0x0000 | 8 | 0x534450565F425346
741            #gPlatformFspPkgTokenSpaceGuid.PcdTest          | 0x0008 | 5 | {0x01,0x02,0x03,0x04,0x05}
742            Match = re.match("([_a-zA-Z0-9]+).([_a-zA-Z0-9]+)(\s\|\sDEFAULT)?\s\|\s(0x[0-9A-F]{4})\s\|\s(\d+|0x[0-9a-fA-F]+)\s\|\s(\{?[x0-9a-fA-F,\s]+\}?)", MapLine)
743            if Match:
744                Space  = Match.group(1)
745                Name   = Match.group(2)
746                if (self._MapVer == 0) and (Match.group(3) != None):
747                    self._MapVer = 1
748                Offset = int (Match.group(4), 16)
749                if Match.group(5).startswith("0x"):
750                    Length = int (Match.group(5), 16)
751                else :
752                    Length = int (Match.group(5))
753                PcdDict["len"]   = Length
754                PcdDict["value"]   = Match.group(6)
755                VpdDict[Space+'.'+Name] = dict(PcdDict)
756
757        for Item in self._CfgItemList:
758            if Item['value'] == '':
759                Item['value']  = VpdDict[Item['space']+'.'+Item['cname']]['value']
760            if Item['length'] == -1:
761                Item['length'] = VpdDict[Item['space']+'.'+Item['cname']]['len']
762            if Item['struct'] != '':
763                Type = Item['struct'].strip()
764                if Type.endswith('*') and (Item['length'] != 4):
765                    self.Error = "Struct pointer '%s' has invalid size" % Type
766                    return 3
767
768        return 0
769
770    def CreateUpdTxtFile (self, UpdTxtFile):
771        FvDir = self._FvDir
772        if 'UPD_TOOL_GUID' not in self._MacroDict:
773            self.Error = "UPD_TOOL_GUID definition is missing in DSC file"
774            return 1
775
776        if UpdTxtFile == '':
777            UpdTxtFile = os.path.join(FvDir, self._MacroDict['UPD_TOOL_GUID'] + '.txt')
778
779        ReCreate = False
780        if not os.path.exists(UpdTxtFile):
781            ReCreate = True
782        else:
783            DscTime = os.path.getmtime(self._DscFile)
784            TxtTime = os.path.getmtime(UpdTxtFile)
785            if DscTime > TxtTime:
786                ReCreate = True
787
788        if not  ReCreate:
789            # DSC has not been modified yet
790            # So don't have to re-generate other files
791            self.Error = 'No DSC file change, skip to create UPD TXT file'
792            return 256
793
794        TxtFd = open(UpdTxtFile, "w")
795        TxtFd.write("%s\n"   % (__copyright_txt__ % date.today().year))
796
797        NextOffset = 0
798        SpaceIdx   = 0
799        if self._MapVer == 1:
800            Default = 'DEFAULT|'
801        else:
802            Default = ''
803        for Item in self._CfgItemList:
804            if Item['region'] != 'UPD':
805                continue
806            Offset = Item['offset']
807            if NextOffset < Offset:
808                # insert one line
809                TxtFd.write("%s.UnusedUpdSpace%d|%s0x%04X|0x%04X|{0}\n" % (Item['space'], SpaceIdx, Default, NextOffset, Offset - NextOffset))
810                SpaceIdx = SpaceIdx + 1
811            NextOffset = Offset + Item['length']
812            TxtFd.write("%s.%s|%s0x%04X|%s|%s\n" % (Item['space'],Item['cname'],Default,Item['offset'],Item['length'],Item['value']))
813        TxtFd.close()
814        return 0
815
816    def CreateField (self, Item, Name, Length, Offset, Struct, BsfName, Help):
817        PosName    = 28
818        PosComment = 30
819        NameLine=''
820        HelpLine=''
821
822        IsArray = False
823        if Length in [1,2,4,8]:
824            Type = "UINT%d" % (Length * 8)
825        else:
826            IsArray = True
827            Type = "UINT8"
828
829        if Item and Item['value'].startswith('{'):
830            Type = "UINT8"
831            IsArray = True
832
833        if Struct != '':
834            Type = Struct
835            if Struct in ['UINT8','UINT16','UINT32','UINT64']:
836                IsArray = True
837                Unit = int(Type[4:]) / 8
838                Length = Length / Unit
839            else:
840                IsArray = False
841
842        if IsArray:
843            Name = Name + '[%d]' % Length
844
845        if len(Type) < PosName:
846            Space1 = PosName - len(Type)
847        else:
848            Space1 = 1
849
850        if BsfName != '':
851            NameLine="    %s\n" % BsfName
852
853        if Help != '':
854            HelpLine="    %s\n" % Help
855
856        if Offset is None:
857            OffsetStr = '????'
858        else:
859            OffsetStr = '0x%04X' % Offset
860
861        return "/** Offset %s\n%s%s**/\n  %s%s%s;\n" % (OffsetStr, NameLine, HelpLine, Type, ' ' * Space1, Name,)
862
863    def PostProcessBody (self, TextBody):
864        NewTextBody = []
865        OldTextBody = []
866        IncludeLine = False
867        StructName  = ''
868        VariableName = ''
869        for Line in TextBody:
870           Match = re.match("^/\*\sEMBED_STRUCT:(\w+):(\w+):(START|END)\s\*/\s([\s\S]*)", Line)
871           if Match:
872               Line = Match.group(4)
873
874           if Match and Match.group(3) == 'START':
875               NewTextBody.append ('typedef struct {\n')
876               StructName   = Match.group(1)
877               VariableName = Match.group(2)
878               MatchOffset = re.search('/\*\*\sOffset\s0x([a-fA-F0-9]+)', Line)
879               if MatchOffset:
880                   Offset = int(MatchOffset.group(1), 16)
881               else:
882                   Offset = None
883               Line
884               IncludeLine = True
885               OldTextBody.append (self.CreateField (None, VariableName, 0, Offset, StructName, '', ''))
886           if IncludeLine:
887               NewTextBody.append (Line)
888           else:
889               OldTextBody.append (Line)
890
891           if Match and Match.group(3) == 'END':
892               if (StructName != Match.group(1)) or (VariableName != Match.group(2)):
893                   print "Unmatched struct name '%s' and '%s' !"  % (StructName, Match.group(1))
894               else:
895                   NewTextBody.append ('} %s;\n\n' %  StructName)
896               IncludeLine = False
897        NewTextBody.extend(OldTextBody)
898        return NewTextBody
899
900    def CreateHeaderFile (self, InputHeaderFile, IsInternal):
901        FvDir = self._FvDir
902
903        if IsInternal:
904            HeaderFile = os.path.join(FvDir, 'FspUpdVpdInternal.h')
905        else:
906            HeaderFile = os.path.join(FvDir, 'FspUpdVpd.h')
907
908        # Check if header needs to be recreated
909        ReCreate = False
910        if IsInternal:
911            if not os.path.exists(HeaderFile):
912                ReCreate = True
913            else:
914                DscTime  = os.path.getmtime(self._DscFile)
915                HeadTime = os.path.getmtime(HeaderFile)
916                if not os.path.exists(InputHeaderFile):
917                    InpTime =  HeadTime
918                else:
919                    InpTime  = os.path.getmtime(InputHeaderFile)
920                if DscTime > HeadTime or InpTime > HeadTime:
921                    ReCreate = True
922
923            if not ReCreate:
924                self.Error = "No DSC or input header file is changed, skip the header file generating"
925                return 256
926
927        TxtBody = []
928        for Item in self._CfgItemList:
929           if str(Item['cname']) == 'Signature' and Item['length'] == 8:
930               Value = int(Item['value'], 16)
931               Chars = []
932               while Value != 0x0:
933                   Chars.append(chr(Value & 0xFF))
934                   Value = Value >> 8
935               SignatureStr = ''.join(Chars)
936               if int(Item['offset']) == 0:
937                   TxtBody.append("#define FSP_UPD_SIGNATURE                %s        /* '%s' */\n" % (Item['value'], SignatureStr))
938               elif 'MEM' in SignatureStr:
939                   TxtBody.append("#define FSP_MEMORY_INIT_UPD_SIGNATURE    %s        /* '%s' */\n" % (Item['value'], SignatureStr))
940               else:
941                   TxtBody.append("#define FSP_SILICON_INIT_UPD_SIGNATURE   %s        /* '%s' */\n" % (Item['value'], SignatureStr))
942        TxtBody.append("\n")
943
944        for Region in ['UPD', 'VPD']:
945
946            # Write  PcdVpdRegionSign and PcdImageRevision
947            if Region[0] == 'V':
948                if 'VPD_TOOL_GUID' not in self._MacroDict:
949                    self.Error = "VPD_TOOL_GUID definition is missing in DSC file"
950                    return 1
951
952                BinFile = os.path.join(FvDir, self._MacroDict['VPD_TOOL_GUID'] + ".bin")
953                if not os.path.exists(BinFile):
954                    self.Error = "VPD binary file '%s' does not exist" % BinFile
955                    return 2
956
957                BinFd = open(BinFile, "rb")
958                IdStr    = BinFd.read(0x08)
959                ImageId  = struct.unpack('<Q', IdStr)
960                ImageRev = struct.unpack('<I', BinFd.read(0x04))
961                BinFd.close()
962
963                TxtBody.append("#define FSP_IMAGE_ID    0x%016X        /* '%s' */\n" % (ImageId[0], IdStr))
964                TxtBody.append("#define FSP_IMAGE_REV   0x%08X \n\n" % ImageRev[0])
965
966            TxtBody.append("typedef struct _" + Region[0]  + "PD_DATA_REGION {\n")
967            NextOffset  = 0
968            SpaceIdx    = 0
969            Offset      = 0
970
971            LastVisible = True
972            ResvOffset  = 0
973            ResvIdx     = 0
974            LineBuffer  = []
975            for Item in self._CfgItemList:
976                if Item['region'] != Region:
977                    continue
978
979                NextVisible = LastVisible
980                if not IsInternal:
981                    if LastVisible and (Item['header'] == 'OFF'):
982                        NextVisible = False
983                        ResvOffset  = Item['offset']
984                    elif (not LastVisible) and Item['header'] == 'ON':
985                        NextVisible = True
986                        Name = "Reserved" + Region[0] + "pdSpace%d" % ResvIdx
987                        ResvIdx = ResvIdx + 1
988                        TxtBody.append(self.CreateField (Item, Name, Item["offset"] - ResvOffset, ResvOffset, '', '', ''))
989
990                if  Offset < Item["offset"]:
991                    if IsInternal or LastVisible:
992                        Name = "Unused" + Region[0] + "pdSpace%d" % SpaceIdx
993                        LineBuffer.append(self.CreateField (Item, Name, Item["offset"] - Offset, Offset, '', '', ''))
994                    SpaceIdx = SpaceIdx + 1
995                    Offset   = Item["offset"]
996
997                if Offset != Item["offset"]:
998                    self.Error = "Unsorted offset 0x%04X\n" % Item["offset"]
999                    return 3
1000
1001                LastVisible = NextVisible
1002
1003                Offset = Offset + Item["length"]
1004                if IsInternal or LastVisible:
1005                    for Each in LineBuffer:
1006                        TxtBody.append (Each)
1007                    LineBuffer = []
1008                    Embed = Item["embed"].upper()
1009                    if Embed.endswith(':START') or Embed.endswith(':END'):
1010                        Marker = '/* EMBED_STRUCT:%s */ ' % Item["embed"]
1011                    else:
1012                        if Embed == '':
1013                            Marker = '';
1014                        else:
1015                            self.Error = "Invalid embedded structure format '%s'!\n" % Item["embed"]
1016                            return 4
1017                    Line = Marker + self.CreateField (Item, Item["cname"], Item["length"], Item["offset"], Item['struct'], Item['name'], Item['help'])
1018                    TxtBody.append(Line)
1019
1020            TxtBody.append("} " + Region[0] + "PD_DATA_REGION;\n\n")
1021
1022        # Handle the embedded data structure
1023        TxtBody = self.PostProcessBody (TxtBody)
1024
1025        HeaderFd = open(HeaderFile, "w")
1026        FileBase = os.path.basename(HeaderFile)
1027        FileName = FileBase.replace(".", "_").upper()
1028        HeaderFd.write("%s\n"   % (__copyright_h__ % date.today().year))
1029        HeaderFd.write("#ifndef __%s__\n"   % FileName)
1030        HeaderFd.write("#define __%s__\n\n" % FileName)
1031        HeaderFd.write("#pragma pack(1)\n\n")
1032
1033        if InputHeaderFile != '':
1034            if not os.path.exists(InputHeaderFile):
1035                 self.Error = "Input header file '%s' does not exist" % InputHeaderFile
1036                 return 6
1037
1038            InFd         = open(InputHeaderFile, "r")
1039            IncLines     = InFd.readlines()
1040            InFd.close()
1041
1042            Export = False
1043            for Line in IncLines:
1044                Match = re.search ("!EXPORT\s+EXTERNAL_BOOTLOADER_STRUCT_(BEGIN|END)\s+", Line)
1045                if Match:
1046                    if Match.group(1) == "BEGIN":
1047                        Export = True
1048                        continue
1049                    else:
1050                        Export = False
1051                        continue
1052                if Export:
1053                    HeaderFd.write(Line)
1054            HeaderFd.write("\n\n")
1055
1056        for Line in TxtBody:
1057            HeaderFd.write (Line)
1058        HeaderFd.write("#pragma pack()\n\n")
1059        HeaderFd.write("#endif\n")
1060        HeaderFd.close()
1061
1062        return 0
1063
1064    def WriteBsfStruct  (self, BsfFd, Item):
1065        if Item['type'] == "None":
1066            Space = "gPlatformFspPkgTokenSpaceGuid"
1067        else:
1068            Space = Item['space']
1069        Line = "    $%s_%s" % (Space, Item['cname'])
1070        Match = re.match("\s*\{([x0-9a-fA-F,\s]+)\}\s*", Item['value'])
1071        if Match:
1072            DefaultValue = Match.group(1).strip()
1073        else:
1074            DefaultValue = Item['value'].strip()
1075        BsfFd.write("    %s%s%4d bytes    $_DEFAULT_ = %s\n" % (Line, ' ' * (64 - len(Line)), Item['length'], DefaultValue))
1076        TmpList = []
1077        if  Item['type'] == "Combo":
1078            if not Item['option'] in self._BuidinOption:
1079                OptList = Item['option'].split(',')
1080                for Option in OptList:
1081                    Option = Option.strip()
1082                    (OpVal, OpStr) = Option.split(':')
1083                    TmpList.append((OpVal, OpStr))
1084        return  TmpList
1085
1086    def WriteBsfOption  (self, BsfFd, Item):
1087        PcdName   = Item['space'] + '_' + Item['cname']
1088        WriteHelp = 0
1089        if Item['type'] == "Combo":
1090            if Item['option'] in self._BuidinOption:
1091                Options = self._BuidinOption[Item['option']]
1092            else:
1093                Options = PcdName
1094            BsfFd.write('    %s $%s, "%s", &%s,\n' % (Item['type'], PcdName, Item['name'], Options));
1095            WriteHelp = 1
1096        elif Item['type'].startswith("EditNum"):
1097            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'])
1098            if Match:
1099                BsfFd.write('    EditNum $%s, "%s", %s,\n' % (PcdName, Item['name'], Match.group(1)));
1100                WriteHelp = 2
1101        elif Item['type'].startswith("EditText"):
1102            BsfFd.write('    %s $%s, "%s",\n' % (Item['type'], PcdName, Item['name']));
1103            WriteHelp = 1
1104        elif Item['type'] == "Table":
1105            Columns = Item['option'].split(',')
1106            if len(Columns) != 0:
1107                BsfFd.write('    %s $%s "%s",' % (Item['type'], PcdName, Item['name']));
1108                for Col in Columns:
1109                    Fmt = Col.split(':')
1110                    if len(Fmt) != 3:
1111                        raise Exception("Column format '%s' is invalid !" % Fmt)
1112                    try:
1113                        Dtype = int(Fmt[1].strip())
1114                    except:
1115                        raise Exception("Column size '%s' is invalid !" % Fmt[1])
1116                    BsfFd.write('\n        Column "%s", %d bytes, %s' % (Fmt[0].strip(), Dtype, Fmt[2].strip()))
1117                BsfFd.write(',\n')
1118                WriteHelp = 1
1119
1120        if WriteHelp  > 0:
1121            HelpLines = Item['help'].split('\\n\\r')
1122            FirstLine = True
1123            for HelpLine in HelpLines:
1124                if FirstLine:
1125                    FirstLine = False
1126                    BsfFd.write('        Help "%s"\n' % (HelpLine));
1127                else:
1128                    BsfFd.write('             "%s"\n' % (HelpLine));
1129            if WriteHelp == 2:
1130                    BsfFd.write('             "Valid range: %s ~ %s"\n' % (Match.group(2), Match.group(3)));
1131
1132    def GenerateBsfFile (self, BsfFile):
1133
1134        if BsfFile == '':
1135            self.Error = "BSF output file '%s' is invalid" % BsfFile
1136            return 1
1137
1138        Error = 0
1139        OptionDict = {}
1140        BsfFd      = open(BsfFile, "w")
1141        BsfFd.write("%s\n" % (__copyright_bsf__ % date.today().year))
1142        BsfFd.write("%s\n" % self._GlobalDataDef);
1143        BsfFd.write("StructDef\n")
1144        NextOffset = -1
1145        for Item in self._CfgItemList:
1146            if Item['find'] != '':
1147                BsfFd.write('\n    Find "%s"\n' % Item['find'])
1148                NextOffset = Item['offset'] + Item['length']
1149            if Item['name'] != '':
1150                if NextOffset != Item['offset']:
1151                    BsfFd.write("        Skip %d bytes\n" % (Item['offset'] - NextOffset))
1152                if len(Item['subreg']) > 0:
1153                    NextOffset =  Item['offset']
1154                    for SubItem in Item['subreg']:
1155                        NextOffset += SubItem['length']
1156                        if SubItem['name'] == '':
1157                            BsfFd.write("        Skip %d bytes\n" % (SubItem['length']))
1158                        else:
1159                            Options = self.WriteBsfStruct(BsfFd, SubItem)
1160                            if len(Options) > 0:
1161                                OptionDict[SubItem['space']+'_'+SubItem['cname']] = Options
1162                    if (Item['offset'] + Item['length']) <  NextOffset:
1163                        self.Error = "BSF sub region '%s' length does not match" % (Item['space']+'.'+Item['cname'])
1164                        return 2
1165                else:
1166                    NextOffset = Item['offset'] + Item['length']
1167                    Options = self.WriteBsfStruct(BsfFd, Item)
1168                    if len(Options) > 0:
1169                        OptionDict[Item['space']+'_'+Item['cname']] = Options
1170        BsfFd.write("\nEndStruct\n\n")
1171
1172        BsfFd.write("%s" % self._BuidinOptionTxt);
1173
1174        for Each in OptionDict:
1175            BsfFd.write("List &%s\n" % Each);
1176            for Item in OptionDict[Each]:
1177                BsfFd.write('    Selection %s , "%s"\n' % (Item[0], Item[1]));
1178            BsfFd.write("EndList\n\n");
1179
1180        BsfFd.write("BeginInfoBlock\n");
1181        BsfFd.write('    PPVer       "%s"\n' % (self._CfgBlkDict['ver']));
1182        BsfFd.write('    Description "%s"\n' % (self._CfgBlkDict['name']));
1183        BsfFd.write("EndInfoBlock\n\n");
1184
1185        for Each in self._CfgPageDict:
1186            BsfFd.write('Page "%s"\n' % self._CfgPageDict[Each]);
1187            BsfItems = []
1188            for Item in self._CfgItemList:
1189                if Item['name'] != '':
1190                    if Item['page'] != Each:
1191                        continue
1192                    if len(Item['subreg']) > 0:
1193                        for SubItem in Item['subreg']:
1194                            if SubItem['name'] != '':
1195                                BsfItems.append(SubItem)
1196                    else:
1197                        BsfItems.append(Item)
1198
1199            BsfItems.sort(key=lambda x: x['order'])
1200
1201            for Item in BsfItems:
1202                self.WriteBsfOption (BsfFd, Item)
1203            BsfFd.write("EndPage\n\n");
1204
1205        BsfFd.close()
1206        return  Error
1207
1208
1209def Usage():
1210    print "GenCfgOpt Version 0.50"
1211    print "Usage:"
1212    print "    GenCfgOpt  UPDTXT  PlatformDscFile BuildFvDir  [TxtOutFile]     [-D Macros]"
1213    print "    GenCfgOpt  HEADER  PlatformDscFile BuildFvDir  [InputHFile]     [-D Macros]"
1214    print "    GenCfgOpt  GENBSF  PlatformDscFile BuildFvDir  BsfOutFile       [-D Macros]"
1215
1216def Main():
1217    #
1218    # Parse the options and args
1219    #
1220    GenCfgOpt = CGenCfgOpt()
1221    argc = len(sys.argv)
1222    if argc < 4:
1223        Usage()
1224        return 1
1225    else:
1226        DscFile = sys.argv[2]
1227        if not os.path.exists(DscFile):
1228            print "ERROR: Cannot open DSC file '%s' !" % DscFile
1229            return 2
1230
1231        UpdateMemSiUpdInitOffsetValue(DscFile)
1232
1233        OutFile = ''
1234        if argc > 4:
1235            if sys.argv[4][0] == '-':
1236                Start = 4
1237            else:
1238                OutFile = sys.argv[4]
1239                Start = 5
1240            if GenCfgOpt.ParseMacros(sys.argv[Start:]) != 0:
1241                print "ERROR: Macro parsing failed !"
1242                return 3
1243
1244        FvDir = sys.argv[3]
1245        if not os.path.isdir(FvDir):
1246            print "ERROR: FV folder '%s' is invalid !" % FvDir
1247            return 4
1248
1249        if GenCfgOpt.ParseDscFile(DscFile, FvDir) != 0:
1250            print "ERROR: %s !" % GenCfgOpt.Error
1251            return 5
1252
1253        if GenCfgOpt.UpdateVpdSizeField() != 0:
1254            print "ERROR: %s !" % GenCfgOpt.Error
1255            return 6
1256
1257        if GenCfgOpt.UpdateSubRegionDefaultValue() != 0:
1258            print "ERROR: %s !" % GenCfgOpt.Error
1259            return 7
1260
1261        if sys.argv[1] == "UPDTXT":
1262            Ret = GenCfgOpt.CreateUpdTxtFile(OutFile)
1263            if Ret != 0:
1264                # No change is detected
1265                if Ret == 256:
1266                    print "INFO: %s !" % (GenCfgOpt.Error)
1267                else :
1268                    print "ERROR: %s !" % (GenCfgOpt.Error)
1269                return Ret
1270        elif sys.argv[1] == "HEADER":
1271            Ret = GenCfgOpt.CreateHeaderFile(OutFile, True)
1272            if Ret != 0:
1273                # No change is detected
1274                if Ret == 256:
1275                    print "INFO: %s !" % (GenCfgOpt.Error)
1276                else :
1277                    print "ERROR: %s !" % (GenCfgOpt.Error)
1278                return Ret
1279            if GenCfgOpt.CreateHeaderFile(OutFile, False) != 0:
1280                print "ERROR: %s !" % GenCfgOpt.Error
1281                return 8
1282        elif sys.argv[1] == "GENBSF":
1283            if GenCfgOpt.GenerateBsfFile(OutFile) != 0:
1284                print "ERROR: %s !" % GenCfgOpt.Error
1285                return 9
1286        else:
1287            if argc < 5:
1288                Usage()
1289                return 1
1290            print "ERROR: Unknown command '%s' !" % sys.argv[1]
1291            Usage()
1292            return 1
1293        return 0
1294    return 0
1295
1296
1297if __name__ == '__main__':
1298    sys.exit(Main())
1299