]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/Python/PatchPcdValue/PatchPcdValue.py
BaseTools: change the Division Operator in the expression
[mirror_edk2.git] / BaseTools / Source / Python / PatchPcdValue / PatchPcdValue.py
CommitLineData
f51461c8
LG
1## @file\r
2# Patch value into the binary file.\r
3#\r
656d2539 4# Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>\r
f51461c8
LG
5# This program and the accompanying materials\r
6# are licensed and made available under the terms and conditions of the BSD License\r
7# which accompanies this distribution. The full text of the license may be found at\r
8# http://opensource.org/licenses/bsd-license.php\r
9#\r
10# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12#\r
13\r
14##\r
15# Import Modules\r
16#\r
1be2ed90
HC
17import Common.LongFilePathOs as os\r
18from Common.LongFilePathSupport import OpenLongFilePath as open\r
f51461c8
LG
19import sys\r
20import re\r
21\r
22from optparse import OptionParser\r
23from optparse import make_option\r
24from Common.BuildToolError import *\r
25import Common.EdkLogger as EdkLogger\r
26from Common.BuildVersion import gBUILD_VERSION\r
27import array\r
656d2539 28from Common.DataType import *\r
f51461c8
LG
29\r
30# Version and Copyright\r
31__version_number__ = ("0.10" + " " + gBUILD_VERSION)\r
32__version__ = "%prog Version " + __version_number__\r
f7496d71 33__copyright__ = "Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved."\r
f51461c8
LG
34\r
35## PatchBinaryFile method\r
36#\r
37# This method mainly patches the data into binary file.\r
f7496d71 38#\r
f51461c8 39# @param FileName File path of the binary file\r
f7496d71 40# @param ValueOffset Offset value\r
f51461c8
LG
41# @param TypeName DataType Name\r
42# @param Value Value String\r
43# @param MaxSize MaxSize value\r
44#\r
45# @retval 0 File is updated successfully.\r
46# @retval not 0 File is updated failed.\r
47#\r
48def PatchBinaryFile(FileName, ValueOffset, TypeName, ValueString, MaxSize=0):\r
49 #\r
50 # Length of Binary File\r
51 #\r
47fea6af 52 FileHandle = open(FileName, 'rb')\r
f51461c8
LG
53 FileHandle.seek (0, 2)\r
54 FileLength = FileHandle.tell()\r
55 FileHandle.close()\r
56 #\r
57 # Unify string to upper string\r
58 #\r
59 TypeName = TypeName.upper()\r
60 #\r
61 # Get PCD value data length\r
62 #\r
63 ValueLength = 0\r
64 if TypeName == 'BOOLEAN':\r
65 ValueLength = 1\r
656d2539 66 elif TypeName == TAB_UINT8:\r
f51461c8 67 ValueLength = 1\r
656d2539 68 elif TypeName == TAB_UINT16:\r
f51461c8 69 ValueLength = 2\r
656d2539 70 elif TypeName == TAB_UINT32:\r
f51461c8 71 ValueLength = 4\r
656d2539 72 elif TypeName == TAB_UINT64:\r
f51461c8 73 ValueLength = 8\r
656d2539 74 elif TypeName == TAB_VOID:\r
f51461c8
LG
75 if MaxSize == 0:\r
76 return OPTION_MISSING, "PcdMaxSize is not specified for VOID* type PCD."\r
77 ValueLength = int(MaxSize)\r
78 else:\r
47fea6af 79 return PARAMETER_INVALID, "PCD type %s is not valid." % (CommandOptions.PcdTypeName)\r
f51461c8
LG
80 #\r
81 # Check PcdValue is in the input binary file.\r
82 #\r
83 if ValueOffset + ValueLength > FileLength:\r
84 return PARAMETER_INVALID, "PcdOffset + PcdMaxSize(DataType) is larger than the input file size."\r
85 #\r
86 # Read binary file into array\r
87 #\r
47fea6af 88 FileHandle = open(FileName, 'rb')\r
f51461c8
LG
89 ByteArray = array.array('B')\r
90 ByteArray.fromfile(FileHandle, FileLength)\r
91 FileHandle.close()\r
92 OrigByteList = ByteArray.tolist()\r
93 ByteList = ByteArray.tolist()\r
94 #\r
95 # Clear the data in file\r
96 #\r
97 for Index in range(ValueLength):\r
98 ByteList[ValueOffset + Index] = 0\r
99 #\r
100 # Patch value into offset\r
101 #\r
102 SavedStr = ValueString\r
103 ValueString = ValueString.upper()\r
104 ValueNumber = 0\r
105 if TypeName == 'BOOLEAN':\r
106 #\r
107 # Get PCD value for BOOLEAN data type\r
108 #\r
109 try:\r
110 if ValueString == 'TRUE':\r
111 ValueNumber = 1\r
112 elif ValueString == 'FALSE':\r
113 ValueNumber = 0\r
0944818a 114 ValueNumber = int (ValueString, 0)\r
f51461c8
LG
115 if ValueNumber != 0:\r
116 ValueNumber = 1\r
117 except:\r
47fea6af 118 return PARAMETER_INVALID, "PCD Value %s is not valid dec or hex string." % (ValueString)\r
f51461c8
LG
119 #\r
120 # Set PCD value into binary data\r
121 #\r
122 ByteList[ValueOffset] = ValueNumber\r
656d2539 123 elif TypeName in TAB_PCD_CLEAN_NUMERIC_TYPES:\r
f51461c8
LG
124 #\r
125 # Get PCD value for UINT* data type\r
126 #\r
127 try:\r
0944818a 128 ValueNumber = int (ValueString, 0)\r
f51461c8 129 except:\r
47fea6af 130 return PARAMETER_INVALID, "PCD Value %s is not valid dec or hex string." % (ValueString)\r
f51461c8
LG
131 #\r
132 # Set PCD value into binary data\r
133 #\r
134 for Index in range(ValueLength):\r
135 ByteList[ValueOffset + Index] = ValueNumber % 0x100\r
2e300969 136 ValueNumber = ValueNumber // 0x100\r
656d2539 137 elif TypeName == TAB_VOID:\r
f51461c8
LG
138 ValueString = SavedStr\r
139 if ValueString.startswith('L"'):\r
140 #\r
141 # Patch Unicode String\r
142 #\r
143 Index = 0\r
144 for ByteString in ValueString[2:-1]:\r
145 #\r
146 # Reserve zero as unicode tail\r
147 #\r
148 if Index + 2 >= ValueLength:\r
149 break\r
150 #\r
151 # Set string value one by one\r
152 #\r
153 ByteList[ValueOffset + Index] = ord(ByteString)\r
154 Index = Index + 2\r
155 elif ValueString.startswith("{") and ValueString.endswith("}"):\r
156 #\r
157 # Patch {0x1, 0x2, ...} byte by byte\r
158 #\r
0537f332 159 ValueList = ValueString[1 : len(ValueString) - 1].split(',')\r
f51461c8
LG
160 Index = 0\r
161 try:\r
162 for ByteString in ValueList:\r
0537f332 163 ByteString = ByteString.strip()\r
f51461c8
LG
164 if ByteString.upper().startswith('0X'):\r
165 ByteValue = int(ByteString, 16)\r
166 else:\r
167 ByteValue = int(ByteString)\r
168 ByteList[ValueOffset + Index] = ByteValue % 0x100\r
169 Index = Index + 1\r
170 if Index >= ValueLength:\r
171 break\r
172 except:\r
47fea6af 173 return PARAMETER_INVALID, "PCD Value %s is not valid dec or hex string array." % (ValueString)\r
f51461c8
LG
174 else:\r
175 #\r
f7496d71 176 # Patch ascii string\r
f51461c8
LG
177 #\r
178 Index = 0\r
179 for ByteString in ValueString[1:-1]:\r
180 #\r
181 # Reserve zero as string tail\r
182 #\r
183 if Index + 1 >= ValueLength:\r
184 break\r
185 #\r
186 # Set string value one by one\r
187 #\r
188 ByteList[ValueOffset + Index] = ord(ByteString)\r
189 Index = Index + 1\r
190 #\r
191 # Update new data into input file.\r
192 #\r
193 if ByteList != OrigByteList:\r
194 ByteArray = array.array('B')\r
195 ByteArray.fromlist(ByteList)\r
47fea6af 196 FileHandle = open(FileName, 'wb')\r
f51461c8
LG
197 ByteArray.tofile(FileHandle)\r
198 FileHandle.close()\r
47fea6af 199 return 0, "Patch Value into File %s successfully." % (FileName)\r
f51461c8
LG
200\r
201## Parse command line options\r
202#\r
203# Using standard Python module optparse to parse command line option of this tool.\r
204#\r
205# @retval Options A optparse.Values object containing the parsed options\r
206# @retval InputFile Path of file to be trimmed\r
207#\r
208def Options():\r
209 OptionList = [\r
210 make_option("-f", "--offset", dest="PcdOffset", action="store", type="int",\r
211 help="Start offset to the image is used to store PCD value."),\r
212 make_option("-u", "--value", dest="PcdValue", action="store",\r
213 help="PCD value will be updated into the image."),\r
214 make_option("-t", "--type", dest="PcdTypeName", action="store",\r
215 help="The name of PCD data type may be one of VOID*,BOOLEAN, UINT8, UINT16, UINT32, UINT64."),\r
216 make_option("-s", "--maxsize", dest="PcdMaxSize", action="store", type="int",\r
217 help="Max size of data buffer is taken by PCD value.It must be set when PCD type is VOID*."),\r
218 make_option("-v", "--verbose", dest="LogLevel", action="store_const", const=EdkLogger.VERBOSE,\r
219 help="Run verbosely"),\r
220 make_option("-d", "--debug", dest="LogLevel", type="int",\r
221 help="Run with debug information"),\r
222 make_option("-q", "--quiet", dest="LogLevel", action="store_const", const=EdkLogger.QUIET,\r
223 help="Run quietly"),\r
224 make_option("-?", action="help", help="show this help message and exit"),\r
225 ]\r
226\r
227 # use clearer usage to override default usage message\r
228 UsageString = "%prog -f Offset -u Value -t Type [-s MaxSize] <input_file>"\r
229\r
230 Parser = OptionParser(description=__copyright__, version=__version__, option_list=OptionList, usage=UsageString)\r
231 Parser.set_defaults(LogLevel=EdkLogger.INFO)\r
232\r
233 Options, Args = Parser.parse_args()\r
234\r
235 # error check\r
236 if len(Args) == 0:\r
237 EdkLogger.error("PatchPcdValue", PARAMETER_INVALID, ExtraData=Parser.get_usage())\r
238\r
239 InputFile = Args[len(Args) - 1]\r
240 return Options, InputFile\r
241\r
242## Entrance method\r
243#\r
244# This method mainly dispatch specific methods per the command line options.\r
245# If no error found, return zero value so the caller of this tool can know\r
246# if it's executed successfully or not.\r
247#\r
248# @retval 0 Tool was successful\r
249# @retval 1 Tool failed\r
250#\r
251def Main():\r
252 try:\r
253 #\r
254 # Check input parameter\r
255 #\r
256 EdkLogger.Initialize()\r
257 CommandOptions, InputFile = Options()\r
258 if CommandOptions.LogLevel < EdkLogger.DEBUG_9:\r
259 EdkLogger.SetLevel(CommandOptions.LogLevel + 1)\r
260 else:\r
261 EdkLogger.SetLevel(CommandOptions.LogLevel)\r
262 if not os.path.exists (InputFile):\r
263 EdkLogger.error("PatchPcdValue", FILE_NOT_FOUND, ExtraData=InputFile)\r
264 return 1\r
4231a819 265 if CommandOptions.PcdOffset is None or CommandOptions.PcdValue is None or CommandOptions.PcdTypeName is None:\r
f51461c8
LG
266 EdkLogger.error("PatchPcdValue", OPTION_MISSING, ExtraData="PcdOffset or PcdValue of PcdTypeName is not specified.")\r
267 return 1\r
656d2539 268 if CommandOptions.PcdTypeName.upper() not in TAB_PCD_NUMERIC_TYPES_VOID:\r
47fea6af 269 EdkLogger.error("PatchPcdValue", PARAMETER_INVALID, ExtraData="PCD type %s is not valid." % (CommandOptions.PcdTypeName))\r
f51461c8 270 return 1\r
656d2539 271 if CommandOptions.PcdTypeName.upper() == TAB_VOID and CommandOptions.PcdMaxSize is None:\r
f51461c8
LG
272 EdkLogger.error("PatchPcdValue", OPTION_MISSING, ExtraData="PcdMaxSize is not specified for VOID* type PCD.")\r
273 return 1\r
274 #\r
275 # Patch value into binary image.\r
276 #\r
277 ReturnValue, ErrorInfo = PatchBinaryFile (InputFile, CommandOptions.PcdOffset, CommandOptions.PcdTypeName, CommandOptions.PcdValue, CommandOptions.PcdMaxSize)\r
278 if ReturnValue != 0:\r
279 EdkLogger.error("PatchPcdValue", ReturnValue, ExtraData=ErrorInfo)\r
280 return 1\r
281 return 0\r
282 except:\r
283 return 1\r
284\r
285if __name__ == '__main__':\r
286 r = Main()\r
287 sys.exit(r)\r