]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/Python/AutoGen/AutoGen.py
BaseTools: Add mixed PCD support feature
[mirror_edk2.git] / BaseTools / Source / Python / AutoGen / AutoGen.py
index 50d585f6aa010360f5c541a19e8a1ffc6193e582..2cc6970325fffb4a5ee2d4a5b189e77f770a8990 100644 (file)
@@ -413,6 +413,129 @@ class WorkspaceAutoGen(AutoGen):
                     if (TokenCName, TokenSpaceGuidCName) in PcdSet:\r
                         PcdSet[(TokenCName, TokenSpaceGuidCName)] = NewValue\r
 \r
+            SourcePcdDict = {'DynamicEx':[], 'PatchableInModule':[],'Dynamic':[],'FixedAtBuild':[]}\r
+            BinaryPcdDict = {'DynamicEx':[], 'PatchableInModule':[]}\r
+            SourcePcdDict_Keys = SourcePcdDict.keys()\r
+            BinaryPcdDict_Keys = BinaryPcdDict.keys()\r
+\r
+            # generate the SourcePcdDict and BinaryPcdDict\r
+            for BuildData in PGen.BuildDatabase._CACHE_.values():\r
+                if BuildData.Arch != Arch:\r
+                    continue\r
+                if BuildData.MetaFile.Ext == '.inf':\r
+                    for key in BuildData.Pcds:\r
+                        if BuildData.Pcds[key].Pending:\r
+                            if key in Platform.Pcds:\r
+                                PcdInPlatform = Platform.Pcds[key]\r
+                                if PcdInPlatform.Type not in [None, '']:\r
+                                    BuildData.Pcds[key].Type = PcdInPlatform.Type\r
+\r
+                            if BuildData.MetaFile in Platform.Modules:\r
+                                PlatformModule = Platform.Modules[str(BuildData.MetaFile)]\r
+                                if key in PlatformModule.Pcds:\r
+                                    PcdInPlatform = PlatformModule.Pcds[key]\r
+                                    if PcdInPlatform.Type not in [None, '']:\r
+                                        BuildData.Pcds[key].Type = PcdInPlatform.Type\r
+\r
+                        if 'DynamicEx' in BuildData.Pcds[key].Type:\r
+                            if BuildData.IsBinaryModule:\r
+                                if (BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName) not in BinaryPcdDict['DynamicEx']:\r
+                                    BinaryPcdDict['DynamicEx'].append((BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName))\r
+                            else:\r
+                                if (BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName) not in SourcePcdDict['DynamicEx']:\r
+                                    SourcePcdDict['DynamicEx'].append((BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName))\r
+\r
+                        elif 'PatchableInModule' in BuildData.Pcds[key].Type:\r
+                            if BuildData.MetaFile.Ext == '.inf':\r
+                                if BuildData.IsBinaryModule:\r
+                                    if (BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName) not in BinaryPcdDict['PatchableInModule']:\r
+                                        BinaryPcdDict['PatchableInModule'].append((BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName))\r
+                                else:\r
+                                    if (BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName) not in SourcePcdDict['PatchableInModule']:\r
+                                        SourcePcdDict['PatchableInModule'].append((BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName))\r
+\r
+                        elif 'Dynamic' in BuildData.Pcds[key].Type:\r
+                            if (BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName) not in SourcePcdDict['Dynamic']:\r
+                                SourcePcdDict['Dynamic'].append((BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName))\r
+                        elif 'FixedAtBuild' in BuildData.Pcds[key].Type:\r
+                            if (BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName) not in SourcePcdDict['FixedAtBuild']:\r
+                                SourcePcdDict['FixedAtBuild'].append((BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName))\r
+                else:\r
+                    pass\r
+\r
+            #\r
+            # intersection the BinaryPCD for Mixed PCD\r
+            #\r
+            for i in BinaryPcdDict_Keys:\r
+                for j in BinaryPcdDict_Keys:\r
+                    if i != j:\r
+                        IntersectionList = list(set(BinaryPcdDict[i]).intersection(set(BinaryPcdDict[j])))\r
+                        for item in IntersectionList:\r
+                            NewPcd1 = (item[0] + '_' + i, item[1])\r
+                            NewPcd2 = (item[0] + '_' + j, item[1])\r
+                            if item not in GlobalData.MixedPcd:\r
+                                GlobalData.MixedPcd[item] = [NewPcd1, NewPcd2]\r
+                            else:\r
+                                if NewPcd1 not in GlobalData.MixedPcd[item]:\r
+                                    GlobalData.MixedPcd[item].append(NewPcd1)\r
+                                if NewPcd2 not in GlobalData.MixedPcd[item]:\r
+                                    GlobalData.MixedPcd[item].append(NewPcd2)\r
+                    else:\r
+                        pass\r
+\r
+            #\r
+            # intersection the SourcePCD and BinaryPCD for Mixed PCD\r
+            #\r
+            for i in SourcePcdDict_Keys:\r
+                for j in BinaryPcdDict_Keys:\r
+                    if i != j:\r
+                        IntersectionList = list(set(SourcePcdDict[i]).intersection(set(BinaryPcdDict[j])))\r
+                        for item in IntersectionList:\r
+                            NewPcd1 = (item[0] + '_' + i, item[1])\r
+                            NewPcd2 = (item[0] + '_' + j, item[1])\r
+                            if item not in GlobalData.MixedPcd:\r
+                                GlobalData.MixedPcd[item] = [NewPcd1, NewPcd2]\r
+                            else:\r
+                                if NewPcd1 not in GlobalData.MixedPcd[item]:\r
+                                    GlobalData.MixedPcd[item].append(NewPcd1)\r
+                                if NewPcd2 not in GlobalData.MixedPcd[item]:\r
+                                    GlobalData.MixedPcd[item].append(NewPcd2)\r
+                    else:\r
+                        pass\r
+\r
+            for BuildData in PGen.BuildDatabase._CACHE_.values():\r
+                if BuildData.Arch != Arch:\r
+                    continue\r
+                for key in BuildData.Pcds:\r
+                    for SinglePcd in GlobalData.MixedPcd:\r
+                        if (BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName) == SinglePcd:\r
+                            for item in GlobalData.MixedPcd[SinglePcd]:\r
+                                Pcd_Type = item[0].split('_')[-1]\r
+                                if (Pcd_Type == BuildData.Pcds[key].Type) or (Pcd_Type == TAB_PCDS_DYNAMIC_EX and BuildData.Pcds[key].Type in GenC.gDynamicExPcd) or \\r
+                                   (Pcd_Type == TAB_PCDS_DYNAMIC and BuildData.Pcds[key].Type in GenC.gDynamicPcd):\r
+                                    Value = BuildData.Pcds[key]\r
+                                    Value.TokenCName = BuildData.Pcds[key].TokenCName + '_' + Pcd_Type\r
+                                    if len(key) == 2:\r
+                                        newkey = (Value.TokenCName, key[1])\r
+                                    elif len(key) == 3:\r
+                                        newkey = (Value.TokenCName, key[1], key[2])\r
+                                    del BuildData.Pcds[key]\r
+                                    BuildData.Pcds[newkey] = Value\r
+                                    break\r
+                                else:\r
+                                    pass\r
+                            break\r
+                        else:\r
+                            pass\r
+\r
+            # handle the mixed pcd in FDF file\r
+            for key in PcdSet:\r
+                if key in GlobalData.MixedPcd:\r
+                    Value = PcdSet[key]\r
+                    del PcdSet[key]\r
+                    for item in GlobalData.MixedPcd[key]:\r
+                        PcdSet[item] = Value\r
+\r
             #Collect package set information from INF of FDF\r
             PkgSet = set()\r
             for Inf in ModuleList:\r
@@ -770,17 +893,23 @@ class WorkspaceAutoGen(AutoGen):
                         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
+                            Flag = False\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
+                                for PcdItem in GlobalData.MixedPcd:\r
+                                    if (TemListItem.TokenCName, TemListItem.TokenSpaceGuidCName) in GlobalData.MixedPcd[PcdItem] or \\r
+                                        (TemListItemNext.TokenCName, TemListItemNext.TokenSpaceGuidCName) in GlobalData.MixedPcd[PcdItem]:\r
+                                        Flag = True\r
+                                if not Flag:\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
@@ -1055,6 +1184,28 @@ class PlatformAutoGen(AutoGen):
                             Sku.DefaultValue = PcdItem[2]\r
                         break\r
 \r
+        for key in self.Platform.Pcds:\r
+            for SinglePcd in GlobalData.MixedPcd:\r
+                if (self.Platform.Pcds[key].TokenCName, self.Platform.Pcds[key].TokenSpaceGuidCName) == SinglePcd:\r
+                    for item in GlobalData.MixedPcd[SinglePcd]:\r
+                        Pcd_Type = item[0].split('_')[-1]\r
+                        if (Pcd_Type == self.Platform.Pcds[key].Type) or (Pcd_Type == TAB_PCDS_DYNAMIC_EX and self.Platform.Pcds[key].Type in GenC.gDynamicExPcd) or \\r
+                           (Pcd_Type == TAB_PCDS_DYNAMIC and self.Platform.Pcds[key].Type in GenC.gDynamicPcd):\r
+                            Value = self.Platform.Pcds[key]\r
+                            Value.TokenCName = self.Platform.Pcds[key].TokenCName + '_' + Pcd_Type\r
+                            if len(key) == 2:\r
+                                newkey = (Value.TokenCName, key[1])\r
+                            elif len(key) == 3:\r
+                                newkey = (Value.TokenCName, key[1], key[2])\r
+                            del self.Platform.Pcds[key]\r
+                            self.Platform.Pcds[newkey] = Value\r
+                            break\r
+                        else:\r
+                            pass\r
+                    break\r
+                else:\r
+                    pass\r
+\r
         # for gathering error information\r
         NoDatumTypePcdList = set()\r
         PcdNotInDb = []\r
@@ -1931,7 +2082,17 @@ class PlatformAutoGen(AutoGen):
         # at this point, ToPcd.Type has the type found from dependent\r
         # package\r
         #\r
+        TokenCName = ToPcd.TokenCName\r
+        for PcdItem in GlobalData.MixedPcd:\r
+            if (ToPcd.TokenCName, ToPcd.TokenSpaceGuidCName) in GlobalData.MixedPcd[PcdItem]:\r
+                TokenCName = PcdItem[0]\r
+                break\r
         if FromPcd != None:\r
+            if GlobalData.BuildOptionPcd:\r
+                for pcd in GlobalData.BuildOptionPcd:\r
+                    if (FromPcd.TokenSpaceGuidCName, FromPcd.TokenCName) == (pcd[0], pcd[1]):\r
+                        FromPcd.DefaultValue = pcd[2]\r
+                        break\r
             if ToPcd.Pending and FromPcd.Type not in [None, '']:\r
                 ToPcd.Type = FromPcd.Type\r
             elif (ToPcd.Type not in [None, '']) and (FromPcd.Type not in [None, ''])\\r
@@ -1942,7 +2103,7 @@ class PlatformAutoGen(AutoGen):
                 and ToPcd.Type != FromPcd.Type:\r
                 EdkLogger.error("build", OPTION_CONFLICT, "Mismatched PCD type",\r
                                 ExtraData="%s.%s is defined as [%s] in module %s, but as [%s] in platform."\\r
-                                          % (ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName,\r
+                                          % (ToPcd.TokenSpaceGuidCName, TokenCName,\r
                                              ToPcd.Type, Module, FromPcd.Type),\r
                                           File=self.MetaFile)\r
 \r
@@ -1963,14 +2124,14 @@ class PlatformAutoGen(AutoGen):
             IsValid, Cause = CheckPcdDatum(ToPcd.DatumType, ToPcd.DefaultValue)\r
             if not IsValid:\r
                 EdkLogger.error('build', FORMAT_INVALID, Cause, File=self.MetaFile,\r
-                                ExtraData="%s.%s" % (ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName))\r
+                                ExtraData="%s.%s" % (ToPcd.TokenSpaceGuidCName, TokenCName))\r
             ToPcd.validateranges = FromPcd.validateranges\r
             ToPcd.validlists = FromPcd.validlists\r
             ToPcd.expressions = FromPcd.expressions\r
 \r
         if ToPcd.DatumType == "VOID*" and ToPcd.MaxDatumSize in ['', None]:\r
             EdkLogger.debug(EdkLogger.DEBUG_9, "No MaxDatumSize specified for PCD %s.%s" \\r
-                            % (ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName))\r
+                            % (ToPcd.TokenSpaceGuidCName, TokenCName))\r
             Value = ToPcd.DefaultValue\r
             if Value in [None, '']:\r
                 ToPcd.MaxDatumSize = '1'\r
@@ -3572,9 +3733,14 @@ class ModuleAutoGen(AutoGen):
                         )\r
         if PatchList:\r
             for PatchPcd in PatchList:\r
-                if PatchPcd[0] not in PatchablePcds:\r
+                if PatchPcd[0] in PatchablePcds:\r
+                    key = PatchPcd[0]\r
+                elif PatchPcd[0] + '_PatchableInModule' in PatchablePcds:\r
+                    key = PatchPcd[0] + '_PatchableInModule'\r
+                else:\r
                     continue\r
-                Pcd = PatchablePcds[PatchPcd[0]]\r
+                Pcd = PatchablePcds[key]\r
+                TokenCName = PatchPcd[0]\r
                 PcdValue = ''\r
                 if Pcd.DatumType != 'VOID*':\r
                     HexFormat = '0x%02x'\r
@@ -3588,7 +3754,7 @@ class ModuleAutoGen(AutoGen):
                 else:\r
                     if Pcd.MaxDatumSize == None or Pcd.MaxDatumSize == '':\r
                         EdkLogger.error("build", AUTOGEN_ERROR,\r
-                                        "Unknown [MaxDatumSize] of PCD [%s.%s]" % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName)\r
+                                        "Unknown [MaxDatumSize] of PCD [%s.%s]" % (Pcd.TokenSpaceGuidCName, TokenCName)\r
                                         )\r
                     ArraySize = int(Pcd.MaxDatumSize, 0)\r
                     PcdValue = Pcd.DefaultValue\r
@@ -3612,7 +3778,7 @@ class ModuleAutoGen(AutoGen):
                             ArraySize = ArraySize / 2\r
                         if ArraySize < (len(PcdValue) + 1):\r
                             EdkLogger.error("build", AUTOGEN_ERROR,\r
-                                            "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName)\r
+                                            "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd.TokenSpaceGuidCName, TokenCName)\r
                                             )\r
                         if ArraySize > len(PcdValue) + 1:\r
                             NewValue = NewValue + Padding * (ArraySize - len(PcdValue) - 1)\r
@@ -3622,10 +3788,10 @@ class ModuleAutoGen(AutoGen):
                         PcdValue += '}'\r
                     else:\r
                         EdkLogger.error("build", AUTOGEN_ERROR,\r
-                                        "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName)\r
+                                        "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd.TokenSpaceGuidCName, TokenCName)\r
                                         )\r
                 PcdItem = '%s.%s|%s|0x%X' % \\r
-                    (Pcd.TokenSpaceGuidCName, Pcd.TokenCName, PcdValue, PatchPcd[1])\r
+                    (Pcd.TokenSpaceGuidCName, TokenCName, PcdValue, PatchPcd[1])\r
                 PcdComments = ''\r
                 if (Pcd.TokenSpaceGuidCName, Pcd.TokenCName) in self._PcdComments:\r
                     PcdComments = '\n  '.join(self._PcdComments[Pcd.TokenSpaceGuidCName, Pcd.TokenCName])\r
@@ -3639,6 +3805,11 @@ class ModuleAutoGen(AutoGen):
             PcdCommentList = []\r
             HiiInfo = ''\r
             SkuId = ''\r
+            TokenCName = Pcd.TokenCName\r
+            for PcdItem in GlobalData.MixedPcd:\r
+                if (Pcd.TokenCName, Pcd.TokenSpaceGuidCName) in GlobalData.MixedPcd[PcdItem]:\r
+                    TokenCName = PcdItem[0]\r
+                    break\r
             if Pcd.Type == TAB_PCDS_DYNAMIC_EX_HII:\r
                 for SkuName in Pcd.SkuInfoList:\r
                     SkuInfo = Pcd.SkuInfoList[SkuName]\r
@@ -3669,7 +3840,7 @@ class ModuleAutoGen(AutoGen):
                 else:\r
                     PcdCommentList.append('## UNDEFINED ' + HiiInfo)\r
             PcdComments = '\n  '.join(PcdCommentList)\r
-            PcdEntry = Pcd.TokenSpaceGuidCName + '.' + Pcd.TokenCName\r
+            PcdEntry = Pcd.TokenSpaceGuidCName + '.' + TokenCName\r
             if PcdComments:\r
                 PcdEntry = PcdComments + '\n  ' + PcdEntry\r
             AsBuiltInfDict['pcd_item'] += [PcdEntry]\r