]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/Python/AutoGen/AutoGen.py
Sync EDKII BaseTools to BaseTools project r2093.
[mirror_edk2.git] / BaseTools / Source / Python / AutoGen / AutoGen.py
index aaba768b4a84867be9d545296f52a978855c7173..4ecf2eafe711f523020373a3436abbeeb9c0d5c3 100644 (file)
@@ -189,7 +189,12 @@ class WorkspaceAutoGen(AutoGen):
             #\r
             Pa.CollectPlatformDynamicPcds()\r
             self.AutoGenObjectList.append(Pa)\r
-\r
+        \r
+        #\r
+        # Check PCDs token value conflict in each DEC file.\r
+        #\r
+        self._CheckAllPcdsTokenValueConflict()\r
+        \r
         self._BuildDir = None\r
         self._FvDir = None\r
         self._MakeFileDir = None\r
@@ -248,6 +253,75 @@ class WorkspaceAutoGen(AutoGen):
             # BuildCommand should be all the same. So just get one from platform AutoGen\r
             self._BuildCommand = self.AutoGenObjectList[0].BuildCommand\r
         return self._BuildCommand\r
+    \r
+    ## Check the PCDs token value conflict in each DEC file.\r
+    #\r
+    # Will cause build break and raise error message while two PCDs conflict.\r
+    # \r
+    # @return  None\r
+    #\r
+    def _CheckAllPcdsTokenValueConflict(self):\r
+        if len(self.BuildDatabase.WorkspaceDb.PackageList) >= 1:\r
+            for Package in self.BuildDatabase.WorkspaceDb.PackageList:\r
+                PcdList = Package.Pcds.values()\r
+                PcdList.sort(lambda x, y: cmp(x.TokenValue, y.TokenValue)) \r
+                Count = 0\r
+                while (Count < len(PcdList) - 1) :\r
+                    Item = PcdList[Count]\r
+                    ItemNext = PcdList[Count + 1]\r
+                    #\r
+                    # Make sure in the same token space the TokenValue should be unique\r
+                    #\r
+                    if (Item.TokenValue == ItemNext.TokenValue):\r
+                        SameTokenValuePcdList = []\r
+                        SameTokenValuePcdList.append(Item)\r
+                        SameTokenValuePcdList.append(ItemNext)\r
+                        RemainPcdListLength = len(PcdList) - Count - 2\r
+                        for ValueSameCount in range(RemainPcdListLength):\r
+                            if PcdList[len(PcdList) - RemainPcdListLength + ValueSameCount].TokenValue == Item.TokenValue:\r
+                                SameTokenValuePcdList.append(PcdList[len(PcdList) - RemainPcdListLength + ValueSameCount])\r
+                            else:\r
+                                break;\r
+                        #\r
+                        # Sort same token value PCD list with TokenGuid and TokenCName\r
+                        #\r
+                        SameTokenValuePcdList.sort(lambda x, y: cmp("%s.%s"%(x.TokenSpaceGuidCName, x.TokenCName), "%s.%s"%(y.TokenSpaceGuidCName, y.TokenCName))) \r
+                        SameTokenValuePcdListCount = 0     \r
+                        while (SameTokenValuePcdListCount < len(SameTokenValuePcdList) - 1):\r
+                            TemListItem     = SameTokenValuePcdList[SameTokenValuePcdListCount]\r
+                            TemListItemNext = SameTokenValuePcdList[SameTokenValuePcdListCount + 1] \r
+                                                                                                      \r
+                            if (TemListItem.TokenSpaceGuidCName == TemListItemNext.TokenSpaceGuidCName) and (TemListItem.TokenCName != TemListItemNext.TokenCName):\r
+                                EdkLogger.error(\r
+                                            'build',\r
+                                            FORMAT_INVALID,\r
+                                            "The TokenValue [%s] of PCD [%s.%s] is conflict with: [%s.%s] in %s"\\r
+                                            % (TemListItem.TokenValue, TemListItem.TokenSpaceGuidCName, TemListItem.TokenCName, TemListItemNext.TokenSpaceGuidCName, TemListItemNext.TokenCName, Package),\r
+                                            ExtraData=None\r
+                                            )\r
+                            SameTokenValuePcdListCount += 1\r
+                        Count += SameTokenValuePcdListCount\r
+                    Count += 1\r
+                \r
+                PcdList = Package.Pcds.values()\r
+                PcdList.sort(lambda x, y: cmp("%s.%s"%(x.TokenSpaceGuidCName, x.TokenCName), "%s.%s"%(y.TokenSpaceGuidCName, y.TokenCName)))\r
+                Count = 0\r
+                while (Count < len(PcdList) - 1) :\r
+                    Item = PcdList[Count]\r
+                    ItemNext = PcdList[Count + 1]                \r
+                    #\r
+                    # Check PCDs with same TokenSpaceGuidCName.TokenCName have same token value as well.\r
+                    #\r
+                    if (Item.TokenSpaceGuidCName == ItemNext.TokenSpaceGuidCName) and (Item.TokenCName == ItemNext.TokenCName) and (Item.TokenValue != ItemNext.TokenValue):\r
+                        EdkLogger.error(\r
+                                    'build',\r
+                                    FORMAT_INVALID,\r
+                                    "The TokenValue [%s] of PCD [%s.%s] in %s defined in two places should be same as well."\\r
+                                    % (Item.TokenValue, Item.TokenSpaceGuidCName, Item.TokenCName, Package),\r
+                                    ExtraData=None\r
+                                    )\r
+                    Count += 1\r
+                                      \r
 \r
     ## Create makefile for the platform and modules in it\r
     #\r
@@ -306,7 +380,27 @@ class PlatformAutoGen(AutoGen):
     # \r
     _DynaPcdList_ = []\r
     _NonDynaPcdList_ = []\r
-\r
+    \r
+    #\r
+    # The priority list while override build option \r
+    #\r
+    PrioList = {"0x11111"  : 16,     #  TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE (Highest)\r
+                "0x01111"  : 15,     #  ******_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE\r
+                "0x10111"  : 14,     #  TARGET_*********_ARCH_COMMANDTYPE_ATTRIBUTE\r
+                "0x00111"  : 13,     #  ******_*********_ARCH_COMMANDTYPE_ATTRIBUTE \r
+                "0x11011"  : 12,     #  TARGET_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE\r
+                "0x01011"  : 11,     #  ******_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE\r
+                "0x10011"  : 10,     #  TARGET_*********_****_COMMANDTYPE_ATTRIBUTE\r
+                "0x00011"  : 9,      #  ******_*********_****_COMMANDTYPE_ATTRIBUTE\r
+                "0x11101"  : 8,      #  TARGET_TOOLCHAIN_ARCH_***********_ATTRIBUTE\r
+                "0x01101"  : 7,      #  ******_TOOLCHAIN_ARCH_***********_ATTRIBUTE\r
+                "0x10101"  : 6,      #  TARGET_*********_ARCH_***********_ATTRIBUTE\r
+                "0x00101"  : 5,      #  ******_*********_ARCH_***********_ATTRIBUTE\r
+                "0x11001"  : 4,      #  TARGET_TOOLCHAIN_****_***********_ATTRIBUTE\r
+                "0x01001"  : 3,      #  ******_TOOLCHAIN_****_***********_ATTRIBUTE\r
+                "0x10001"  : 2,      #  TARGET_*********_****_***********_ATTRIBUTE\r
+                "0x00001"  : 1}      #  ******_*********_****_***********_ATTRIBUTE (Lowest)\r
+    \r
     ## The real constructor of PlatformAutoGen\r
     #\r
     #  This method is not supposed to be called by users of PlatformAutoGen. It's\r
@@ -481,12 +575,12 @@ class PlatformAutoGen(AutoGen):
         UnicodePcdArray = []\r
         HiiPcdArray     = []\r
         OtherPcdArray   = []\r
+        VpdPcdDict      = {}\r
         VpdFile               = VpdInfoFile.VpdInfoFile()\r
         NeedProcessVpdMapFile = False                    \r
         \r
         if (self.Workspace.ArchList[-1] == self.Arch): \r
             for Pcd in self._DynamicPcdList:\r
-\r
                 # just pick the a value to determine whether is unicode string type\r
                 Sku      = Pcd.SkuInfoList[Pcd.SkuInfoList.keys()[0]]\r
                 Sku.VpdOffset = Sku.VpdOffset.strip()\r
@@ -500,32 +594,47 @@ class PlatformAutoGen(AutoGen):
                     HiiPcdArray.append(Pcd)\r
                 else:\r
                     OtherPcdArray.append(Pcd)\r
-                    \r
                 if Pcd.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD]:\r
-                    if not (self.Platform.VpdToolGuid == None or self.Platform.VpdToolGuid == ''):\r
-                        #\r
-                        # Fix the optional data of VPD PCD.\r
-                        #\r
-                        if (Pcd.DatumType.strip() != "VOID*"):\r
-                            if Sku.DefaultValue == '':\r
-                                Pcd.SkuInfoList[Pcd.SkuInfoList.keys()[0]].DefaultValue = Pcd.MaxDatumSize\r
-                                Pcd.MaxDatumSize = None\r
-                            else:\r
-                                EdkLogger.error("build", AUTOGEN_ERROR, "PCD setting error",\r
-                                                File=self.MetaFile,\r
-                                                ExtraData="\n\tPCD: %s.%s format incorrect in DSC: %s\n\t\t\n"\r
-                                                          % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName, self.Platform.MetaFile.Path))                                                                            \r
-                        \r
-                        VpdFile.Add(Pcd, Sku.VpdOffset)\r
-                        # if the offset of a VPD is *, then it need to be fixed up by third party tool.\r
-                        if not NeedProcessVpdMapFile and Sku.VpdOffset == "*":\r
-                            NeedProcessVpdMapFile = True\r
+                    VpdPcdDict[(Pcd.TokenCName, Pcd.TokenSpaceGuidCName)] = Pcd                   \r
+            \r
+            PlatformPcds = self.Platform.Pcds.keys()\r
+            PlatformPcds.sort()            \r
+            #\r
+            # Add VPD type PCD into VpdFile and determine whether the VPD PCD need to be fixed up.\r
+            #\r
+            for PcdKey in PlatformPcds:\r
+                Pcd           = self.Platform.Pcds[PcdKey]                            \r
+                if Pcd.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD]:\r
+                    Pcd           = VpdPcdDict[PcdKey]\r
+                    Sku           = Pcd.SkuInfoList[Pcd.SkuInfoList.keys()[0]]\r
+                    Sku.VpdOffset = Sku.VpdOffset.strip()                \r
+                    #\r
+                    # Fix the optional data of VPD PCD.\r
+                    #\r
+                    if (Pcd.DatumType.strip() != "VOID*"):\r
+                        if Sku.DefaultValue == '':\r
+                            Pcd.SkuInfoList[Pcd.SkuInfoList.keys()[0]].DefaultValue = Pcd.MaxDatumSize\r
+                            Pcd.MaxDatumSize = None\r
+                        else:\r
+                            EdkLogger.error("build", AUTOGEN_ERROR, "PCD setting error",\r
+                                            File=self.MetaFile,\r
+                                            ExtraData="\n\tPCD: %s.%s format incorrect in DSC: %s\n\t\t\n"\r
+                                                      % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName, self.Platform.MetaFile.Path))                                                                            \r
+                    \r
+                    VpdFile.Add(Pcd, Sku.VpdOffset)\r
+                    # if the offset of a VPD is *, then it need to be fixed up by third party tool.\r
+                    if not NeedProcessVpdMapFile and Sku.VpdOffset == "*":\r
+                        NeedProcessVpdMapFile = True\r
+                        if self.Platform.VpdToolGuid == None or self.Platform.VpdToolGuid == '':\r
+                            EdkLogger.error("Build", FILE_NOT_FOUND, \\r
+                                            "Fail to find third-party BPDG tool to process VPD PCDs. BPDG Guid tool need to be defined in tools_def.txt and VPD_TOOL_GUID need to be provided in DSC file.")\r
+                            \r
                                    \r
             #\r
             # Fix the PCDs define in VPD PCD section that never referenced by module.\r
             # An example is PCD for signature usage.\r
-            #              \r
-            for DscPcd in self.Platform.Pcds:\r
+            #            \r
+            for DscPcd in PlatformPcds:\r
                 DscPcdEntry = self.Platform.Pcds[DscPcd]\r
                 if DscPcdEntry.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD]:\r
                     if not (self.Platform.VpdToolGuid == None or self.Platform.VpdToolGuid == ''):\r
@@ -614,7 +723,7 @@ class PlatformAutoGen(AutoGen):
                             # just pick the a value to determine whether is unicode string type\r
                             Sku = Pcd.SkuInfoList[Pcd.SkuInfoList.keys()[0]]                        \r
                             if Sku.VpdOffset == "*":\r
-                                    Sku.VpdOffset = VpdFile.GetOffset(Pcd)[0]\r
+                                Sku.VpdOffset = VpdFile.GetOffset(Pcd)[0]\r
                     else:\r
                         EdkLogger.error("build", FILE_READ_FAILURE, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath)\r
             \r
@@ -693,7 +802,7 @@ class PlatformAutoGen(AutoGen):
                 if "FLAGS" in self.ToolDefinition["MAKE"]:\r
                     NewOption = self.ToolDefinition["MAKE"]["FLAGS"].strip()\r
                     if NewOption != '':\r
-                      self._BuildCommand += SplitOption(NewOption)\r
+                        self._BuildCommand += SplitOption(NewOption)\r
         return self._BuildCommand\r
 \r
     ## Get tool chain definition\r
@@ -1220,16 +1329,86 @@ class PlatformAutoGen(AutoGen):
                     EdkLogger.verbose("\t" + LibraryName + " : " + str(Library) + ' ' + str(type(Library)))\r
         return LibraryList\r
 \r
+    ## Calculate the priority value of the build option\r
+    #\r
+    # @param    Key    Build option definition contain: TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE\r
+    #\r
+    # @retval   Value  Priority value based on the priority list.\r
+    #\r
+    def CalculatePriorityValue(self, Key):\r
+        Target, ToolChain, Arch, CommandType, Attr = Key.split('_')       \r
+        PriorityValue = 0x11111          \r
+        if Target == "*":\r
+            PriorityValue &= 0x01111\r
+        if ToolChain == "*":\r
+            PriorityValue &= 0x10111\r
+        if Arch == "*":\r
+            PriorityValue &= 0x11011\r
+        if CommandType == "*":\r
+            PriorityValue &= 0x11101\r
+        if Attr == "*":\r
+            PriorityValue &= 0x11110\r
+        \r
+        return self.PrioList["0x%0.5x"%PriorityValue]\r
+                                    \r
+\r
     ## Expand * in build option key\r
     #\r
     #   @param  Options     Options to be expanded\r
     #\r
     #   @retval options     Options expanded\r
-    #\r
+    #      \r
     def _ExpandBuildOption(self, Options, ModuleStyle=None):\r
         BuildOptions = {}\r
         FamilyMatch  = False\r
         FamilyIsNull = True\r
+                \r
+        OverrideList = {}\r
+        #\r
+        # Construct a list contain the build options which need override.\r
+        #\r
+        for Key in Options:\r
+            #\r
+            # Key[0] -- tool family\r
+            # Key[1] -- TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE\r
+            #\r
+            if Key[0] == self.BuildRuleFamily :\r
+                Target, ToolChain, Arch, CommandType, Attr = Key[1].split('_')\r
+                if Target == self.BuildTarget or Target == "*":\r
+                    if ToolChain == self.ToolChain or ToolChain == "*":\r
+                        if Arch == self.Arch or Arch == "*":\r
+                            if Options[Key].startswith("="):\r
+                                if OverrideList.get(Key[1]) != None:                                                \r
+                                    OverrideList.pop(Key[1])\r
+                                OverrideList[Key[1]] = Options[Key]\r
+        \r
+        #\r
+        # Use the highest priority value. \r
+        #\r
+        if (len(OverrideList) >= 2):\r
+            KeyList   = OverrideList.keys()\r
+            for Index in range(len(KeyList)):\r
+                NowKey      = KeyList[Index]\r
+                Target1, ToolChain1, Arch1, CommandType1, Attr1 = NowKey.split("_")\r
+                for Index1 in range(len(KeyList) - Index - 1):\r
+                    NextKey = KeyList[Index1 + Index + 1]\r
+                    #\r
+                    # Compare two Key, if one is included by another, choose the higher priority one\r
+                    #                    \r
+                    Target2, ToolChain2, Arch2, CommandType2, Attr2 = NextKey.split("_")\r
+                    if Target1 == Target2 or Target1 == "*" or Target2 == "*":\r
+                        if ToolChain1 == ToolChain2 or ToolChain1 == "*" or ToolChain2 == "*":\r
+                            if Arch1 == Arch2 or Arch1 == "*" or Arch2 == "*":\r
+                                if CommandType1 == CommandType2 or CommandType1 == "*" or CommandType2 == "*":\r
+                                    if Attr1 == Attr2 or Attr1 == "*" or Attr2 == "*":\r
+                                        if self.CalculatePriorityValue(NowKey) > self.CalculatePriorityValue(NextKey):\r
+                                            if Options.get((self.BuildRuleFamily, NextKey)) != None:  \r
+                                                Options.pop((self.BuildRuleFamily, NextKey))\r
+                                        else:\r
+                                            if Options.get((self.BuildRuleFamily, NowKey)) != None: \r
+                                                Options.pop((self.BuildRuleFamily, NowKey))\r
+                                                           \r
+        \r
         for Key in Options:\r
             if ModuleStyle != None and len (Key) > 2:\r
                 # Check Module style is EDK or EDKII.\r