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