]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/Python/Common/VpdInfoFile.py
BaseTools/Tests: Update GNUmakefile to use python3 variable
[mirror_edk2.git] / BaseTools / Source / Python / Common / VpdInfoFile.py
CommitLineData
e56468c0 1## @file\r
f7496d71 2#\r
e56468c0 3# This package manage the VPD PCD information file which will be generated\r
4# by build tool's autogen.\r
5# The VPD PCD information file will be input for third-party BPDG tool which\r
f7496d71 6# is pointed by *_*_*_VPD_TOOL_GUID in conf/tools_def.txt\r
e56468c0 7#\r
8#\r
9eb87141 9# Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>\r
e56468c0 10# This program and the accompanying materials\r
11# are licensed and made available under the terms and conditions of the BSD License\r
12# which accompanies this distribution. The full text of the license may be found at\r
13# http://opensource.org/licenses/bsd-license.php\r
14#\r
15# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
16# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
17#\r
1be2ed90 18import Common.LongFilePathOs as os\r
e56468c0 19import re\r
20import Common.EdkLogger as EdkLogger\r
21import Common.BuildToolError as BuildToolError\r
22import subprocess\r
2a29017e 23import Common.GlobalData as GlobalData\r
1be2ed90 24from Common.LongFilePathSupport import OpenLongFilePath as open\r
e459de78 25from Common.Misc import SaveFileOnChange\r
25598f8b 26from Common.DataType import *\r
e56468c0 27\r
28FILE_COMMENT_TEMPLATE = \\r
29"""\r
30## @file\r
31#\r
32# THIS IS AUTO-GENERATED FILE BY BUILD TOOLS AND PLEASE DO NOT MAKE MODIFICATION.\r
33#\r
34# This file lists all VPD informations for a platform collected by build.exe.\r
f7496d71
LG
35#\r
36# Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>\r
e56468c0 37# This program and the accompanying materials\r
38# are licensed and made available under the terms and conditions of the BSD License\r
39# which accompanies this distribution. The full text of the license may be found at\r
40# http://opensource.org/licenses/bsd-license.php\r
41#\r
42# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
43# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
44#\r
45\r
46"""\r
47\r
48## The class manage VpdInfoFile.\r
49#\r
50# This file contains an ordered (based on position in the DSC file) list of the PCDs specified in the platform description file (DSC). The Value field that will be assigned to the PCD comes from the DSC file, INF file (if not defined in the DSC file) or the DEC file (if not defined in the INF file). This file is used as an input to the BPDG tool.\r
51# Format for this file (using EBNF notation) is:\r
52# <File> :: = [<CommentBlock>]\r
53# [<PcdEntry>]*\r
54# <CommentBlock> ::= ["#" <String> <EOL>]*\r
55# <PcdEntry> ::= <PcdName> "|" <Offset> "|" <Size> "|" <Value> <EOL>\r
56# <PcdName> ::= <TokenSpaceCName> "." <PcdCName>\r
57# <TokenSpaceCName> ::= C Variable Name of the Token Space GUID\r
58# <PcdCName> ::= C Variable Name of the PCD\r
59# <Offset> ::= {"*"} {<HexNumber>}\r
60# <HexNumber> ::= "0x" (a-fA-F0-9){1,8}\r
61# <Size> ::= <HexNumber>\r
62# <Value> ::= {<HexNumber>} {<NonNegativeInt>} {<QString>} {<Array>}\r
63# <NonNegativeInt> ::= (0-9)+\r
64# <QString> ::= ["L"] <DblQuote> <String> <DblQuote>\r
65# <DblQuote> ::= 0x22\r
66# <Array> ::= {<CArray>} {<NList>}\r
67# <CArray> ::= "{" <HexNumber> ["," <HexNumber>]* "}"\r
68# <NList> ::= <HexNumber> ["," <HexNumber>]*\r
69#\r
70class VpdInfoFile:\r
25598f8b 71\r
f7496d71 72 _rVpdPcdLine = None\r
e56468c0 73 ## Constructor\r
74 def __init__(self):\r
75 ## Dictionary for VPD in following format\r
76 #\r
f7496d71 77 # Key : PcdClassObject instance.\r
e56468c0 78 # @see BuildClassObject.PcdClassObject\r
79 # Value : offset in different SKU such as [sku1_offset, sku2_offset]\r
80 self._VpdArray = {}\r
626bece4 81 self._VpdInfo = {}\r
f7496d71 82\r
e56468c0 83 ## Add a VPD PCD collected from platform's autogen when building.\r
84 #\r
85 # @param vpds The list of VPD PCD collected for a platform.\r
86 # @see BuildClassObject.PcdClassObject\r
87 #\r
88 # @param offset integer value for VPD's offset in specific SKU.\r
89 #\r
ccaa7754 90 def Add(self, Vpd, skuname, Offset):\r
4231a819 91 if (Vpd is None):\r
e56468c0 92 EdkLogger.error("VpdInfoFile", BuildToolError.ATTRIBUTE_UNKNOWN_ERROR, "Invalid VPD PCD entry.")\r
f7496d71 93\r
86e6cf98 94 if not (Offset >= "0" or Offset == "*"):\r
e56468c0 95 EdkLogger.error("VpdInfoFile", BuildToolError.PARAMETER_INVALID, "Invalid offset parameter: %s." % Offset)\r
f7496d71 96\r
656d2539 97 if Vpd.DatumType == TAB_VOID:\r
86e6cf98 98 if Vpd.MaxDatumSize <= "0":\r
f7496d71 99 EdkLogger.error("VpdInfoFile", BuildToolError.PARAMETER_INVALID,\r
e56468c0 100 "Invalid max datum size for VPD PCD %s.%s" % (Vpd.TokenSpaceGuidCName, Vpd.TokenCName))\r
f7496d71 101 elif Vpd.DatumType in TAB_PCD_NUMERIC_TYPES:\r
5565a8c4 102 if not Vpd.MaxDatumSize:\r
25598f8b 103 Vpd.MaxDatumSize = MAX_SIZE_TYPE[Vpd.DatumType]\r
e56468c0 104 else:\r
86e6cf98 105 if Vpd.MaxDatumSize <= "0":\r
2b8a6c44
LG
106 EdkLogger.error("VpdInfoFile", BuildToolError.PARAMETER_INVALID,\r
107 "Invalid max datum size for VPD PCD %s.%s" % (Vpd.TokenSpaceGuidCName, Vpd.TokenCName))\r
f7496d71 108\r
9eb87141 109 if Vpd not in self._VpdArray:\r
e56468c0 110 #\r
f7496d71 111 # If there is no Vpd instance in dict, that imply this offset for a given SKU is a new one\r
e56468c0 112 #\r
8ac16789
LG
113 self._VpdArray[Vpd] = {}\r
114\r
115 self._VpdArray[Vpd].update({skuname:Offset})\r
f7496d71
LG
116\r
117\r
e56468c0 118 ## Generate VPD PCD information into a text file\r
f7496d71 119 #\r
e56468c0 120 # If parameter FilePath is invalid, then assert.\r
f7496d71 121 # If\r
e56468c0 122 # @param FilePath The given file path which would hold VPD information\r
123 def Write(self, FilePath):\r
4231a819 124 if not (FilePath is not None or len(FilePath) != 0):\r
f7496d71
LG
125 EdkLogger.error("VpdInfoFile", BuildToolError.PARAMETER_INVALID,\r
126 "Invalid parameter FilePath: %s." % FilePath)\r
e56468c0 127\r
e459de78 128 Content = FILE_COMMENT_TEMPLATE\r
86e6cf98 129 Pcds = sorted(self._VpdArray.keys(), key=lambda x: x.TokenCName)\r
e459de78
YZ
130 for Pcd in Pcds:\r
131 i = 0\r
2a29017e
YZ
132 PcdTokenCName = Pcd.TokenCName\r
133 for PcdItem in GlobalData.MixedPcd:\r
134 if (Pcd.TokenCName, Pcd.TokenSpaceGuidCName) in GlobalData.MixedPcd[PcdItem]:\r
135 PcdTokenCName = PcdItem[0]\r
8ac16789
LG
136 for skuname in self._VpdArray[Pcd]:\r
137 PcdValue = str(Pcd.SkuInfoList[skuname].DefaultValue).strip()\r
e459de78
YZ
138 if PcdValue == "" :\r
139 PcdValue = Pcd.DefaultValue\r
140\r
ccaa7754 141 Content += "%s.%s|%s|%s|%s|%s \n" % (Pcd.TokenSpaceGuidCName, PcdTokenCName, skuname, str(self._VpdArray[Pcd][skuname]).strip(), str(Pcd.MaxDatumSize).strip(), PcdValue)\r
e459de78
YZ
142 i += 1\r
143\r
144 return SaveFileOnChange(FilePath, Content, False)\r
e56468c0 145\r
146 ## Read an existing VPD PCD info file.\r
147 #\r
148 # This routine will read VPD PCD information from existing file and construct\r
149 # internal PcdClassObject array.\r
150 # This routine could be used by third-party tool to parse VPD info file content.\r
151 #\r
152 # @param FilePath The full path string for existing VPD PCD info file.\r
153 def Read(self, FilePath):\r
154 try:\r
155 fd = open(FilePath, "r")\r
156 except:\r
f7496d71
LG
157 EdkLogger.error("VpdInfoFile",\r
158 BuildToolError.FILE_OPEN_FAILURE,\r
e56468c0 159 "Fail to open file %s for written." % FilePath)\r
160 Lines = fd.readlines()\r
161 for Line in Lines:\r
162 Line = Line.strip()\r
163 if len(Line) == 0 or Line.startswith("#"):\r
164 continue\r
f7496d71 165\r
e56468c0 166 #\r
167 # the line must follow output format defined in BPDG spec.\r
168 #\r
169 try:\r
ccaa7754
GL
170 PcdName, SkuId, Offset, Size, Value = Line.split("#")[0].split("|")\r
171 PcdName, SkuId, Offset, Size, Value = PcdName.strip(), SkuId.strip(), Offset.strip(), Size.strip(), Value.strip()\r
e56468c0 172 TokenSpaceName, PcdTokenName = PcdName.split(".")\r
173 except:\r
174 EdkLogger.error("BPDG", BuildToolError.PARSER_ERROR, "Fail to parse VPD information file %s" % FilePath)\r
f7496d71 175\r
e56468c0 176 Found = False\r
f7496d71 177\r
626bece4
LG
178 if (TokenSpaceName, PcdTokenName) not in self._VpdInfo:\r
179 self._VpdInfo[(TokenSpaceName, PcdTokenName)] = []\r
ccaa7754 180 self._VpdInfo[(TokenSpaceName, PcdTokenName)].append((SkuId, Offset, Value))\r
9eb87141 181 for VpdObject in self._VpdArray:\r
2a29017e
YZ
182 VpdObjectTokenCName = VpdObject.TokenCName\r
183 for PcdItem in GlobalData.MixedPcd:\r
184 if (VpdObject.TokenCName, VpdObject.TokenSpaceGuidCName) in GlobalData.MixedPcd[PcdItem]:\r
185 VpdObjectTokenCName = PcdItem[0]\r
9eb87141 186 for sku in VpdObject.SkuInfoList:\r
2a29017e 187 if VpdObject.TokenSpaceGuidCName == TokenSpaceName and VpdObjectTokenCName == PcdTokenName.strip() and sku == SkuId:\r
8ac16789 188 if self._VpdArray[VpdObject][sku] == "*":\r
e8a47801 189 if Offset == "*":\r
f7496d71 190 EdkLogger.error("BPDG", BuildToolError.FORMAT_INVALID, "The offset of %s has not been fixed up by third-party BPDG tool." % PcdName)\r
8ac16789 191 self._VpdArray[VpdObject][sku] = Offset\r
e8a47801 192 Found = True\r
e56468c0 193 if not Found:\r
194 EdkLogger.error("BPDG", BuildToolError.PARSER_ERROR, "Can not find PCD defined in VPD guid file.")\r
f7496d71 195\r
e56468c0 196 ## Get count of VPD PCD collected from platform's autogen when building.\r
197 #\r
f7496d71 198 # @return The integer count value\r
e56468c0 199 def GetCount(self):\r
200 Count = 0\r
201 for OffsetList in self._VpdArray.values():\r
202 Count += len(OffsetList)\r
f7496d71 203\r
e56468c0 204 return Count\r
f7496d71 205\r
e56468c0 206 ## Get an offset value for a given VPD PCD\r
207 #\r
f7496d71 208 # Because BPDG only support one Sku, so only return offset for SKU default.\r
e56468c0 209 #\r
f7496d71 210 # @param vpd A given VPD PCD\r
e56468c0 211 def GetOffset(self, vpd):\r
27c4ceb4 212 if vpd not in self._VpdArray:\r
e56468c0 213 return None\r
f7496d71 214\r
e56468c0 215 if len(self._VpdArray[vpd]) == 0:\r
216 return None\r
f7496d71 217\r
e56468c0 218 return self._VpdArray[vpd]\r
890d8ede
GL
219 def GetVpdInfo(self, arg):\r
220 (PcdTokenName, TokenSpaceName) = arg\r
626bece4 221 return self._VpdInfo.get((TokenSpaceName, PcdTokenName))\r
f7496d71 222\r
e56468c0 223## Call external BPDG tool to process VPD file\r
f7496d71 224#\r
e56468c0 225# @param ToolPath The string path name for BPDG tool\r
226# @param VpdFileName The string path name for VPD information guid.txt\r
f7496d71 227#\r
08dd311f 228def CallExtenalBPDGTool(ToolPath, VpdFileName):\r
4231a819
CJ
229 assert ToolPath is not None, "Invalid parameter ToolPath"\r
230 assert VpdFileName is not None and os.path.exists(VpdFileName), "Invalid parameter VpdFileName"\r
f7496d71 231\r
08dd311f
LG
232 OutputDir = os.path.dirname(VpdFileName)\r
233 FileName = os.path.basename(VpdFileName)\r
234 BaseName, ext = os.path.splitext(FileName)\r
235 OutputMapFileName = os.path.join(OutputDir, "%s.map" % BaseName)\r
236 OutputBinFileName = os.path.join(OutputDir, "%s.bin" % BaseName)\r
f7496d71 237\r
e56468c0 238 try:\r
71f5913e 239 PopenObject = subprocess.Popen(' '.join([ToolPath,\r
f7496d71 240 '-o', OutputBinFileName,\r
e56468c0 241 '-m', OutputMapFileName,\r
08dd311f 242 '-q',\r
e56468c0 243 '-f',\r
71f5913e 244 VpdFileName]),\r
f7496d71 245 stdout=subprocess.PIPE,\r
71f5913e
LG
246 stderr= subprocess.PIPE,\r
247 shell=True)\r
5b0671c1 248 except Exception as X:\r
caf74495 249 EdkLogger.error("BPDG", BuildToolError.COMMAND_FAILURE, ExtraData=str(X))\r
e56468c0 250 (out, error) = PopenObject.communicate()\r
86e6cf98 251 print(out.decode(encoding='utf-8', errors='ignore'))\r
4231a819 252 while PopenObject.returncode is None :\r
e56468c0 253 PopenObject.wait()\r
f7496d71 254\r
e56468c0 255 if PopenObject.returncode != 0:\r
256 if PopenObject.returncode != 0:\r
257 EdkLogger.debug(EdkLogger.DEBUG_1, "Fail to call BPDG tool", str(error))\r
258 EdkLogger.error("BPDG", BuildToolError.COMMAND_FAILURE, "Fail to execute BPDG tool with exit code: %d, the error message is: \n %s" % \\r
259 (PopenObject.returncode, str(error)))\r
f7496d71 260\r
e56468c0 261 return PopenObject.returncode\r