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