]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/Python/Common/VpdInfoFile.py
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / BaseTools / Source / Python / Common / VpdInfoFile.py
index 18f6f5663c51d4386269988ade67e0e00c1a270e..1e0c3dfe76830b8460315b89877cdec14850c011 100644 (file)
@@ -1,25 +1,24 @@
 ## @file\r
-# \r
+#\r
 # This package manage the VPD PCD information file which will be generated\r
 # by build tool's autogen.\r
 # The VPD PCD information file will be input for third-party BPDG tool which\r
-# is pointed by *_*_*_VPD_TOOL_GUID in conf/tools_def.txt \r
-#\r
+# is pointed by *_*_*_VPD_TOOL_GUID in conf/tools_def.txt\r
 #\r
-# Copyright (c) 2010, 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
 #\r
-# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+# Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>\r
+# SPDX-License-Identifier: BSD-2-Clause-Patent\r
 #\r
-import os\r
+from __future__ import print_function\r
+import Common.LongFilePathOs as os\r
 import re\r
 import Common.EdkLogger as EdkLogger\r
 import Common.BuildToolError as BuildToolError\r
 import subprocess\r
+import Common.GlobalData as GlobalData\r
+from Common.LongFilePathSupport import OpenLongFilePath as open\r
+from Common.Misc import SaveFileOnChange\r
+from Common.DataType import *\r
 \r
 FILE_COMMENT_TEMPLATE = \\r
 """\r
@@ -28,8 +27,8 @@ FILE_COMMENT_TEMPLATE = \
 #  THIS IS AUTO-GENERATED FILE BY BUILD TOOLS AND PLEASE DO NOT MAKE MODIFICATION.\r
 #\r
 #  This file lists all VPD informations for a platform collected by build.exe.\r
-# \r
-# Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+#\r
+# Copyright (c) 2010 - 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
@@ -52,7 +51,7 @@ FILE_COMMENT_TEMPLATE = \
 #  <PcdName>         ::=  <TokenSpaceCName> "." <PcdCName>\r
 #  <TokenSpaceCName> ::=  C Variable Name of the Token Space GUID\r
 #  <PcdCName>        ::=  C Variable Name of the PCD\r
-#  <Offset>          ::=  {"*"} {<HexNumber>}\r
+#  <Offset>          ::=  {TAB_STAR} {<HexNumber>}\r
 #  <HexNumber>       ::=  "0x" (a-fA-F0-9){1,8}\r
 #  <Size>            ::=  <HexNumber>\r
 #  <Value>           ::=  {<HexNumber>} {<NonNegativeInt>} {<QString>} {<Array>}\r
@@ -64,19 +63,18 @@ FILE_COMMENT_TEMPLATE = \
 #  <NList>           ::=  <HexNumber> ["," <HexNumber>]*\r
 #\r
 class VpdInfoFile:\r
-    \r
-    ## The mapping dictionary from datum type to size string.\r
-    _MAX_SIZE_TYPE = {"BOOLEAN":"1", "UINT8":"1", "UINT16":"2", "UINT32":"4", "UINT64":"8"}\r
-    _rVpdPcdLine = None \r
+\r
+    _rVpdPcdLine = None\r
     ## Constructor\r
     def __init__(self):\r
         ## Dictionary for VPD in following format\r
         #\r
-        #  Key    : PcdClassObject instance. \r
+        #  Key    : PcdClassObject instance.\r
         #           @see BuildClassObject.PcdClassObject\r
         #  Value  : offset in different SKU such as [sku1_offset, sku2_offset]\r
         self._VpdArray = {}\r
-    \r
+        self._VpdInfo = {}\r
+\r
     ## Add a VPD PCD collected from platform's autogen when building.\r
     #\r
     #  @param vpds  The list of VPD PCD collected for a platform.\r
@@ -84,73 +82,61 @@ class VpdInfoFile:
     #\r
     #  @param offset integer value for VPD's offset in specific SKU.\r
     #\r
-    def Add(self, Vpd, Offset):\r
-        if (Vpd == None):\r
+    def Add(self, Vpd, skuname, Offset):\r
+        if (Vpd is None):\r
             EdkLogger.error("VpdInfoFile", BuildToolError.ATTRIBUTE_UNKNOWN_ERROR, "Invalid VPD PCD entry.")\r
-        \r
-        if not (Offset >= 0 or Offset == "*"):\r
+\r
+        if not (Offset >= "0" or Offset == TAB_STAR):\r
             EdkLogger.error("VpdInfoFile", BuildToolError.PARAMETER_INVALID, "Invalid offset parameter: %s." % Offset)\r
-        \r
-        if Vpd.DatumType == "VOID*":\r
-            if Vpd.MaxDatumSize <= 0:\r
-                EdkLogger.error("VpdInfoFile", BuildToolError.PARAMETER_INVALID, \r
+\r
+        if Vpd.DatumType == TAB_VOID:\r
+            if Vpd.MaxDatumSize <= "0":\r
+                EdkLogger.error("VpdInfoFile", BuildToolError.PARAMETER_INVALID,\r
                                 "Invalid max datum size for VPD PCD %s.%s" % (Vpd.TokenSpaceGuidCName, Vpd.TokenCName))\r
-        elif Vpd.DatumType in ["BOOLEAN", "UINT8", "UINT16", "UINT32", "UINT64"]: \r
-            if Vpd.MaxDatumSize == None or Vpd.MaxDatumSize == "":\r
-                Vpd.MaxDatumSize = VpdInfoFile._MAX_SIZE_TYPE[Vpd.DatumType]\r
-        else:\r
-            EdkLogger.error("VpdInfoFile", BuildToolError.PARAMETER_INVALID,  \r
-                            "Invalid DatumType %s for VPD PCD %s.%s" % (Vpd.DatumType, Vpd.TokenSpaceGuidCName, Vpd.TokenCName))\r
-            \r
-        if Vpd not in self._VpdArray.keys():\r
-            #\r
-            # If there is no Vpd instance in dict, that imply this offset for a given SKU is a new one \r
-            #\r
-            self._VpdArray[Vpd] = [Offset]\r
+        elif Vpd.DatumType in TAB_PCD_NUMERIC_TYPES:\r
+            if not Vpd.MaxDatumSize:\r
+                Vpd.MaxDatumSize = MAX_SIZE_TYPE[Vpd.DatumType]\r
         else:\r
+            if Vpd.MaxDatumSize <= "0":\r
+                EdkLogger.error("VpdInfoFile", BuildToolError.PARAMETER_INVALID,\r
+                                "Invalid max datum size for VPD PCD %s.%s" % (Vpd.TokenSpaceGuidCName, Vpd.TokenCName))\r
+\r
+        if Vpd not in self._VpdArray:\r
             #\r
-            # If there is an offset for a specific SKU in dict, then append this offset for other sku to array.\r
+            # If there is no Vpd instance in dict, that imply this offset for a given SKU is a new one\r
             #\r
-            self._VpdArray[Vpd].append(Offset)\r
-            \r
-        \r
+            self._VpdArray[Vpd] = {}\r
+\r
+        self._VpdArray[Vpd].update({skuname:Offset})\r
+\r
+\r
     ## Generate VPD PCD information into a text file\r
-    #  \r
+    #\r
     #  If parameter FilePath is invalid, then assert.\r
-    #  If \r
+    #  If\r
     #  @param FilePath        The given file path which would hold VPD information\r
     def Write(self, FilePath):\r
-        if not (FilePath != None or len(FilePath) != 0):\r
-            EdkLogger.error("VpdInfoFile", BuildToolError.PARAMETER_INVALID,  \r
-                            "Invalid parameter FilePath: %s." % FilePath)        \r
-        try:\r
-            fd = open(FilePath, "w")\r
-        except:\r
-            EdkLogger.error("VpdInfoFile", \r
-                            BuildToolError.FILE_OPEN_FAILURE, \r
-                            "Fail to open file %s for written." % FilePath)\r
-        \r
-        try:\r
-            # write file header\r
-            fd.write(FILE_COMMENT_TEMPLATE)\r
+        if not (FilePath is not None or len(FilePath) != 0):\r
+            EdkLogger.error("VpdInfoFile", BuildToolError.PARAMETER_INVALID,\r
+                            "Invalid parameter FilePath: %s." % FilePath)\r
 \r
-            # write each of PCD in VPD type\r
-            Pcds = self._VpdArray.keys()\r
-            Pcds.sort()\r
-            for Pcd in Pcds:\r
-                i = 0\r
-                for Offset in self._VpdArray[Pcd]:\r
-                    PcdValue = str(Pcd.SkuInfoList[Pcd.SkuInfoList.keys()[i]].DefaultValue).strip()\r
-                    if PcdValue == "" :\r
-                        PcdValue  = Pcd.DefaultValue\r
-                        \r
-                    fd.write("%s.%s|%s|%s|%s|%s  \n" % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName, str(Pcd.SkuInfoList.keys()[i]),str(Offset).strip(), str(Pcd.MaxDatumSize).strip(),PcdValue))\r
-                    i += 1\r
-        except:\r
-            EdkLogger.error("VpdInfoFile",\r
-                            BuildToolError.FILE_WRITE_FAILURE,\r
-                            "Fail to write file %s" % FilePath) \r
-        fd.close()\r
+        Content = FILE_COMMENT_TEMPLATE\r
+        Pcds = sorted(self._VpdArray.keys(), key=lambda x: x.TokenCName)\r
+        for Pcd in Pcds:\r
+            i = 0\r
+            PcdTokenCName = Pcd.TokenCName\r
+            for PcdItem in GlobalData.MixedPcd:\r
+                if (Pcd.TokenCName, Pcd.TokenSpaceGuidCName) in GlobalData.MixedPcd[PcdItem]:\r
+                    PcdTokenCName = PcdItem[0]\r
+            for skuname in self._VpdArray[Pcd]:\r
+                PcdValue = str(Pcd.SkuInfoList[skuname].DefaultValue).strip()\r
+                if PcdValue == "" :\r
+                    PcdValue  = Pcd.DefaultValue\r
+\r
+                Content += "%s.%s|%s|%s|%s|%s  \n" % (Pcd.TokenSpaceGuidCName, PcdTokenCName, skuname, str(self._VpdArray[Pcd][skuname]).strip(), str(Pcd.MaxDatumSize).strip(), PcdValue)\r
+                i += 1\r
+\r
+        return SaveFileOnChange(FilePath, Content, False)\r
 \r
     ## Read an existing VPD PCD info file.\r
     #\r
@@ -163,97 +149,107 @@ class VpdInfoFile:
         try:\r
             fd = open(FilePath, "r")\r
         except:\r
-            EdkLogger.error("VpdInfoFile", \r
-                            BuildToolError.FILE_OPEN_FAILURE, \r
+            EdkLogger.error("VpdInfoFile",\r
+                            BuildToolError.FILE_OPEN_FAILURE,\r
                             "Fail to open file %s for written." % FilePath)\r
         Lines = fd.readlines()\r
         for Line in Lines:\r
             Line = Line.strip()\r
             if len(Line) == 0 or Line.startswith("#"):\r
                 continue\r
-            \r
+\r
             #\r
             # the line must follow output format defined in BPDG spec.\r
             #\r
             try:\r
-                PcdName, SkuId,Offset, Size, Value = Line.split("#")[0].split("|")\r
-                PcdName, SkuId,Offset, Size, Value = PcdName.strip(), SkuId.strip(),Offset.strip(), Size.strip(), Value.strip()\r
+                PcdName, SkuId, Offset, Size, Value = Line.split("#")[0].split("|")\r
+                PcdName, SkuId, Offset, Size, Value = PcdName.strip(), SkuId.strip(), Offset.strip(), Size.strip(), Value.strip()\r
                 TokenSpaceName, PcdTokenName = PcdName.split(".")\r
             except:\r
                 EdkLogger.error("BPDG", BuildToolError.PARSER_ERROR, "Fail to parse VPD information file %s" % FilePath)\r
-            \r
+\r
             Found = False\r
-            \r
-            for VpdObject in self._VpdArray.keys():\r
-                for sku in VpdObject.SkuInfoList.keys(): \r
-                    if VpdObject.TokenSpaceGuidCName == TokenSpaceName and VpdObject.TokenCName == PcdTokenName.strip() and sku == SkuId:\r
-                        if self._VpdArray[VpdObject][VpdObject.SkuInfoList.keys().index(sku)] == "*":\r
-                            if Offset == "*":\r
-                                EdkLogger.error("BPDG", BuildToolError.FORMAT_INVALID, "The offset of %s has not been fixed up by third-party BPDG tool." % PcdName)                              \r
-                            self._VpdArray[VpdObject][VpdObject.SkuInfoList.keys().index(sku)] = Offset\r
+\r
+            if (TokenSpaceName, PcdTokenName) not in self._VpdInfo:\r
+                self._VpdInfo[(TokenSpaceName, PcdTokenName)] = {}\r
+            self._VpdInfo[(TokenSpaceName, PcdTokenName)][(SkuId, Offset)] = Value\r
+            for VpdObject in self._VpdArray:\r
+                VpdObjectTokenCName = VpdObject.TokenCName\r
+                for PcdItem in GlobalData.MixedPcd:\r
+                    if (VpdObject.TokenCName, VpdObject.TokenSpaceGuidCName) in GlobalData.MixedPcd[PcdItem]:\r
+                        VpdObjectTokenCName = PcdItem[0]\r
+                for sku in VpdObject.SkuInfoList:\r
+                    if VpdObject.TokenSpaceGuidCName == TokenSpaceName and VpdObjectTokenCName == PcdTokenName.strip() and sku == SkuId:\r
+                        if self._VpdArray[VpdObject][sku] == TAB_STAR:\r
+                            if Offset == TAB_STAR:\r
+                                EdkLogger.error("BPDG", BuildToolError.FORMAT_INVALID, "The offset of %s has not been fixed up by third-party BPDG tool." % PcdName)\r
+                            self._VpdArray[VpdObject][sku] = Offset\r
                         Found = True\r
             if not Found:\r
                 EdkLogger.error("BPDG", BuildToolError.PARSER_ERROR, "Can not find PCD defined in VPD guid file.")\r
-                \r
+\r
     ## Get count of VPD PCD collected from platform's autogen when building.\r
     #\r
-    #  @return The integer count value \r
+    #  @return The integer count value\r
     def GetCount(self):\r
         Count = 0\r
         for OffsetList in self._VpdArray.values():\r
             Count += len(OffsetList)\r
-            \r
+\r
         return Count\r
-    \r
+\r
     ## Get an offset value for a given VPD PCD\r
     #\r
-    #  Because BPDG only support one Sku, so only return offset for SKU default.   \r
+    #  Because BPDG only support one Sku, so only return offset for SKU default.\r
     #\r
-    #  @param vpd    A given VPD PCD \r
+    #  @param vpd    A given VPD PCD\r
     def GetOffset(self, vpd):\r
-        if not self._VpdArray.has_key(vpd):\r
+        if vpd not in self._VpdArray:\r
             return None\r
-        \r
+\r
         if len(self._VpdArray[vpd]) == 0:\r
             return None\r
-        \r
+\r
         return self._VpdArray[vpd]\r
-    \r
+    def GetVpdInfo(self, arg):\r
+        (PcdTokenName, TokenSpaceName) = arg\r
+        return [(sku,offset,value) for (sku,offset),value in self._VpdInfo.get((TokenSpaceName, PcdTokenName)).items()]\r
+\r
 ## Call external BPDG tool to process VPD file\r
-#    \r
+#\r
 #  @param ToolPath      The string path name for BPDG tool\r
 #  @param VpdFileName   The string path name for VPD information guid.txt\r
-# \r
+#\r
 def CallExtenalBPDGTool(ToolPath, VpdFileName):\r
-    assert ToolPath != None, "Invalid parameter ToolPath"\r
-    assert VpdFileName != None and os.path.exists(VpdFileName), "Invalid parameter VpdFileName"\r
-    \r
+    assert ToolPath is not None, "Invalid parameter ToolPath"\r
+    assert VpdFileName is not None and os.path.exists(VpdFileName), "Invalid parameter VpdFileName"\r
+\r
     OutputDir = os.path.dirname(VpdFileName)\r
     FileName = os.path.basename(VpdFileName)\r
     BaseName, ext = os.path.splitext(FileName)\r
     OutputMapFileName = os.path.join(OutputDir, "%s.map" % BaseName)\r
     OutputBinFileName = os.path.join(OutputDir, "%s.bin" % BaseName)\r
-          \r
+\r
     try:\r
-        PopenObject = subprocess.Popen([ToolPath,\r
-                                        '-o', OutputBinFileName, \r
+        PopenObject = subprocess.Popen(' '.join([ToolPath,\r
+                                        '-o', OutputBinFileName,\r
                                         '-m', OutputMapFileName,\r
                                         '-q',\r
                                         '-f',\r
-                                        VpdFileName],\r
-                                        stdout=subprocess.PIPE, \r
-                                        stderr= subprocess.PIPE)\r
-    except Exception, X:\r
-        EdkLogger.error("BPDG", BuildToolError.COMMAND_FAILURE, ExtraData="%s" % (str(X)))\r
+                                        VpdFileName]),\r
+                                        stdout=subprocess.PIPE,\r
+                                        stderr= subprocess.PIPE,\r
+                                        shell=True)\r
+    except Exception as X:\r
+        EdkLogger.error("BPDG", BuildToolError.COMMAND_FAILURE, ExtraData=str(X))\r
     (out, error) = PopenObject.communicate()\r
-    print out\r
-    while PopenObject.returncode == None :\r
+    print(out.decode())\r
+    while PopenObject.returncode is None :\r
         PopenObject.wait()\r
-    \r
+\r
     if PopenObject.returncode != 0:\r
-        if PopenObject.returncode != 0:\r
-            EdkLogger.debug(EdkLogger.DEBUG_1, "Fail to call BPDG tool", str(error))\r
-            EdkLogger.error("BPDG", BuildToolError.COMMAND_FAILURE, "Fail to execute BPDG tool with exit code: %d, the error message is: \n %s" % \\r
-                            (PopenObject.returncode, str(error)))\r
-        \r
+        EdkLogger.debug(EdkLogger.DEBUG_1, "Fail to call BPDG tool", str(error.decode()))\r
+        EdkLogger.error("BPDG", BuildToolError.COMMAND_FAILURE, "Fail to execute BPDG tool with exit code: %d, the error message is: \n %s" % \\r
+                            (PopenObject.returncode, str(error.decode())))\r
+\r
     return PopenObject.returncode\r