Home | History | Annotate | Download | only in Tools
      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 
     14 import os
     15 import re
     16 import sys
     17 import struct
     18 from   datetime import date
     19 
     20 # Generated file copyright header

     21 
     22 __copyright_txt__ = """## @file
     23 #
     24 #  THIS IS AUTO-GENERATED FILE BY BUILD TOOLS AND PLEASE DO NOT MAKE MODIFICATION.
     25 #
     26 #  This file lists all VPD informations for a platform collected by build.exe.
     27 #
     28 # Copyright (c) %4d, Intel Corporation. All rights reserved.<BR>
     29 # This program and the accompanying materials
     30 # are licensed and made available under the terms and conditions of the BSD License
     31 # which accompanies this distribution.  The full text of the license may be found at
     32 # http://opensource.org/licenses/bsd-license.php
     33 #
     34 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     35 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     36 #
     37 """
     38 
     39 __copyright_bsf__ = """/** @file
     40 
     41   Boot Setting File for Platform Configuration.
     42 
     43   Copyright (c) %4d, Intel Corporation. All rights reserved.<BR>
     44   This program and the accompanying materials
     45   are licensed and made available under the terms and conditions of the BSD License
     46   which accompanies this distribution.  The full text of the license may be found at
     47   http://opensource.org/licenses/bsd-license.php
     48 
     49   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     50   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     51 
     52   This file is automatically generated. Please do NOT modify !!!
     53 
     54 **/
     55 
     56 """
     57 
     58 __copyright_h__ = """/** @file
     59 
     60 Copyright (c) %4d, Intel Corporation. All rights reserved.<BR>
     61 
     62 Redistribution and use in source and binary forms, with or without modification,
     63 are permitted provided that the following conditions are met:
     64 
     65 * Redistributions of source code must retain the above copyright notice, this
     66   list of conditions and the following disclaimer.
     67 * Redistributions in binary form must reproduce the above copyright notice, this
     68   list of conditions and the following disclaimer in the documentation and/or
     69   other materials provided with the distribution.
     70 * Neither the name of Intel Corporation nor the names of its contributors may
     71   be used to endorse or promote products derived from this software without
     72   specific prior written permission.
     73 
     74   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     75   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     76   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     77   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
     78   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     79   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     80   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     81   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     82   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     83   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
     84   THE POSSIBILITY OF SUCH DAMAGE.
     85 
     86   This file is automatically generated. Please do NOT modify !!!
     87 
     88 **/
     89 """
     90 
     91 def 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 
    133 class 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 
    330 class CGenCfgOpt:
    331     def __init__(self):
    332         self.Debug          = False
    333         self.Error          = ''
    334 
    335         self._GlobalDataDef = """
    336 GlobalDataDef
    337     SKUID = 0, "DEFAULT"
    338 EndGlobalData
    339 
    340 """
    341         self._BuidinOptionTxt = """
    342 List &EN_DIS
    343     Selection 0x1 , "Enabled"
    344     Selection 0x0 , "Disabled"
    345 EndList
    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 
   1215 def 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 
   1222 def 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 
   1303 if __name__ == '__main__':
   1304     sys.exit(Main())
   1305