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