]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/Python/GenFds/FfsInfStatement.py
License header updated to match correct format.
[mirror_edk2.git] / BaseTools / Source / Python / GenFds / FfsInfStatement.py
index 96e212cae7aa7d892ea06b1f2e4af7b21dbb5f04..cc85a32796d2e2b4e0200ada753bcf4dbfa47d83 100644 (file)
@@ -1,7 +1,7 @@
 ## @file\r
 # process FFS generation from INF statement\r
 #\r
-#  Copyright (c) 2007 - 2011, Intel Corporation. All rights reserved.<BR>\r
+#  Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<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
@@ -16,8 +16,7 @@
 # Import Modules\r
 #\r
 import Rule\r
-import os\r
-import shutil\r
+import Common.LongFilePathOs as os\r
 import StringIO\r
 from struct import *\r
 from GenFdsGlobalVariable import GenFdsGlobalVariable\r
@@ -31,17 +30,23 @@ from CommonDataClass.FdfClass import FfsInfStatementClassObject
 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 import EdkLogger\r
 from Common.BuildToolError import *\r
 from GuidSection import GuidSection\r
 from FvImageSection import FvImageSection\r
 from Common.Misc import PeImageClass\r
 from AutoGen.GenDepex import DependencyExpression\r
+from PatchPcdValue.PatchPcdValue import PatchBinaryFile\r
+from Common.LongFilePathSupport import CopyLongFilePath\r
+from Common.LongFilePathSupport import OpenLongFilePath as open\r
 \r
 ## generate FFS from INF\r
 #\r
 #\r
 class FfsInfStatement(FfsInfStatementClassObject):\r
+    ## The mapping dictionary from datum type to its maximum number.\r
+    _MAX_SIZE_TYPE = {"BOOLEAN":0x01, "UINT8":0xFF, "UINT16":0xFFFF, "UINT32":0xFFFFFFFF, "UINT64":0xFFFFFFFFFFFFFFFF}\r
     ## The constructor\r
     #\r
     #   @param  self        The object pointer\r
@@ -60,6 +65,8 @@ class FfsInfStatement(FfsInfStatementClassObject):
         self.CurrentLineContent = None\r
         self.FileName = None\r
         self.InfFileName = None\r
+        self.OverrideGuid = None\r
+        self.PatchedBinFile = ''\r
 \r
     ## GetFinalTargetSuffixMap() method\r
     #\r
@@ -141,7 +148,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
@@ -160,7 +169,9 @@ class FfsInfStatement(FfsInfStatementClassObject):
         ErrorCode, ErrorInfo = PathClassObj.Validate(".inf")\r
         if ErrorCode != 0:\r
             EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo)\r
-        \r
+\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
@@ -195,6 +206,9 @@ 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
@@ -203,14 +217,94 @@ class FfsInfStatement(FfsInfStatementClassObject):
 \r
         if Inf._Defs != None and len(Inf._Defs) > 0:\r
             self.OptRomDefs.update(Inf._Defs)\r
-        \r
+\r
+        self.PatchPcds = []\r
+        InfPcds = Inf.Pcds\r
+        Platform = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, self.CurrentArch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]\r
+        FdfPcdDict = GenFdsGlobalVariable.FdfParser.Profile.PcdDict\r
+\r
+        # Workaround here: both build and GenFds tool convert the workspace path to lower case\r
+        # But INF file path in FDF and DSC file may have real case characters.\r
+        # Try to convert the path to lower case to see if PCDs value are override by DSC.\r
+        DscModules = {}\r
+        for DscModule in Platform.Modules:\r
+            DscModules[str(DscModule).lower()] = Platform.Modules[DscModule]\r
+        for PcdKey in InfPcds:\r
+            Pcd = InfPcds[PcdKey]\r
+            if not hasattr(Pcd, 'Offset'):\r
+                continue\r
+            if Pcd.Type != 'PatchableInModule':\r
+                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
+                PatchPcd = Platform.Pcds[PcdKey]\r
+            DscOverride = False\r
+            if PatchPcd and Pcd.Type == PatchPcd.Type:\r
+                DefaultValue = PatchPcd.DefaultValue\r
+                DscOverride = True\r
+\r
+            # Override Patchable PCD value by the value from FDF\r
+            FdfOverride = False\r
+            if PcdKey in FdfPcdDict:\r
+                DefaultValue = FdfPcdDict[PcdKey]\r
+                FdfOverride = True\r
+\r
+            if not DscOverride and not FdfOverride:\r
+                continue\r
+            # Check value, if value are equal, no need to patch\r
+            if Pcd.DatumType == "VOID*":\r
+                if Pcd.DefaultValue == DefaultValue or DefaultValue in [None, '']:\r
+                    continue\r
+                # Get the string size from FDF or DSC\r
+                if DefaultValue[0] == 'L':\r
+                    # Remove L"", but the '\0' must be appended\r
+                    MaxDatumSize = str((len(DefaultValue) - 2) * 2)\r
+                elif DefaultValue[0] == '{':\r
+                    MaxDatumSize = str(len(DefaultValue.split(',')))\r
+                else:\r
+                    MaxDatumSize = str(len(DefaultValue) - 1)\r
+                if DscOverride:\r
+                    Pcd.MaxDatumSize = PatchPcd.MaxDatumSize\r
+                # If no defined the maximum size in DSC, try to get current size from INF\r
+                if Pcd.MaxDatumSize in ['', None]:\r
+                    Pcd.MaxDatumSize = str(len(Pcd.DefaultValue.split(',')))\r
+            else:\r
+                Base1 = Base2 = 10\r
+                if Pcd.DefaultValue.upper().startswith('0X'):\r
+                    Base1 = 16\r
+                if DefaultValue.upper().startswith('0X'):\r
+                    Base2 = 16\r
+                try:\r
+                    PcdValueInImg = int(Pcd.DefaultValue, Base1)\r
+                    PcdValueInDscOrFdf = int(DefaultValue, Base2)\r
+                    if PcdValueInImg == PcdValueInDscOrFdf:\r
+                        continue\r
+                except:\r
+                    continue\r
+            # Check the Pcd size and data type\r
+            if Pcd.DatumType == "VOID*":\r
+                if int(MaxDatumSize) > int(Pcd.MaxDatumSize):\r
+                    EdkLogger.error("GenFds", GENFDS_ERROR, "The size of VOID* type PCD '%s.%s' exceeds its maximum size %d bytes." \\r
+                                    % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName, int(MaxDatumSize) - int(Pcd.MaxDatumSize)))\r
+            else:\r
+                if PcdValueInDscOrFdf > FfsInfStatement._MAX_SIZE_TYPE[Pcd.DatumType] \\r
+                    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
+            self.PatchPcds.append((Pcd, DefaultValue))\r
+\r
         self.InfModule = Inf\r
-            \r
-        GenFdsGlobalVariable.VerboseLogger( "BaseName : %s" %self.BaseName)\r
-        GenFdsGlobalVariable.VerboseLogger("ModuleGuid : %s" %self.ModuleGuid)\r
-        GenFdsGlobalVariable.VerboseLogger("ModuleType : %s" %self.ModuleType)\r
-        GenFdsGlobalVariable.VerboseLogger("VersionString : %s" %self.VersionString)\r
-        GenFdsGlobalVariable.VerboseLogger("InfFileName :%s"  %self.InfFileName)\r
+        self.PcdIsDriver = Inf.PcdIsDriver\r
+        self.IsBinaryModule = Inf.IsBinaryModule\r
+        GenFdsGlobalVariable.VerboseLogger("BaseName : %s" % self.BaseName)\r
+        GenFdsGlobalVariable.VerboseLogger("ModuleGuid : %s" % self.ModuleGuid)\r
+        GenFdsGlobalVariable.VerboseLogger("ModuleType : %s" % self.ModuleType)\r
+        GenFdsGlobalVariable.VerboseLogger("VersionString : %s" % self.VersionString)\r
+        GenFdsGlobalVariable.VerboseLogger("InfFileName :%s" % self.InfFileName)\r
 \r
         #\r
         # Set OutputPath = ${WorkSpace}\Build\Fv\Ffs\${ModuleGuid}+ ${MdouleName}\\r
@@ -224,6 +318,34 @@ class FfsInfStatement(FfsInfStatementClassObject):
         self.EfiOutputPath = self.__GetEFIOutPutPath__()\r
         GenFdsGlobalVariable.VerboseLogger( "ModuelEFIPath: " + self.EfiOutputPath)\r
 \r
+    ## PatchEfiFile\r
+    #\r
+    #  Patch EFI file with patch PCD\r
+    #\r
+    #  @param EfiFile: EFI file needs to be patched.\r
+    #  @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, FileType):\r
+        if not self.PatchPcds:\r
+            return EfiFile\r
+        if FileType != 'PE32' and self.ModuleType != "USER_DEFINED":\r
+            return EfiFile\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
+        Basename = os.path.basename(EfiFile)\r
+        Output = os.path.join(self.OutputPath, Basename)\r
+        CopyLongFilePath(EfiFile, Output)\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
+        self.PatchedBinFile = os.path.normpath(EfiFile)\r
+        return Output\r
     ## GenFfs() method\r
     #\r
     #   Generate FFS\r
@@ -244,7 +366,7 @@ class FfsInfStatement(FfsInfStatementClassObject):
         #\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
@@ -388,6 +510,11 @@ class FfsInfStatement(FfsInfStatementClassObject):
             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
+\r
         return DscArchList\r
 \r
     ## GetCurrentArch() method\r
@@ -458,6 +585,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
@@ -539,8 +668,8 @@ class FfsInfStatement(FfsInfStatementClassObject):
                 if not NoStrip:\r
                     FileBeforeStrip = os.path.join(self.OutputPath, ModuleName + '.reloc')\r
                     if not os.path.exists(FileBeforeStrip) or \\r
-                        (os.path.getmtime(File) > os.path.getmtime(FileBeforeStrip)):\r
-                        shutil.copyfile(File, FileBeforeStrip)\r
+                           (os.path.getmtime(File) > os.path.getmtime(FileBeforeStrip)):\r
+                        CopyLongFilePath(File, FileBeforeStrip)\r
                     StrippedFile = os.path.join(self.OutputPath, ModuleName + '.stipped')\r
                     GenFdsGlobalVariable.GenerateFirmwareImage(\r
                                             StrippedFile,\r
@@ -578,8 +707,9 @@ class FfsInfStatement(FfsInfStatementClassObject):
             if not NoStrip:\r
                 FileBeforeStrip = os.path.join(self.OutputPath, ModuleName + '.reloc')\r
                 if not os.path.exists(FileBeforeStrip) or \\r
-                    (os.path.getmtime(GenSecInputFile) > os.path.getmtime(FileBeforeStrip)):\r
-                    shutil.copyfile(GenSecInputFile, FileBeforeStrip)\r
+                       (os.path.getmtime(GenSecInputFile) > os.path.getmtime(FileBeforeStrip)):\r
+                    CopyLongFilePath(GenSecInputFile, FileBeforeStrip)\r
+\r
                 StrippedFile = os.path.join(self.OutputPath, ModuleName + '.stipped')\r
                 GenFdsGlobalVariable.GenerateFirmwareImage(\r
                                         StrippedFile,\r
@@ -663,6 +793,30 @@ class FfsInfStatement(FfsInfStatementClassObject):
         SectAlignments = []\r
         Index = 1\r
         HasGneratedFlag = False\r
+        if self.PcdIsDriver == 'PEI_PCD_DRIVER':\r
+            if self.IsBinaryModule:\r
+                PcdExDbFileName = os.path.join(GenFdsGlobalVariable.FvDir, "PEIPcdDataBase.raw")\r
+            else:\r
+                PcdExDbFileName = os.path.join(self.EfiOutputPath, "PEIPcdDataBase.raw")\r
+            PcdExDbSecName = os.path.join(self.OutputPath, "PEIPcdDataBaseSec.raw")\r
+            GenFdsGlobalVariable.GenerateSection(PcdExDbSecName,\r
+                                                 [PcdExDbFileName],\r
+                                                 "EFI_SECTION_RAW",\r
+                                                 )\r
+            SectFiles.append(PcdExDbSecName)\r
+            SectAlignments.append(None)\r
+        elif self.PcdIsDriver == 'DXE_PCD_DRIVER':\r
+            if self.IsBinaryModule:\r
+                PcdExDbFileName = os.path.join(GenFdsGlobalVariable.FvDir, "DXEPcdDataBase.raw")\r
+            else:\r
+                PcdExDbFileName = os.path.join(self.EfiOutputPath, "DXEPcdDataBase.raw")\r
+            PcdExDbSecName = os.path.join(self.OutputPath, "DXEPcdDataBaseSec.raw")\r
+            GenFdsGlobalVariable.GenerateSection(PcdExDbSecName,\r
+                                                 [PcdExDbFileName],\r
+                                                 "EFI_SECTION_RAW",\r
+                                                 )\r
+            SectFiles.append(PcdExDbSecName)\r
+            SectAlignments.append(None)\r
         for Sect in Rule.SectionList:\r
             SecIndex = '%d' %Index\r
             SectList  = []\r