]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/Python/PatchPcdValue/PatchPcdValue.py
BaseTools: Replace BSD License with BSD+Patent License
[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
2e351cbe 5# SPDX-License-Identifier: BSD-2-Clause-Patent\r
f51461c8
LG
6#\r
7\r
8##\r
9# Import Modules\r
10#\r
1be2ed90
HC
11import Common.LongFilePathOs as os\r
12from Common.LongFilePathSupport import OpenLongFilePath as open\r
f51461c8
LG
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
656d2539 22from Common.DataType import *\r
f51461c8
LG
23\r
24# Version and Copyright\r
25__version_number__ = ("0.10" + " " + gBUILD_VERSION)\r
26__version__ = "%prog Version " + __version_number__\r
f7496d71 27__copyright__ = "Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved."\r
f51461c8
LG
28\r
29## PatchBinaryFile method\r
30#\r
31# This method mainly patches the data into binary file.\r
f7496d71 32#\r
f51461c8 33# @param FileName File path of the binary file\r
f7496d71 34# @param ValueOffset Offset value\r
f51461c8
LG
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
47fea6af 46 FileHandle = open(FileName, 'rb')\r
f51461c8
LG
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
656d2539 60 elif TypeName == TAB_UINT8:\r
f51461c8 61 ValueLength = 1\r
656d2539 62 elif TypeName == TAB_UINT16:\r
f51461c8 63 ValueLength = 2\r
656d2539 64 elif TypeName == TAB_UINT32:\r
f51461c8 65 ValueLength = 4\r
656d2539 66 elif TypeName == TAB_UINT64:\r
f51461c8 67 ValueLength = 8\r
656d2539 68 elif TypeName == TAB_VOID:\r
f51461c8
LG
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
47fea6af 73 return PARAMETER_INVALID, "PCD type %s is not valid." % (CommandOptions.PcdTypeName)\r
f51461c8
LG
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
47fea6af 82 FileHandle = open(FileName, 'rb')\r
f51461c8
LG
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
0944818a 108 ValueNumber = int (ValueString, 0)\r
f51461c8
LG
109 if ValueNumber != 0:\r
110 ValueNumber = 1\r
111 except:\r
47fea6af 112 return PARAMETER_INVALID, "PCD Value %s is not valid dec or hex string." % (ValueString)\r
f51461c8
LG
113 #\r
114 # Set PCD value into binary data\r
115 #\r
116 ByteList[ValueOffset] = ValueNumber\r
656d2539 117 elif TypeName in TAB_PCD_CLEAN_NUMERIC_TYPES:\r
f51461c8
LG
118 #\r
119 # Get PCD value for UINT* data type\r
120 #\r
121 try:\r
0944818a 122 ValueNumber = int (ValueString, 0)\r
f51461c8 123 except:\r
47fea6af 124 return PARAMETER_INVALID, "PCD Value %s is not valid dec or hex string." % (ValueString)\r
f51461c8
LG
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
b3e94a06 130 ValueNumber = ValueNumber // 0x100\r
656d2539 131 elif TypeName == TAB_VOID:\r
f51461c8
LG
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
b3e94a06 145 # Set string value one by one/ 0x100\r
f51461c8
LG
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
0537f332 153 ValueList = ValueString[1 : len(ValueString) - 1].split(',')\r
f51461c8
LG
154 Index = 0\r
155 try:\r
156 for ByteString in ValueList:\r
0537f332 157 ByteString = ByteString.strip()\r
f51461c8
LG
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
47fea6af 167 return PARAMETER_INVALID, "PCD Value %s is not valid dec or hex string array." % (ValueString)\r
f51461c8
LG
168 else:\r
169 #\r
f7496d71 170 # Patch ascii string\r
f51461c8
LG
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
47fea6af 190 FileHandle = open(FileName, 'wb')\r
f51461c8
LG
191 ByteArray.tofile(FileHandle)\r
192 FileHandle.close()\r
47fea6af 193 return 0, "Patch Value into File %s successfully." % (FileName)\r
f51461c8
LG
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
4231a819 259 if CommandOptions.PcdOffset is None or CommandOptions.PcdValue is None or CommandOptions.PcdTypeName is None:\r
f51461c8
LG
260 EdkLogger.error("PatchPcdValue", OPTION_MISSING, ExtraData="PcdOffset or PcdValue of PcdTypeName is not specified.")\r
261 return 1\r
656d2539 262 if CommandOptions.PcdTypeName.upper() not in TAB_PCD_NUMERIC_TYPES_VOID:\r
47fea6af 263 EdkLogger.error("PatchPcdValue", PARAMETER_INVALID, ExtraData="PCD type %s is not valid." % (CommandOptions.PcdTypeName))\r
f51461c8 264 return 1\r
656d2539 265 if CommandOptions.PcdTypeName.upper() == TAB_VOID and CommandOptions.PcdMaxSize is None:\r
f51461c8
LG
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