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