Switches regex patterns to raw text to resolve python 3.12 syntax warnings in regards to invalid escape sequences, as is suggested by the re (regex) module in python. Cc: Rebecca Cran <rebecca@bsdio.com> Cc: Liming Gao <gaoliming@byosoft.com.cn> Cc: Bob Feng <bob.c.feng@intel.com> Cc: Yuwei Chen <yuwei.chen@intel.com> Signed-off-by: Joey Vagedes <joey.vagedes@gmail.com> Reviewed-by: Rebecca Cran <rebecca@bsdio.com>
		
			
				
	
	
		
			465 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			465 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
## @file
 | 
						|
# This file is used to generate DEPEX file for module's dependency expression
 | 
						|
#
 | 
						|
# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
 | 
						|
# SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
 | 
						|
## Import Modules
 | 
						|
#
 | 
						|
import sys
 | 
						|
import Common.LongFilePathOs as os
 | 
						|
import re
 | 
						|
import traceback
 | 
						|
from Common.LongFilePathSupport import OpenLongFilePath as open
 | 
						|
from io import BytesIO
 | 
						|
from struct import pack
 | 
						|
from Common.BuildToolError import *
 | 
						|
from Common.Misc import SaveFileOnChange
 | 
						|
from Common.Misc import GuidStructureStringToGuidString
 | 
						|
from Common.Misc import GuidStructureByteArrayToGuidString
 | 
						|
from Common.Misc import GuidStringToGuidStructureString
 | 
						|
from Common import EdkLogger as EdkLogger
 | 
						|
from Common.BuildVersion import gBUILD_VERSION
 | 
						|
from Common.DataType import *
 | 
						|
 | 
						|
## Regular expression for matching "DEPENDENCY_START ... DEPENDENCY_END"
 | 
						|
gStartClosePattern = re.compile(".*DEPENDENCY_START(.+)DEPENDENCY_END.*", re.S)
 | 
						|
 | 
						|
## Mapping between module type and EFI phase
 | 
						|
gType2Phase = {
 | 
						|
    SUP_MODULE_BASE              :   None,
 | 
						|
    SUP_MODULE_SEC               :   "PEI",
 | 
						|
    SUP_MODULE_PEI_CORE          :   "PEI",
 | 
						|
    SUP_MODULE_PEIM              :   "PEI",
 | 
						|
    SUP_MODULE_DXE_CORE          :   "DXE",
 | 
						|
    SUP_MODULE_DXE_DRIVER        :   "DXE",
 | 
						|
    SUP_MODULE_DXE_SMM_DRIVER    :   "DXE",
 | 
						|
    SUP_MODULE_DXE_RUNTIME_DRIVER:   "DXE",
 | 
						|
    SUP_MODULE_DXE_SAL_DRIVER    :   "DXE",
 | 
						|
    SUP_MODULE_UEFI_DRIVER       :   "DXE",
 | 
						|
    SUP_MODULE_UEFI_APPLICATION  :   "DXE",
 | 
						|
    SUP_MODULE_SMM_CORE          :   "DXE",
 | 
						|
    SUP_MODULE_MM_STANDALONE     :   "MM",
 | 
						|
    SUP_MODULE_MM_CORE_STANDALONE :  "MM",
 | 
						|
}
 | 
						|
 | 
						|
## Convert dependency expression string into EFI internal representation
 | 
						|
#
 | 
						|
#   DependencyExpression class is used to parse dependency expression string and
 | 
						|
# convert it into its binary form.
 | 
						|
#
 | 
						|
class DependencyExpression:
 | 
						|
 | 
						|
    ArchProtocols = {
 | 
						|
                        '665e3ff6-46cc-11d4-9a38-0090273fc14d',     #   'gEfiBdsArchProtocolGuid'
 | 
						|
                        '26baccb1-6f42-11d4-bce7-0080c73c8881',     #   'gEfiCpuArchProtocolGuid'
 | 
						|
                        '26baccb2-6f42-11d4-bce7-0080c73c8881',     #   'gEfiMetronomeArchProtocolGuid'
 | 
						|
                        '1da97072-bddc-4b30-99f1-72a0b56fff2a',     #   'gEfiMonotonicCounterArchProtocolGuid'
 | 
						|
                        '27cfac87-46cc-11d4-9a38-0090273fc14d',     #   'gEfiRealTimeClockArchProtocolGuid'
 | 
						|
                        '27cfac88-46cc-11d4-9a38-0090273fc14d',     #   'gEfiResetArchProtocolGuid'
 | 
						|
                        'b7dfb4e1-052f-449f-87be-9818fc91b733',     #   'gEfiRuntimeArchProtocolGuid'
 | 
						|
                        'a46423e3-4617-49f1-b9ff-d1bfa9115839',     #   'gEfiSecurityArchProtocolGuid'
 | 
						|
                        '26baccb3-6f42-11d4-bce7-0080c73c8881',     #   'gEfiTimerArchProtocolGuid'
 | 
						|
                        '6441f818-6362-4e44-b570-7dba31dd2453',     #   'gEfiVariableWriteArchProtocolGuid'
 | 
						|
                        '1e5668e2-8481-11d4-bcf1-0080c73c8881',     #   'gEfiVariableArchProtocolGuid'
 | 
						|
                        '665e3ff5-46cc-11d4-9a38-0090273fc14d'      #   'gEfiWatchdogTimerArchProtocolGuid'
 | 
						|
                    }
 | 
						|
 | 
						|
    OpcodePriority = {
 | 
						|
        DEPEX_OPCODE_AND   :   1,
 | 
						|
        DEPEX_OPCODE_OR    :   1,
 | 
						|
        DEPEX_OPCODE_NOT   :   2,
 | 
						|
    }
 | 
						|
 | 
						|
    Opcode = {
 | 
						|
        "PEI"   : {
 | 
						|
            DEPEX_OPCODE_PUSH  :   0x02,
 | 
						|
            DEPEX_OPCODE_AND   :   0x03,
 | 
						|
            DEPEX_OPCODE_OR    :   0x04,
 | 
						|
            DEPEX_OPCODE_NOT   :   0x05,
 | 
						|
            DEPEX_OPCODE_TRUE  :   0x06,
 | 
						|
            DEPEX_OPCODE_FALSE :   0x07,
 | 
						|
            DEPEX_OPCODE_END   :   0x08
 | 
						|
        },
 | 
						|
 | 
						|
        "DXE"   : {
 | 
						|
            DEPEX_OPCODE_BEFORE:   0x00,
 | 
						|
            DEPEX_OPCODE_AFTER :   0x01,
 | 
						|
            DEPEX_OPCODE_PUSH  :   0x02,
 | 
						|
            DEPEX_OPCODE_AND   :   0x03,
 | 
						|
            DEPEX_OPCODE_OR    :   0x04,
 | 
						|
            DEPEX_OPCODE_NOT   :   0x05,
 | 
						|
            DEPEX_OPCODE_TRUE  :   0x06,
 | 
						|
            DEPEX_OPCODE_FALSE :   0x07,
 | 
						|
            DEPEX_OPCODE_END   :   0x08,
 | 
						|
            DEPEX_OPCODE_SOR   :   0x09
 | 
						|
        },
 | 
						|
 | 
						|
        "MM"   : {
 | 
						|
            DEPEX_OPCODE_BEFORE:   0x00,
 | 
						|
            DEPEX_OPCODE_AFTER :   0x01,
 | 
						|
            DEPEX_OPCODE_PUSH  :   0x02,
 | 
						|
            DEPEX_OPCODE_AND   :   0x03,
 | 
						|
            DEPEX_OPCODE_OR    :   0x04,
 | 
						|
            DEPEX_OPCODE_NOT   :   0x05,
 | 
						|
            DEPEX_OPCODE_TRUE  :   0x06,
 | 
						|
            DEPEX_OPCODE_FALSE :   0x07,
 | 
						|
            DEPEX_OPCODE_END   :   0x08,
 | 
						|
            DEPEX_OPCODE_SOR   :   0x09
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    # all supported op codes and operands
 | 
						|
    SupportedOpcode = [DEPEX_OPCODE_BEFORE, DEPEX_OPCODE_AFTER, DEPEX_OPCODE_PUSH, DEPEX_OPCODE_AND, DEPEX_OPCODE_OR, DEPEX_OPCODE_NOT, DEPEX_OPCODE_END, DEPEX_OPCODE_SOR]
 | 
						|
    SupportedOperand = [DEPEX_OPCODE_TRUE, DEPEX_OPCODE_FALSE]
 | 
						|
 | 
						|
    OpcodeWithSingleOperand = [DEPEX_OPCODE_NOT, DEPEX_OPCODE_BEFORE, DEPEX_OPCODE_AFTER]
 | 
						|
    OpcodeWithTwoOperand = [DEPEX_OPCODE_AND, DEPEX_OPCODE_OR]
 | 
						|
 | 
						|
    # op code that should not be the last one
 | 
						|
    NonEndingOpcode = [DEPEX_OPCODE_AND, DEPEX_OPCODE_OR, DEPEX_OPCODE_NOT, DEPEX_OPCODE_SOR]
 | 
						|
    # op code must not present at the same time
 | 
						|
    ExclusiveOpcode = [DEPEX_OPCODE_BEFORE, DEPEX_OPCODE_AFTER]
 | 
						|
    # op code that should be the first one if it presents
 | 
						|
    AboveAllOpcode = [DEPEX_OPCODE_SOR, DEPEX_OPCODE_BEFORE, DEPEX_OPCODE_AFTER]
 | 
						|
 | 
						|
    #
 | 
						|
    # open and close brace must be taken as individual tokens
 | 
						|
    #
 | 
						|
    TokenPattern = re.compile(r"(\(|\)|\{[^{}]+\{?[^{}]+\}?[ ]*\}|\w+)")
 | 
						|
 | 
						|
    ## Constructor
 | 
						|
    #
 | 
						|
    #   @param  Expression  The list or string of dependency expression
 | 
						|
    #   @param  ModuleType  The type of the module using the dependency expression
 | 
						|
    #
 | 
						|
    def __init__(self, Expression, ModuleType, Optimize=False):
 | 
						|
        self.ModuleType = ModuleType
 | 
						|
        self.Phase = gType2Phase[ModuleType]
 | 
						|
        if isinstance(Expression, type([])):
 | 
						|
            self.ExpressionString = " ".join(Expression)
 | 
						|
            self.TokenList = Expression
 | 
						|
        else:
 | 
						|
            self.ExpressionString = Expression
 | 
						|
            self.GetExpressionTokenList()
 | 
						|
 | 
						|
        self.PostfixNotation = []
 | 
						|
        self.OpcodeList = []
 | 
						|
 | 
						|
        self.GetPostfixNotation()
 | 
						|
        self.ValidateOpcode()
 | 
						|
 | 
						|
        EdkLogger.debug(EdkLogger.DEBUG_8, repr(self))
 | 
						|
        if Optimize:
 | 
						|
            self.Optimize()
 | 
						|
            EdkLogger.debug(EdkLogger.DEBUG_8, "\n    Optimized: " + repr(self))
 | 
						|
 | 
						|
    def __str__(self):
 | 
						|
        return " ".join(self.TokenList)
 | 
						|
 | 
						|
    def __repr__(self):
 | 
						|
        WellForm = ''
 | 
						|
        for Token in self.PostfixNotation:
 | 
						|
            if Token in self.SupportedOpcode:
 | 
						|
                WellForm += "\n    " + Token
 | 
						|
            else:
 | 
						|
                WellForm += ' ' + Token
 | 
						|
        return WellForm
 | 
						|
 | 
						|
    ## Split the expression string into token list
 | 
						|
    def GetExpressionTokenList(self):
 | 
						|
        self.TokenList = self.TokenPattern.findall(self.ExpressionString)
 | 
						|
 | 
						|
    ## Convert token list into postfix notation
 | 
						|
    def GetPostfixNotation(self):
 | 
						|
        Stack = []
 | 
						|
        LastToken = ''
 | 
						|
        for Token in self.TokenList:
 | 
						|
            if Token == "(":
 | 
						|
                if LastToken not in self.SupportedOpcode + ['(', '', None]:
 | 
						|
                    EdkLogger.error("GenDepex", PARSER_ERROR, "Invalid dependency expression: missing operator before open parentheses",
 | 
						|
                                    ExtraData="Near %s" % LastToken)
 | 
						|
                Stack.append(Token)
 | 
						|
            elif Token == ")":
 | 
						|
                if '(' not in Stack:
 | 
						|
                    EdkLogger.error("GenDepex", PARSER_ERROR, "Invalid dependency expression: mismatched parentheses",
 | 
						|
                                    ExtraData=str(self))
 | 
						|
                elif LastToken in self.SupportedOpcode + ['', None]:
 | 
						|
                    EdkLogger.error("GenDepex", PARSER_ERROR, "Invalid dependency expression: missing operand before close parentheses",
 | 
						|
                                    ExtraData="Near %s" % LastToken)
 | 
						|
                while len(Stack) > 0:
 | 
						|
                    if Stack[-1] == '(':
 | 
						|
                        Stack.pop()
 | 
						|
                        break
 | 
						|
                    self.PostfixNotation.append(Stack.pop())
 | 
						|
            elif Token in self.OpcodePriority:
 | 
						|
                if Token == DEPEX_OPCODE_NOT:
 | 
						|
                    if LastToken not in self.SupportedOpcode + ['(', '', None]:
 | 
						|
                        EdkLogger.error("GenDepex", PARSER_ERROR, "Invalid dependency expression: missing operator before NOT",
 | 
						|
                                        ExtraData="Near %s" % LastToken)
 | 
						|
                elif LastToken in self.SupportedOpcode + ['(', '', None]:
 | 
						|
                        EdkLogger.error("GenDepex", PARSER_ERROR, "Invalid dependency expression: missing operand before " + Token,
 | 
						|
                                        ExtraData="Near %s" % LastToken)
 | 
						|
 | 
						|
                while len(Stack) > 0:
 | 
						|
                    if Stack[-1] == "(" or self.OpcodePriority[Token] >= self.OpcodePriority[Stack[-1]]:
 | 
						|
                        break
 | 
						|
                    self.PostfixNotation.append(Stack.pop())
 | 
						|
                Stack.append(Token)
 | 
						|
                self.OpcodeList.append(Token)
 | 
						|
            else:
 | 
						|
                if Token not in self.SupportedOpcode:
 | 
						|
                    # not OP, take it as GUID
 | 
						|
                    if LastToken not in self.SupportedOpcode + ['(', '', None]:
 | 
						|
                        EdkLogger.error("GenDepex", PARSER_ERROR, "Invalid dependency expression: missing operator before %s" % Token,
 | 
						|
                                        ExtraData="Near %s" % LastToken)
 | 
						|
                    if len(self.OpcodeList) == 0 or self.OpcodeList[-1] not in self.ExclusiveOpcode:
 | 
						|
                        if Token not in self.SupportedOperand:
 | 
						|
                            self.PostfixNotation.append(DEPEX_OPCODE_PUSH)
 | 
						|
                # check if OP is valid in this phase
 | 
						|
                elif Token in self.Opcode[self.Phase]:
 | 
						|
                    if Token == DEPEX_OPCODE_END:
 | 
						|
                        break
 | 
						|
                    self.OpcodeList.append(Token)
 | 
						|
                else:
 | 
						|
                    EdkLogger.error("GenDepex", PARSER_ERROR,
 | 
						|
                                    "Opcode=%s doesn't supported in %s stage " % (Token, self.Phase),
 | 
						|
                                    ExtraData=str(self))
 | 
						|
                self.PostfixNotation.append(Token)
 | 
						|
            LastToken = Token
 | 
						|
 | 
						|
        # there should not be parentheses in Stack
 | 
						|
        if '(' in Stack or ')' in Stack:
 | 
						|
            EdkLogger.error("GenDepex", PARSER_ERROR, "Invalid dependency expression: mismatched parentheses",
 | 
						|
                            ExtraData=str(self))
 | 
						|
        while len(Stack) > 0:
 | 
						|
            self.PostfixNotation.append(Stack.pop())
 | 
						|
        if self.PostfixNotation[-1] != DEPEX_OPCODE_END:
 | 
						|
            self.PostfixNotation.append(DEPEX_OPCODE_END)
 | 
						|
 | 
						|
    ## Validate the dependency expression
 | 
						|
    def ValidateOpcode(self):
 | 
						|
        for Op in self.AboveAllOpcode:
 | 
						|
            if Op in self.PostfixNotation:
 | 
						|
                if Op != self.PostfixNotation[0]:
 | 
						|
                    EdkLogger.error("GenDepex", PARSER_ERROR, "%s should be the first opcode in the expression" % Op,
 | 
						|
                                    ExtraData=str(self))
 | 
						|
                if len(self.PostfixNotation) < 3:
 | 
						|
                    EdkLogger.error("GenDepex", PARSER_ERROR, "Missing operand for %s" % Op,
 | 
						|
                                    ExtraData=str(self))
 | 
						|
        for Op in self.ExclusiveOpcode:
 | 
						|
            if Op in self.OpcodeList:
 | 
						|
                if len(self.OpcodeList) > 1:
 | 
						|
                    EdkLogger.error("GenDepex", PARSER_ERROR, "%s should be the only opcode in the expression" % Op,
 | 
						|
                                    ExtraData=str(self))
 | 
						|
                if len(self.PostfixNotation) < 3:
 | 
						|
                    EdkLogger.error("GenDepex", PARSER_ERROR, "Missing operand for %s" % Op,
 | 
						|
                                    ExtraData=str(self))
 | 
						|
        if self.TokenList[-1] != DEPEX_OPCODE_END and self.TokenList[-1] in self.NonEndingOpcode:
 | 
						|
            EdkLogger.error("GenDepex", PARSER_ERROR, "Extra %s at the end of the dependency expression" % self.TokenList[-1],
 | 
						|
                            ExtraData=str(self))
 | 
						|
        if self.TokenList[-1] == DEPEX_OPCODE_END and self.TokenList[-2] in self.NonEndingOpcode:
 | 
						|
            EdkLogger.error("GenDepex", PARSER_ERROR, "Extra %s at the end of the dependency expression" % self.TokenList[-2],
 | 
						|
                            ExtraData=str(self))
 | 
						|
        if DEPEX_OPCODE_END in self.TokenList and DEPEX_OPCODE_END != self.TokenList[-1]:
 | 
						|
            EdkLogger.error("GenDepex", PARSER_ERROR, "Extra expressions after END",
 | 
						|
                            ExtraData=str(self))
 | 
						|
 | 
						|
    ## Simply optimize the dependency expression by removing duplicated operands
 | 
						|
    def Optimize(self):
 | 
						|
        OpcodeSet = set(self.OpcodeList)
 | 
						|
        # if there are isn't one in the set, return
 | 
						|
        if len(OpcodeSet) != 1:
 | 
						|
          return
 | 
						|
        Op = OpcodeSet.pop()
 | 
						|
        #if Op isn't either OR or AND, return
 | 
						|
        if Op not in [DEPEX_OPCODE_AND, DEPEX_OPCODE_OR]:
 | 
						|
            return
 | 
						|
        NewOperand = []
 | 
						|
        AllOperand = set()
 | 
						|
        for Token in self.PostfixNotation:
 | 
						|
            if Token in self.SupportedOpcode or Token in NewOperand:
 | 
						|
                continue
 | 
						|
            AllOperand.add(Token)
 | 
						|
            if Token == DEPEX_OPCODE_TRUE:
 | 
						|
                if Op == DEPEX_OPCODE_AND:
 | 
						|
                    continue
 | 
						|
                else:
 | 
						|
                    NewOperand.append(Token)
 | 
						|
                    break
 | 
						|
            elif Token == DEPEX_OPCODE_FALSE:
 | 
						|
                if Op == DEPEX_OPCODE_OR:
 | 
						|
                    continue
 | 
						|
                else:
 | 
						|
                    NewOperand.append(Token)
 | 
						|
                    break
 | 
						|
            NewOperand.append(Token)
 | 
						|
 | 
						|
        # don't generate depex if only TRUE operand left
 | 
						|
        if self.ModuleType == SUP_MODULE_PEIM and len(NewOperand) == 1 and NewOperand[0] == DEPEX_OPCODE_TRUE:
 | 
						|
            self.PostfixNotation = []
 | 
						|
            return
 | 
						|
 | 
						|
        # don't generate depex if all operands are architecture protocols
 | 
						|
        if self.ModuleType in [SUP_MODULE_UEFI_DRIVER, SUP_MODULE_DXE_DRIVER, SUP_MODULE_DXE_RUNTIME_DRIVER, SUP_MODULE_DXE_SAL_DRIVER, SUP_MODULE_DXE_SMM_DRIVER, SUP_MODULE_MM_STANDALONE] and \
 | 
						|
           Op == DEPEX_OPCODE_AND and \
 | 
						|
           self.ArchProtocols == set(GuidStructureStringToGuidString(Guid) for Guid in AllOperand):
 | 
						|
            self.PostfixNotation = []
 | 
						|
            return
 | 
						|
 | 
						|
        if len(NewOperand) == 0:
 | 
						|
            self.TokenList = list(AllOperand)
 | 
						|
        else:
 | 
						|
            self.TokenList = []
 | 
						|
            while True:
 | 
						|
                self.TokenList.append(NewOperand.pop(0))
 | 
						|
                if NewOperand == []:
 | 
						|
                    break
 | 
						|
                self.TokenList.append(Op)
 | 
						|
        self.PostfixNotation = []
 | 
						|
        self.GetPostfixNotation()
 | 
						|
 | 
						|
 | 
						|
    ## Convert a GUID value in C structure format into its binary form
 | 
						|
    #
 | 
						|
    #   @param  Guid    The GUID value in C structure format
 | 
						|
    #
 | 
						|
    #   @retval array   The byte array representing the GUID value
 | 
						|
    #
 | 
						|
    def GetGuidValue(self, Guid):
 | 
						|
        GuidValueString = Guid.replace("{", "").replace("}", "").replace(" ", "")
 | 
						|
        GuidValueList = GuidValueString.split(",")
 | 
						|
        if len(GuidValueList) != 11 and len(GuidValueList) == 16:
 | 
						|
            GuidValueString = GuidStringToGuidStructureString(GuidStructureByteArrayToGuidString(Guid))
 | 
						|
            GuidValueString = GuidValueString.replace("{", "").replace("}", "").replace(" ", "")
 | 
						|
            GuidValueList = GuidValueString.split(",")
 | 
						|
        if len(GuidValueList) != 11:
 | 
						|
            EdkLogger.error("GenDepex", PARSER_ERROR, "Invalid GUID value string or opcode: %s" % Guid)
 | 
						|
        return pack("1I2H8B", *(int(value, 16) for value in GuidValueList))
 | 
						|
 | 
						|
    ## Save the binary form of dependency expression in file
 | 
						|
    #
 | 
						|
    #   @param  File    The path of file. If None is given, put the data on console
 | 
						|
    #
 | 
						|
    #   @retval True    If the file doesn't exist or file is changed
 | 
						|
    #   @retval False   If file exists and is not changed.
 | 
						|
    #
 | 
						|
    def Generate(self, File=None):
 | 
						|
        Buffer = BytesIO()
 | 
						|
        if len(self.PostfixNotation) == 0:
 | 
						|
            return False
 | 
						|
 | 
						|
        for Item in self.PostfixNotation:
 | 
						|
            if Item in self.Opcode[self.Phase]:
 | 
						|
                Buffer.write(pack("B", self.Opcode[self.Phase][Item]))
 | 
						|
            elif Item in self.SupportedOpcode:
 | 
						|
                EdkLogger.error("GenDepex", FORMAT_INVALID,
 | 
						|
                                "Opcode [%s] is not expected in %s phase" % (Item, self.Phase),
 | 
						|
                                ExtraData=self.ExpressionString)
 | 
						|
            else:
 | 
						|
                Buffer.write(self.GetGuidValue(Item))
 | 
						|
 | 
						|
        FilePath = ""
 | 
						|
        FileChangeFlag = True
 | 
						|
        if File is None:
 | 
						|
            sys.stdout.write(Buffer.getvalue())
 | 
						|
            FilePath = "STDOUT"
 | 
						|
        else:
 | 
						|
            FileChangeFlag = SaveFileOnChange(File, Buffer.getvalue(), True)
 | 
						|
 | 
						|
        Buffer.close()
 | 
						|
        return FileChangeFlag
 | 
						|
 | 
						|
versionNumber = ("0.04" + " " + gBUILD_VERSION)
 | 
						|
__version__ = "%prog Version " + versionNumber
 | 
						|
__copyright__ = "Copyright (c) 2007-2018, Intel Corporation  All rights reserved."
 | 
						|
__usage__ = "%prog [options] [dependency_expression_file]"
 | 
						|
 | 
						|
## Parse command line options
 | 
						|
#
 | 
						|
#   @retval OptionParser
 | 
						|
#
 | 
						|
def GetOptions():
 | 
						|
    from optparse import OptionParser
 | 
						|
 | 
						|
    Parser = OptionParser(description=__copyright__, version=__version__, usage=__usage__)
 | 
						|
 | 
						|
    Parser.add_option("-o", "--output", dest="OutputFile", default=None, metavar="FILE",
 | 
						|
                      help="Specify the name of depex file to be generated")
 | 
						|
    Parser.add_option("-t", "--module-type", dest="ModuleType", default=None,
 | 
						|
                      help="The type of module for which the dependency expression serves")
 | 
						|
    Parser.add_option("-e", "--dependency-expression", dest="Expression", default="",
 | 
						|
                      help="The string of dependency expression. If this option presents, the input file will be ignored.")
 | 
						|
    Parser.add_option("-m", "--optimize", dest="Optimize", default=False, action="store_true",
 | 
						|
                      help="Do some simple optimization on the expression.")
 | 
						|
    Parser.add_option("-v", "--verbose", dest="verbose", default=False, action="store_true",
 | 
						|
                      help="build with verbose information")
 | 
						|
    Parser.add_option("-d", "--debug", action="store", type="int", help="Enable debug messages at specified level.")
 | 
						|
    Parser.add_option("-q", "--quiet", dest="quiet", default=False, action="store_true",
 | 
						|
                      help="build with little information")
 | 
						|
 | 
						|
    return Parser.parse_args()
 | 
						|
 | 
						|
 | 
						|
## Entrance method
 | 
						|
#
 | 
						|
# @retval 0     Tool was successful
 | 
						|
# @retval 1     Tool failed
 | 
						|
#
 | 
						|
def Main():
 | 
						|
    EdkLogger.Initialize()
 | 
						|
    Option, Input = GetOptions()
 | 
						|
 | 
						|
    # Set log level
 | 
						|
    if Option.quiet:
 | 
						|
        EdkLogger.SetLevel(EdkLogger.QUIET)
 | 
						|
    elif Option.verbose:
 | 
						|
        EdkLogger.SetLevel(EdkLogger.VERBOSE)
 | 
						|
    elif Option.debug is not None:
 | 
						|
        EdkLogger.SetLevel(Option.debug + 1)
 | 
						|
    else:
 | 
						|
        EdkLogger.SetLevel(EdkLogger.INFO)
 | 
						|
 | 
						|
    try:
 | 
						|
        if Option.ModuleType is None or Option.ModuleType not in gType2Phase:
 | 
						|
            EdkLogger.error("GenDepex", OPTION_MISSING, "Module type is not specified or supported")
 | 
						|
 | 
						|
        DxsFile = ''
 | 
						|
        if len(Input) > 0 and Option.Expression == "":
 | 
						|
            DxsFile = Input[0]
 | 
						|
            DxsString = open(DxsFile, 'r').read().replace("\n", " ").replace("\r", " ")
 | 
						|
            DxsString = gStartClosePattern.sub("\\1", DxsString)
 | 
						|
        elif Option.Expression != "":
 | 
						|
            if Option.Expression[0] == '"':
 | 
						|
                DxsString = Option.Expression[1:-1]
 | 
						|
            else:
 | 
						|
                DxsString = Option.Expression
 | 
						|
        else:
 | 
						|
            EdkLogger.error("GenDepex", OPTION_MISSING, "No expression string or file given")
 | 
						|
 | 
						|
        Dpx = DependencyExpression(DxsString, Option.ModuleType, Option.Optimize)
 | 
						|
        if Option.OutputFile is not None:
 | 
						|
            FileChangeFlag = Dpx.Generate(Option.OutputFile)
 | 
						|
            if not FileChangeFlag and DxsFile:
 | 
						|
                #
 | 
						|
                # Touch the output file if its time stamp is older than the original
 | 
						|
                # DXS file to avoid re-invoke this tool for the dependency check in build rule.
 | 
						|
                #
 | 
						|
                if os.stat(DxsFile)[8] > os.stat(Option.OutputFile)[8]:
 | 
						|
                    os.utime(Option.OutputFile, None)
 | 
						|
        else:
 | 
						|
            Dpx.Generate()
 | 
						|
    except BaseException as X:
 | 
						|
        EdkLogger.quiet("")
 | 
						|
        if Option is not None and Option.debug is not None:
 | 
						|
            EdkLogger.quiet(traceback.format_exc())
 | 
						|
        else:
 | 
						|
            EdkLogger.quiet(str(X))
 | 
						|
        return 1
 | 
						|
 | 
						|
    return 0
 | 
						|
 | 
						|
if __name__ == '__main__':
 | 
						|
    sys.exit(Main())
 | 
						|
 |