]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/Python/GenFds/FfsInfStatement.py
BaseTools/GenFds: register MM Modules and MM FV file types.
[mirror_edk2.git] / BaseTools / Source / Python / GenFds / FfsInfStatement.py
index a7a65919d7cd977d6f3c12f5769e01cb66f362e1..c61c227c99000df9926db44ada82b2c2e401e76c 100644 (file)
@@ -1,7 +1,8 @@
 ## @file\r
 # process FFS generation from INF statement\r
 #\r
-#  Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>\r
+#  Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR>\r
+#  Copyright (c) 2014-2016 Hewlett-Packard Development Company, L.P.<BR>\r
 #\r
 #  This program and the accompanying materials\r
 #  are licensed and made available under the terms and conditions of the BSD License\r
@@ -27,9 +28,12 @@ import Section
 import RuleSimpleFile\r
 import RuleComplexFile\r
 from CommonDataClass.FdfClass import FfsInfStatementClassObject\r
+from Common.MultipleWorkspace import MultipleWorkspace as mws\r
 from Common.String import *\r
 from Common.Misc import PathClass\r
 from Common.Misc import GuidStructureByteArrayToGuidString\r
+from Common.Misc import ProcessDuplicatedInf\r
+from Common.Misc import GetVariableOffset\r
 from Common import EdkLogger\r
 from Common.BuildToolError import *\r
 from GuidSection import GuidSection\r
@@ -39,6 +43,7 @@ from AutoGen.GenDepex import DependencyExpression
 from PatchPcdValue.PatchPcdValue import PatchBinaryFile\r
 from Common.LongFilePathSupport import CopyLongFilePath\r
 from Common.LongFilePathSupport import OpenLongFilePath as open\r
+import Common.GlobalData as GlobalData\r
 \r
 ## generate FFS from INF\r
 #\r
@@ -64,6 +69,9 @@ class FfsInfStatement(FfsInfStatementClassObject):
         self.CurrentLineContent = None\r
         self.FileName = None\r
         self.InfFileName = None\r
+        self.OverrideGuid = None\r
+        self.PatchedBinFile = ''\r
+        self.MacroDict = {}\r
 \r
     ## GetFinalTargetSuffixMap() method\r
     #\r
@@ -145,7 +153,9 @@ class FfsInfStatement(FfsInfStatementClassObject):
         GenFdsGlobalVariable.VerboseLogger( " Begine parsing INf file : %s" %self.InfFileName)\r
 \r
         self.InfFileName = self.InfFileName.replace('$(WORKSPACE)', '')\r
-        if self.InfFileName[0] == '\\' or self.InfFileName[0] == '/' :\r
+        if len(self.InfFileName) > 1 and self.InfFileName[0] == '\\' and self.InfFileName[1] == '\\':\r
+            pass\r
+        elif self.InfFileName[0] == '\\' or self.InfFileName[0] == '/' :\r
             self.InfFileName = self.InfFileName[1:]\r
 \r
         if self.InfFileName.find('$') == -1:\r
@@ -164,7 +174,13 @@ class FfsInfStatement(FfsInfStatementClassObject):
         ErrorCode, ErrorInfo = PathClassObj.Validate(".inf")\r
         if ErrorCode != 0:\r
             EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo)\r
-        \r
+\r
+        #\r
+        # Cache lower case version of INF path before processing FILE_GUID override\r
+        #\r
+        InfLowerPath = str(PathClassObj).lower()\r
+        if self.OverrideGuid:\r
+            PathClassObj = ProcessDuplicatedInf(PathClassObj, self.OverrideGuid, GenFdsGlobalVariable.WorkSpaceDir)\r
         if self.CurrentArch != None:\r
 \r
             Inf = GenFdsGlobalVariable.WorkSpace.BuildObject[PathClassObj, self.CurrentArch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]\r
@@ -199,12 +215,18 @@ class FfsInfStatement(FfsInfStatementClassObject):
                                 "INF %s specified in FDF could not be found in build ARCH %s!" \\r
                                 % (self.InfFileName, GenFdsGlobalVariable.ArchList))\r
 \r
+        if self.OverrideGuid:\r
+            self.ModuleGuid = self.OverrideGuid\r
+\r
         if len(self.SourceFileList) != 0 and not self.InDsc:\r
             EdkLogger.warn("GenFds", GENFDS_ERROR, "Module %s NOT found in DSC file; Is it really a binary module?" % (self.InfFileName))\r
 \r
         if self.ModuleType == 'SMM_CORE' and int(self.PiSpecVersion, 16) < 0x0001000A:\r
             EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "SMM_CORE module type can't be used in the module with PI_SPECIFICATION_VERSION less than 0x0001000A", File=self.InfFileName)      \r
 \r
+        if self.ModuleType == 'MM_CORE_STANDALONE' and int(self.PiSpecVersion, 16) < 0x00010032:\r
+            EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "MM_CORE_STANDALONE module type can't be used in the module with PI_SPECIFICATION_VERSION less than 0x00010032", File=self.InfFileName)\r
+\r
         if Inf._Defs != None and len(Inf._Defs) > 0:\r
             self.OptRomDefs.update(Inf._Defs)\r
 \r
@@ -227,7 +249,6 @@ class FfsInfStatement(FfsInfStatementClassObject):
                 continue\r
             # Override Patchable PCD value by the value from DSC\r
             PatchPcd = None\r
-            InfLowerPath = str(PathClassObj).lower()\r
             if InfLowerPath in DscModules and PcdKey in DscModules[InfLowerPath].Pcds:\r
                 PatchPcd = DscModules[InfLowerPath].Pcds[PcdKey]\r
             elif PcdKey in Platform.Pcds:\r
@@ -243,7 +264,16 @@ class FfsInfStatement(FfsInfStatementClassObject):
                 DefaultValue = FdfPcdDict[PcdKey]\r
                 FdfOverride = True\r
 \r
-            if not DscOverride and not FdfOverride:\r
+            # Override Patchable PCD value by the value from Build Option\r
+            BuildOptionOverride = False\r
+            if GlobalData.BuildOptionPcd:\r
+                for pcd in GlobalData.BuildOptionPcd:\r
+                    if PcdKey == (pcd[1], pcd[0]):\r
+                        DefaultValue = pcd[2]\r
+                        BuildOptionOverride = True\r
+                        break\r
+\r
+            if not DscOverride and not FdfOverride and not BuildOptionOverride:\r
                 continue\r
             # Check value, if value are equal, no need to patch\r
             if Pcd.DatumType == "VOID*":\r
@@ -285,8 +315,8 @@ class FfsInfStatement(FfsInfStatementClassObject):
                     or PcdValueInImg > FfsInfStatement._MAX_SIZE_TYPE[Pcd.DatumType]:\r
                     EdkLogger.error("GenFds", GENFDS_ERROR, "The size of %s type PCD '%s.%s' doesn't match its data type." \\r
                                     % (Pcd.DatumType, Pcd.TokenSpaceGuidCName, Pcd.TokenCName))\r
-            Pcd.DefaultValue = DefaultValue\r
-            self.PatchPcds.append(Pcd)\r
+            self.PatchPcds.append((Pcd, DefaultValue))\r
+\r
         self.InfModule = Inf\r
         self.PcdIsDriver = Inf.PcdIsDriver\r
         self.IsBinaryModule = Inf.IsBinaryModule\r
@@ -308,7 +338,7 @@ class FfsInfStatement(FfsInfStatementClassObject):
         self.EfiOutputPath = self.__GetEFIOutPutPath__()\r
         GenFdsGlobalVariable.VerboseLogger( "ModuelEFIPath: " + self.EfiOutputPath)\r
 \r
-## PatchEfiFile\r
+    ## PatchEfiFile\r
     #\r
     #  Patch EFI file with patch PCD\r
     #\r
@@ -316,19 +346,64 @@ class FfsInfStatement(FfsInfStatementClassObject):
     #  @retval: Full path of patched EFI file: self.OutputPath + EfiFile base name\r
     #           If passed in file does not end with efi, return as is\r
     #\r
-    def PatchEfiFile(self, EfiFile):\r
-        if os.path.splitext(EfiFile)[1].lower() != '.efi':\r
-            return EfiFile\r
+    def PatchEfiFile(self, EfiFile, FileType):\r
+        #\r
+        # If the module does not have any patches, then return path to input file\r
+        #  \r
         if not self.PatchPcds:\r
             return EfiFile\r
+\r
+        #\r
+        # Only patch file if FileType is PE32 or ModuleType is USER_DEFINED\r
+        #  \r
+        if FileType != 'PE32' and self.ModuleType != "USER_DEFINED":\r
+            return EfiFile\r
+\r
+        #\r
+        # Generate path to patched output file\r
+        #\r
         Basename = os.path.basename(EfiFile)\r
-        Output = os.path.join(self.OutputPath, Basename)\r
+        Output = os.path.normpath (os.path.join(self.OutputPath, Basename))\r
+\r
+        #\r
+        # If this file has already been patched, then return the path to the patched file\r
+        #\r
+        if self.PatchedBinFile == Output:\r
+          return Output\r
+\r
+        #\r
+        # If a different file from the same module has already been patched, then generate an error\r
+        #  \r
+        if self.PatchedBinFile:\r
+            EdkLogger.error("GenFds", GENFDS_ERROR,\r
+                            'Only one binary file can be patched:\n'\r
+                            '  a binary file has been patched: %s\n'\r
+                            '  current file: %s' % (self.PatchedBinFile, EfiFile),\r
+                            File=self.InfFileName)\r
+\r
+        #\r
+        # Copy unpatched file contents to output file location to perform patching\r
+        #  \r
         CopyLongFilePath(EfiFile, Output)\r
-        for Pcd in self.PatchPcds:\r
-            RetVal, RetStr = PatchBinaryFile(Output, int(Pcd.Offset, 0), Pcd.DatumType, Pcd.DefaultValue, Pcd.MaxDatumSize)\r
+\r
+        #\r
+        # Apply patches to patched output file\r
+        #  \r
+        for Pcd, Value in self.PatchPcds:\r
+            RetVal, RetStr = PatchBinaryFile(Output, int(Pcd.Offset, 0), Pcd.DatumType, Value, Pcd.MaxDatumSize)\r
             if RetVal:\r
                 EdkLogger.error("GenFds", GENFDS_ERROR, RetStr, File=self.InfFileName)\r
+\r
+        #\r
+        # Save the path of the patched output file\r
+        #  \r
+        self.PatchedBinFile = Output\r
+\r
+        #\r
+        # Return path to patched output file\r
+        #  \r
         return Output\r
+\r
     ## GenFfs() method\r
     #\r
     #   Generate FFS\r
@@ -345,11 +420,35 @@ class FfsInfStatement(FfsInfStatementClassObject):
         #\r
 \r
         self.__InfParse__(Dict)\r
+        SrcFile = mws.join( GenFdsGlobalVariable.WorkSpaceDir , self.InfFileName);\r
+        DestFile = os.path.join( self.OutputPath, self.ModuleGuid + '.ffs')\r
         \r
+        SrcFileDir = "."\r
+        SrcPath = os.path.dirname(SrcFile)\r
+        SrcFileName = os.path.basename(SrcFile)\r
+        SrcFileBase, SrcFileExt = os.path.splitext(SrcFileName)   \r
+        DestPath = os.path.dirname(DestFile)\r
+        DestFileName = os.path.basename(DestFile)\r
+        DestFileBase, DestFileExt = os.path.splitext(DestFileName)   \r
+        self.MacroDict = {\r
+            # source file\r
+            "${src}"      :   SrcFile,\r
+            "${s_path}"   :   SrcPath,\r
+            "${s_dir}"    :   SrcFileDir,\r
+            "${s_name}"   :   SrcFileName,\r
+            "${s_base}"   :   SrcFileBase,\r
+            "${s_ext}"    :   SrcFileExt,\r
+            # destination file\r
+            "${dst}"      :   DestFile,\r
+            "${d_path}"   :   DestPath,\r
+            "${d_name}"   :   DestFileName,\r
+            "${d_base}"   :   DestFileBase,\r
+            "${d_ext}"    :   DestFileExt\r
+        }\r
         #\r
         # Allow binary type module not specify override rule in FDF file.\r
         # \r
-        if len(self.BinFileList) >0 and not self.InDsc:\r
+        if len(self.BinFileList) > 0:\r
             if self.Rule == None or self.Rule == "":\r
                 self.Rule = "BINARY"\r
                 \r
@@ -403,6 +502,7 @@ class FfsInfStatement(FfsInfStatementClassObject):
             '$(NAMED_GUID)'  : self.ModuleGuid\r
         }\r
         String = GenFdsGlobalVariable.MacroExtend(String, MacroDict)\r
+        String = GenFdsGlobalVariable.MacroExtend(String, self.MacroDict)        \r
         return String\r
 \r
     ## __GetRule__() method\r
@@ -466,37 +566,23 @@ class FfsInfStatement(FfsInfStatementClassObject):
     #\r
     def __GetPlatformArchList__(self):\r
 \r
-        InfFileKey = os.path.normpath(os.path.join(GenFdsGlobalVariable.WorkSpaceDir, self.InfFileName))\r
+        InfFileKey = os.path.normpath(mws.join(GenFdsGlobalVariable.WorkSpaceDir, self.InfFileName))\r
         DscArchList = []\r
-        PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'IA32', GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]\r
-        if  PlatformDataBase != None:\r
-            if InfFileKey in PlatformDataBase.Modules:\r
-                DscArchList.append ('IA32')\r
-\r
-        PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'X64', GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]\r
-        if  PlatformDataBase != None:\r
-            if InfFileKey in PlatformDataBase.Modules:\r
-                DscArchList.append ('X64')\r
-\r
-        PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'IPF', GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]\r
-        if PlatformDataBase != None:\r
-            if InfFileKey in (PlatformDataBase.Modules):\r
-                DscArchList.append ('IPF')\r
-\r
-        PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'ARM', GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]\r
-        if PlatformDataBase != None:\r
-            if InfFileKey in (PlatformDataBase.Modules):\r
-                DscArchList.append ('ARM')\r
-\r
-        PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'EBC', GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]\r
-        if PlatformDataBase != None:\r
-            if InfFileKey in (PlatformDataBase.Modules):\r
-                DscArchList.append ('EBC')\r
-\r
-        PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'AARCH64', GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]\r
-        if PlatformDataBase != None:\r
-            if InfFileKey in (PlatformDataBase.Modules):\r
-                DscArchList.append ('AARCH64')\r
+        for Arch in GenFdsGlobalVariable.ArchList :\r
+            PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]\r
+            if  PlatformDataBase != None:\r
+                if InfFileKey in PlatformDataBase.Modules:\r
+                    DscArchList.append (Arch)\r
+                else:\r
+                    #\r
+                    # BaseTools support build same module more than once, the module path with FILE_GUID overridden has\r
+                    # the file name FILE_GUIDmodule.inf, then PlatformDataBase.Modules use FILE_GUIDmodule.inf as key,\r
+                    # but the path (self.MetaFile.Path) is the real path\r
+                    #\r
+                    for key in PlatformDataBase.Modules.keys():\r
+                        if InfFileKey == str((PlatformDataBase.Modules[key]).MetaFile.Path):\r
+                            DscArchList.append (Arch)\r
+                            break\r
 \r
         return DscArchList\r
 \r
@@ -568,6 +654,8 @@ class FfsInfStatement(FfsInfStatementClassObject):
         (ModulePath, FileName) = os.path.split(self.InfFileName)\r
         Index = FileName.rfind('.')\r
         FileName = FileName[0:Index]\r
+        if self.OverrideGuid:\r
+            FileName = self.OverrideGuid\r
         Arch = "NoneArch"\r
         if self.CurrentArch != None:\r
             Arch = self.CurrentArch\r
@@ -831,7 +919,7 @@ class FfsInfStatement(FfsInfStatementClassObject):
             \r
             if not HasGneratedFlag:\r
                 UniVfrOffsetFileSection = ""    \r
-                ModuleFileName = os.path.join(GenFdsGlobalVariable.WorkSpaceDir, self.InfFileName)\r
+                ModuleFileName = mws.join(GenFdsGlobalVariable.WorkSpaceDir, self.InfFileName)\r
                 InfData = GenFdsGlobalVariable.WorkSpace.BuildObject[PathClass(ModuleFileName), self.CurrentArch]\r
                 #\r
                 # Search the source list in InfData to find if there are .vfr file exist.\r
@@ -856,22 +944,23 @@ class FfsInfStatement(FfsInfStatementClassObject):
                     #\r
                     # Generate the Raw data of raw section\r
                     #\r
-                    os.path.join( self.OutputPath, self.BaseName + '.offset')\r
-                    UniVfrOffsetFileName    =  os.path.join( self.OutputPath, self.BaseName + '.offset')\r
-                    UniVfrOffsetFileSection =  os.path.join( self.OutputPath, self.BaseName + 'Offset' + '.raw')\r
-                    \r
-                    self.__GenUniVfrOffsetFile (VfrUniOffsetList, UniVfrOffsetFileName)\r
-                    \r
-                    UniVfrOffsetFileNameList = []\r
-                    UniVfrOffsetFileNameList.append(UniVfrOffsetFileName)\r
-                    """Call GenSection"""\r
-                    GenFdsGlobalVariable.GenerateSection(UniVfrOffsetFileSection,\r
-                                                         UniVfrOffsetFileNameList,\r
-                                                         "EFI_SECTION_RAW"\r
-                                                         )\r
-                    os.remove(UniVfrOffsetFileName)         \r
-                    SectList.append(UniVfrOffsetFileSection)\r
-                    HasGneratedFlag = True\r
+                    if VfrUniOffsetList:\r
+                        os.path.join( self.OutputPath, self.BaseName + '.offset')\r
+                        UniVfrOffsetFileName    =  os.path.join( self.OutputPath, self.BaseName + '.offset')\r
+                        UniVfrOffsetFileSection =  os.path.join( self.OutputPath, self.BaseName + 'Offset' + '.raw')\r
+\r
+                        self.__GenUniVfrOffsetFile (VfrUniOffsetList, UniVfrOffsetFileName)\r
+\r
+                        UniVfrOffsetFileNameList = []\r
+                        UniVfrOffsetFileNameList.append(UniVfrOffsetFileName)\r
+                        """Call GenSection"""\r
+                        GenFdsGlobalVariable.GenerateSection(UniVfrOffsetFileSection,\r
+                                                             UniVfrOffsetFileNameList,\r
+                                                             "EFI_SECTION_RAW"\r
+                                                             )\r
+                        os.remove(UniVfrOffsetFileName)\r
+                        SectList.append(UniVfrOffsetFileSection)\r
+                        HasGneratedFlag = True\r
                 \r
             for SecName in  SectList :\r
                 SectFiles.append(SecName)\r
@@ -942,47 +1031,9 @@ class FfsInfStatement(FfsInfStatementClassObject):
     #   @retval RetValue              A list contain offset of UNI/INF object.\r
     #    \r
     def __GetBuildOutputMapFileVfrUniInfo(self, VfrUniBaseName):\r
-        \r
-        RetValue = []\r
-        \r
         MapFileName = os.path.join(self.EfiOutputPath, self.BaseName + ".map")\r
-        try:\r
-            fInputfile = open(MapFileName, "r", 0)\r
-            try:\r
-                FileLinesList = fInputfile.readlines()\r
-            except:\r
-                EdkLogger.error("GenFds", FILE_READ_FAILURE, "File read failed for %s" %MapFileName,None)\r
-            finally:\r
-                fInputfile.close()\r
-        except:\r
-            EdkLogger.error("GenFds", FILE_OPEN_FAILURE, "File open failed for %s" %MapFileName,None)\r
-        \r
-        IsHex = False\r
-        for eachLine in FileLinesList:\r
-            for eachName in VfrUniBaseName.values():\r
-                if eachLine.find(eachName) != -1:\r
-                    eachLine = eachLine.strip()\r
-                    Element  = eachLine.split()\r
-                    #\r
-                    # MSFT/ICC/EBC map file\r
-                    #\r
-                    if (len(Element) == 4):\r
-                        try:\r
-                            int (Element[2], 16)\r
-                            IsHex = True\r
-                        except:\r
-                            IsHex = False\r
-                    \r
-                        if IsHex:\r
-                            RetValue.append((eachName, Element[2]))\r
-                            IsHex = False\r
-                    #\r
-                    # GCC map file\r
-                    #\r
-                    elif (len(Element) == 2) and Element[0].startswith("0x"):\r
-                        RetValue.append((eachName, Element[0]))\r
-        \r
-        return RetValue\r
+        EfiFileName = os.path.join(self.EfiOutputPath, self.BaseName + ".efi")\r
+        return GetVariableOffset(MapFileName, EfiFileName, VfrUniBaseName.values())\r
     \r
     ## __GenUniVfrOffsetFile() method\r
     #\r