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