]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/Python/AutoGen/GenDepex.py
BaseTools: enable FixedAtBuild (VOID*) PCD use in the [DEPEX] section
[mirror_edk2.git] / BaseTools / Source / Python / AutoGen / GenDepex.py
index 9ee615cdc800fa489def0c9853b8c12713d32818..c12b6139e105ec32fe56c73af750e264448dd877 100644 (file)
@@ -1,8 +1,8 @@
 ## @file\r
 # This file is used to generate DEPEX file for module's dependency expression\r
 #\r
-# Copyright (c) 2007, Intel Corporation\r
-# All rights reserved. This program and the accompanying materials\r
+# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>\r
+# This program and the accompanying materials\r
 # are licensed and made available under the terms and conditions of the BSD License\r
 # which accompanies this distribution.    The full text of the license may be found at\r
 # http://opensource.org/licenses/bsd-license.php\r
 ## Import Modules\r
 #\r
 import sys\r
-import os\r
+import Common.LongFilePathOs as os\r
 import re\r
 import traceback\r
-\r
-from StringIO import StringIO\r
+from Common.LongFilePathSupport import OpenLongFilePath as open\r
+from io import BytesIO\r
 from struct import pack\r
 from Common.BuildToolError import *\r
 from Common.Misc import SaveFileOnChange\r
 from Common.Misc import GuidStructureStringToGuidString\r
+from Common.Misc import GuidStructureByteArrayToGuidString\r
+from Common.Misc import GuidStringToGuidStructureString\r
 from Common import EdkLogger as EdkLogger\r
-\r
+from Common.BuildVersion import gBUILD_VERSION\r
+from Common.DataType import *\r
 \r
 ## Regular expression for matching "DEPENDENCY_START ... DEPENDENCY_END"\r
 gStartClosePattern = re.compile(".*DEPENDENCY_START(.+)DEPENDENCY_END.*", re.S)\r
 \r
 ## Mapping between module type and EFI phase\r
 gType2Phase = {\r
-    "BASE"              :   None,\r
-    "SEC"               :   "PEI",\r
-    "PEI_CORE"          :   "PEI",\r
-    "PEIM"              :   "PEI",\r
-    "DXE_CORE"          :   "DXE",\r
-    "DXE_DRIVER"        :   "DXE",\r
-    "DXE_SMM_DRIVER"    :   "DXE",\r
-    "DXE_RUNTIME_DRIVER":   "DXE",\r
-    "DXE_SAL_DRIVER"    :   "DXE",\r
-    "UEFI_DRIVER"       :   "DXE",\r
-    "UEFI_APPLICATION"  :   "DXE",\r
-    "SMM_CORE"          :   "DXE",\r
+    SUP_MODULE_BASE              :   None,\r
+    SUP_MODULE_SEC               :   "PEI",\r
+    SUP_MODULE_PEI_CORE          :   "PEI",\r
+    SUP_MODULE_PEIM              :   "PEI",\r
+    SUP_MODULE_DXE_CORE          :   "DXE",\r
+    SUP_MODULE_DXE_DRIVER        :   "DXE",\r
+    SUP_MODULE_DXE_SMM_DRIVER    :   "DXE",\r
+    SUP_MODULE_DXE_RUNTIME_DRIVER:   "DXE",\r
+    SUP_MODULE_DXE_SAL_DRIVER    :   "DXE",\r
+    SUP_MODULE_UEFI_DRIVER       :   "DXE",\r
+    SUP_MODULE_UEFI_APPLICATION  :   "DXE",\r
+    SUP_MODULE_SMM_CORE          :   "DXE",\r
+    SUP_MODULE_MM_STANDALONE     :   "MM",\r
+    SUP_MODULE_MM_CORE_STANDALONE :  "MM",\r
 }\r
 \r
 ## Convert dependency expression string into EFI internal representation\r
@@ -51,7 +56,7 @@ gType2Phase = {
 #\r
 class DependencyExpression:\r
 \r
-    ArchProtocols = set([\r
+    ArchProtocols = {\r
                         '665e3ff6-46cc-11d4-9a38-0090273fc14d',     #   'gEfiBdsArchProtocolGuid'\r
                         '26baccb1-6f42-11d4-bce7-0080c73c8881',     #   'gEfiCpuArchProtocolGuid'\r
                         '26baccb2-6f42-11d4-bce7-0080c73c8881',     #   'gEfiMetronomeArchProtocolGuid'\r
@@ -64,56 +69,65 @@ class DependencyExpression:
                         '6441f818-6362-4e44-b570-7dba31dd2453',     #   'gEfiVariableWriteArchProtocolGuid'\r
                         '1e5668e2-8481-11d4-bcf1-0080c73c8881',     #   'gEfiVariableArchProtocolGuid'\r
                         '665e3ff5-46cc-11d4-9a38-0090273fc14d'      #   'gEfiWatchdogTimerArchProtocolGuid'\r
-                        ]\r
-                    )\r
+                    }\r
 \r
     OpcodePriority = {\r
-        "AND"   :   1,\r
-        "OR"    :   1,\r
-        "NOT"   :   2,\r
-        # "SOR"   :   9,\r
-        # "BEFORE":   9,\r
-        # "AFTER" :   9,\r
+        DEPEX_OPCODE_AND   :   1,\r
+        DEPEX_OPCODE_OR    :   1,\r
+        DEPEX_OPCODE_NOT   :   2,\r
     }\r
 \r
     Opcode = {\r
         "PEI"   : {\r
-            "PUSH"  :   0x02,\r
-            "AND"   :   0x03,\r
-            "OR"    :   0x04,\r
-            "NOT"   :   0x05,\r
-            "TRUE"  :   0x06,\r
-            "FALSE" :   0x07,\r
-            "END"   :   0x08\r
+            DEPEX_OPCODE_PUSH  :   0x02,\r
+            DEPEX_OPCODE_AND   :   0x03,\r
+            DEPEX_OPCODE_OR    :   0x04,\r
+            DEPEX_OPCODE_NOT   :   0x05,\r
+            DEPEX_OPCODE_TRUE  :   0x06,\r
+            DEPEX_OPCODE_FALSE :   0x07,\r
+            DEPEX_OPCODE_END   :   0x08\r
         },\r
 \r
         "DXE"   : {\r
-            "BEFORE":   0x00,\r
-            "AFTER" :   0x01,\r
-            "PUSH"  :   0x02,\r
-            "AND"   :   0x03,\r
-            "OR"    :   0x04,\r
-            "NOT"   :   0x05,\r
-            "TRUE"  :   0x06,\r
-            "FALSE" :   0x07,\r
-            "END"   :   0x08,\r
-            "SOR"   :   0x09\r
+            DEPEX_OPCODE_BEFORE:   0x00,\r
+            DEPEX_OPCODE_AFTER :   0x01,\r
+            DEPEX_OPCODE_PUSH  :   0x02,\r
+            DEPEX_OPCODE_AND   :   0x03,\r
+            DEPEX_OPCODE_OR    :   0x04,\r
+            DEPEX_OPCODE_NOT   :   0x05,\r
+            DEPEX_OPCODE_TRUE  :   0x06,\r
+            DEPEX_OPCODE_FALSE :   0x07,\r
+            DEPEX_OPCODE_END   :   0x08,\r
+            DEPEX_OPCODE_SOR   :   0x09\r
+        },\r
+\r
+        "MM"   : {\r
+            DEPEX_OPCODE_BEFORE:   0x00,\r
+            DEPEX_OPCODE_AFTER :   0x01,\r
+            DEPEX_OPCODE_PUSH  :   0x02,\r
+            DEPEX_OPCODE_AND   :   0x03,\r
+            DEPEX_OPCODE_OR    :   0x04,\r
+            DEPEX_OPCODE_NOT   :   0x05,\r
+            DEPEX_OPCODE_TRUE  :   0x06,\r
+            DEPEX_OPCODE_FALSE :   0x07,\r
+            DEPEX_OPCODE_END   :   0x08,\r
+            DEPEX_OPCODE_SOR   :   0x09\r
         }\r
     }\r
 \r
     # all supported op codes and operands\r
-    SupportedOpcode = ["BEFORE", "AFTER", "PUSH", "AND", "OR", "NOT", "END", "SOR"]\r
-    SupportedOperand = ["TRUE", "FALSE"]\r
+    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]\r
+    SupportedOperand = [DEPEX_OPCODE_TRUE, DEPEX_OPCODE_FALSE]\r
 \r
-    OpcodeWithSingleOperand = ['NOT', 'BEFORE', 'AFTER']\r
-    OpcodeWithTwoOperand = ['AND', 'OR']\r
+    OpcodeWithSingleOperand = [DEPEX_OPCODE_NOT, DEPEX_OPCODE_BEFORE, DEPEX_OPCODE_AFTER]\r
+    OpcodeWithTwoOperand = [DEPEX_OPCODE_AND, DEPEX_OPCODE_OR]\r
 \r
     # op code that should not be the last one\r
-    NonEndingOpcode = ["AND", "OR", "NOT", 'SOR']\r
+    NonEndingOpcode = [DEPEX_OPCODE_AND, DEPEX_OPCODE_OR, DEPEX_OPCODE_NOT, DEPEX_OPCODE_SOR]\r
     # op code must not present at the same time\r
-    ExclusiveOpcode = ["BEFORE", "AFTER"]\r
+    ExclusiveOpcode = [DEPEX_OPCODE_BEFORE, DEPEX_OPCODE_AFTER]\r
     # op code that should be the first one if it presents\r
-    AboveAllOpcode = ["SOR", "BEFORE", "AFTER"]\r
+    AboveAllOpcode = [DEPEX_OPCODE_SOR, DEPEX_OPCODE_BEFORE, DEPEX_OPCODE_AFTER]\r
 \r
     #\r
     # open and close brace must be taken as individual tokens\r
@@ -128,7 +142,7 @@ class DependencyExpression:
     def __init__(self, Expression, ModuleType, Optimize=False):\r
         self.ModuleType = ModuleType\r
         self.Phase = gType2Phase[ModuleType]\r
-        if type(Expression) == type([]):\r
+        if isinstance(Expression, type([])):\r
             self.ExpressionString = " ".join(Expression)\r
             self.TokenList = Expression\r
         else:\r
@@ -185,7 +199,7 @@ class DependencyExpression:
                         break\r
                     self.PostfixNotation.append(Stack.pop())\r
             elif Token in self.OpcodePriority:\r
-                if Token == "NOT":\r
+                if Token == DEPEX_OPCODE_NOT:\r
                     if LastToken not in self.SupportedOpcode + ['(', '', None]:\r
                         EdkLogger.error("GenDepex", PARSER_ERROR, "Invalid dependency expression: missing operator before NOT",\r
                                         ExtraData="Near %s" % LastToken)\r
@@ -207,10 +221,10 @@ class DependencyExpression:
                                         ExtraData="Near %s" % LastToken)\r
                     if len(self.OpcodeList) == 0 or self.OpcodeList[-1] not in self.ExclusiveOpcode:\r
                         if Token not in self.SupportedOperand:\r
-                            self.PostfixNotation.append("PUSH")\r
+                            self.PostfixNotation.append(DEPEX_OPCODE_PUSH)\r
                 # check if OP is valid in this phase\r
                 elif Token in self.Opcode[self.Phase]:\r
-                    if Token == "END":\r
+                    if Token == DEPEX_OPCODE_END:\r
                         break\r
                     self.OpcodeList.append(Token)\r
                 else:\r
@@ -226,8 +240,8 @@ class DependencyExpression:
                             ExtraData=str(self))\r
         while len(Stack) > 0:\r
             self.PostfixNotation.append(Stack.pop())\r
-        if self.PostfixNotation[-1] != 'END':\r
-            self.PostfixNotation.append("END")\r
+        if self.PostfixNotation[-1] != DEPEX_OPCODE_END:\r
+            self.PostfixNotation.append(DEPEX_OPCODE_END)\r
 \r
     ## Validate the dependency expression\r
     def ValidateOpcode(self):\r
@@ -247,36 +261,40 @@ class DependencyExpression:
                 if len(self.PostfixNotation) < 3:\r
                     EdkLogger.error("GenDepex", PARSER_ERROR, "Missing operand for %s" % Op,\r
                                     ExtraData=str(self))\r
-        if self.TokenList[-1] != 'END' and self.TokenList[-1] in self.NonEndingOpcode:\r
+        if self.TokenList[-1] != DEPEX_OPCODE_END and self.TokenList[-1] in self.NonEndingOpcode:\r
             EdkLogger.error("GenDepex", PARSER_ERROR, "Extra %s at the end of the dependency expression" % self.TokenList[-1],\r
                             ExtraData=str(self))\r
-        if self.TokenList[-1] == 'END' and self.TokenList[-2] in self.NonEndingOpcode:\r
+        if self.TokenList[-1] == DEPEX_OPCODE_END and self.TokenList[-2] in self.NonEndingOpcode:\r
             EdkLogger.error("GenDepex", PARSER_ERROR, "Extra %s at the end of the dependency expression" % self.TokenList[-2],\r
                             ExtraData=str(self))\r
-        if "END" in self.TokenList and "END" != self.TokenList[-1]:\r
+        if DEPEX_OPCODE_END in self.TokenList and DEPEX_OPCODE_END != self.TokenList[-1]:\r
             EdkLogger.error("GenDepex", PARSER_ERROR, "Extra expressions after END",\r
                             ExtraData=str(self))\r
 \r
     ## Simply optimize the dependency expression by removing duplicated operands\r
     def Optimize(self):\r
-        ValidOpcode = list(set(self.OpcodeList))\r
-        if len(ValidOpcode) != 1 or ValidOpcode[0] not in ['AND', 'OR']:\r
+        OpcodeSet = set(self.OpcodeList)\r
+        # if there are isn't one in the set, return\r
+        if len(OpcodeSet) != 1:\r
+          return\r
+        Op = OpcodeSet.pop()\r
+        #if Op isn't either OR or AND, return\r
+        if Op not in [DEPEX_OPCODE_AND, DEPEX_OPCODE_OR]:\r
             return\r
-        Op = ValidOpcode[0]\r
         NewOperand = []\r
         AllOperand = set()\r
         for Token in self.PostfixNotation:\r
             if Token in self.SupportedOpcode or Token in NewOperand:\r
                 continue\r
             AllOperand.add(Token)\r
-            if Token == 'TRUE':\r
-                if Op == 'AND':\r
+            if Token == DEPEX_OPCODE_TRUE:\r
+                if Op == DEPEX_OPCODE_AND:\r
                     continue\r
                 else:\r
                     NewOperand.append(Token)\r
                     break\r
-            elif Token == 'FALSE':\r
-                if Op == 'OR':\r
+            elif Token == DEPEX_OPCODE_FALSE:\r
+                if Op == DEPEX_OPCODE_OR:\r
                     continue\r
                 else:\r
                     NewOperand.append(Token)\r
@@ -284,14 +302,14 @@ class DependencyExpression:
             NewOperand.append(Token)\r
 \r
         # don't generate depex if only TRUE operand left\r
-        if self.ModuleType == 'PEIM' and len(NewOperand) == 1 and NewOperand[0] == 'TRUE':\r
+        if self.ModuleType == SUP_MODULE_PEIM and len(NewOperand) == 1 and NewOperand[0] == DEPEX_OPCODE_TRUE:\r
             self.PostfixNotation = []\r
-            return            \r
+            return\r
 \r
         # don't generate depex if all operands are architecture protocols\r
-        if self.ModuleType in ['UEFI_DRIVER', 'DXE_DRIVER', 'DXE_RUNTIME_DRIVER', 'DXE_SAL_DRIVER', 'DXE_SMM_DRIVER'] and \\r
-           Op == 'AND' and \\r
-           self.ArchProtocols == set([GuidStructureStringToGuidString(Guid) for Guid in AllOperand]):\r
+        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 \\r
+           Op == DEPEX_OPCODE_AND and \\r
+           self.ArchProtocols == set(GuidStructureStringToGuidString(Guid) for Guid in AllOperand):\r
             self.PostfixNotation = []\r
             return\r
 \r
@@ -317,6 +335,10 @@ class DependencyExpression:
     def GetGuidValue(self, Guid):\r
         GuidValueString = Guid.replace("{", "").replace("}", "").replace(" ", "")\r
         GuidValueList = GuidValueString.split(",")\r
+        if len(GuidValueList) != 11 and len(GuidValueList) == 16:\r
+            GuidValueString = GuidStringToGuidStructureString(GuidStructureByteArrayToGuidString(Guid))\r
+            GuidValueString = GuidValueString.replace("{", "").replace("}", "").replace(" ", "")\r
+            GuidValueList = GuidValueString.split(",")\r
         if len(GuidValueList) != 11:\r
             EdkLogger.error("GenDepex", PARSER_ERROR, "Invalid GUID value string or opcode: %s" % Guid)\r
         return pack("1I2H8B", *(int(value, 16) for value in GuidValueList))\r
@@ -329,7 +351,7 @@ class DependencyExpression:
     #   @retval False   If file exists and is not changed.\r
     #\r
     def Generate(self, File=None):\r
-        Buffer = StringIO()\r
+        Buffer = BytesIO()\r
         if len(self.PostfixNotation) == 0:\r
             return False\r
 \r
@@ -345,7 +367,7 @@ class DependencyExpression:
 \r
         FilePath = ""\r
         FileChangeFlag = True\r
-        if File == None:\r
+        if File is None:\r
             sys.stdout.write(Buffer.getvalue())\r
             FilePath = "STDOUT"\r
         else:\r
@@ -354,9 +376,9 @@ class DependencyExpression:
         Buffer.close()\r
         return FileChangeFlag\r
 \r
-versionNumber = "0.04"\r
+versionNumber = ("0.04" + " " + gBUILD_VERSION)\r
 __version__ = "%prog Version " + versionNumber\r
-__copyright__ = "Copyright (c) 2007-2008, Intel Corporation  All rights reserved."\r
+__copyright__ = "Copyright (c) 2007-2018, Intel Corporation  All rights reserved."\r
 __usage__ = "%prog [options] [dependency_expression_file]"\r
 \r
 ## Parse command line options\r
@@ -399,13 +421,13 @@ def Main():
         EdkLogger.SetLevel(EdkLogger.QUIET)\r
     elif Option.verbose:\r
         EdkLogger.SetLevel(EdkLogger.VERBOSE)\r
-    elif Option.debug != None:\r
+    elif Option.debug is not None:\r
         EdkLogger.SetLevel(Option.debug + 1)\r
     else:\r
         EdkLogger.SetLevel(EdkLogger.INFO)\r
 \r
     try:\r
-        if Option.ModuleType == None or Option.ModuleType not in gType2Phase:\r
+        if Option.ModuleType is None or Option.ModuleType not in gType2Phase:\r
             EdkLogger.error("GenDepex", OPTION_MISSING, "Module type is not specified or supported")\r
 \r
         DxsFile = ''\r
@@ -422,13 +444,20 @@ def Main():
             EdkLogger.error("GenDepex", OPTION_MISSING, "No expression string or file given")\r
 \r
         Dpx = DependencyExpression(DxsString, Option.ModuleType, Option.Optimize)\r
-        if Option.OutputFile != None:\r
-            Dpx.Generate(Option.OutputFile)\r
+        if Option.OutputFile is not None:\r
+            FileChangeFlag = Dpx.Generate(Option.OutputFile)\r
+            if not FileChangeFlag and DxsFile:\r
+                #\r
+                # Touch the output file if its time stamp is older than the original\r
+                # DXS file to avoid re-invoke this tool for the dependency check in build rule.\r
+                #\r
+                if os.stat(DxsFile)[8] > os.stat(Option.OutputFile)[8]:\r
+                    os.utime(Option.OutputFile, None)\r
         else:\r
             Dpx.Generate()\r
-    except BaseException, X:\r
+    except BaseException as X:\r
         EdkLogger.quiet("")\r
-        if Option != None and Option.debug != None:\r
+        if Option is not None and Option.debug is not None:\r
             EdkLogger.quiet(traceback.format_exc())\r
         else:\r
             EdkLogger.quiet(str(X))\r