]>
git.proxmox.com Git - mirror_edk2.git/blob - IntelFsp2Pkg/Tools/PatchFv.py
3 # Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.<BR>
4 # SPDX-License-Identifier: BSD-2-Clause-Patent
15 # param [in] binfile Binary file
16 # param [in] offset Offset
17 # param [in] len Length
21 def readDataFromFile (binfile
, offset
, len=1):
22 fd
= open(binfile
, "r+b")
23 fsize
= os
.path
.getsize(binfile
)
24 offval
= offset
& 0xFFFFFFFF
25 if (offval
& 0x80000000):
26 offval
= fsize
- (0xFFFFFFFF - offval
+ 1)
28 if sys
.version_info
[0] < 3:
29 bytearray
= [ord(b
) for b
in fd
.read(len)]
31 bytearray
= [b
for b
in fd
.read(len)]
35 value
= value
<< 8 | bytearray
[idx
]
41 # Check FSP header is valid or not
43 # param [in] binfile Binary file
45 # retval boolean True: valid; False: invalid
47 def IsFspHeaderValid (binfile
):
48 fd
= open (binfile
, "rb")
49 bindat
= fd
.read(0x200) # only read first 0x200 bytes
51 HeaderList
= [b
'FSPH' , b
'FSPP' , b
'FSPE'] # Check 'FSPH', 'FSPP', and 'FSPE' in the FSP header
53 for each
in HeaderList
:
55 idx
= bindat
.index(each
)
58 OffsetList
.append(idx
)
59 if not OffsetList
[0] or not OffsetList
[1]: # If 'FSPH' or 'FSPP' is missing, it will return false
61 if sys
.version_info
[0] < 3:
62 Revision
= ord(bindat
[OffsetList
[0] + 0x0B])
64 Revision
= bindat
[OffsetList
[0] + 0x0B]
66 # if revision is bigger than 1, it means it is FSP v1.1 or greater revision, which must contain 'FSPE'.
68 if Revision
> 1 and not OffsetList
[2]:
69 return False # If FSP v1.1 or greater without 'FSPE', then return false
75 # param [in] binfile Binary file
76 # param [in] offset Offset
77 # param [in] value Patch value
78 # param [in] len Length
82 def patchDataInFile (binfile
, offset
, value
, len=1):
83 fd
= open(binfile
, "r+b")
84 fsize
= os
.path
.getsize(binfile
)
85 offval
= offset
& 0xFFFFFFFF
86 if (offval
& 0x80000000):
87 offval
= fsize
- (0xFFFFFFFF - offval
+ 1)
91 bytearray
.append(value
& 0xFF)
95 if sys
.version_info
[0] < 3:
96 fd
.write("".join(chr(b
) for b
in bytearray
))
98 fd
.write(bytes(bytearray
))
105 self
.dictSymbolAddress
= {}
106 self
.dictGuidNameXref
= {}
107 self
.dictFfsOffset
= {}
108 self
.dictVariable
= {}
109 self
.dictModBase
= {}
112 self
.fdBase
= 0xFFFFFFFF
116 self
.parenthesisOpenSet
= '([{<'
117 self
.parenthesisCloseSet
= ')]}>'
122 # retval self.fdFile Retrieve FD file
124 def getFdFile (self
):
130 # retval self.fdSize Retrieve the size of FD file
132 def getFdSize (self
):
135 def parseFvInfFile (self
, infFile
):
137 fvFile
= infFile
[0:-4] + ".Fv"
138 fvInfo
['Name'] = os
.path
.splitext(os
.path
.basename(infFile
))[0]
139 fvInfo
['Offset'] = self
.getFvOffsetInFd(fvFile
)
140 fvInfo
['Size'] = readDataFromFile (fvFile
, 0x20, 4)
141 fdIn
= open(infFile
, "r")
142 rptLines
= fdIn
.readlines()
145 for rptLine
in rptLines
:
146 match
= re
.match("^EFI_BASE_ADDRESS\s*=\s*(0x[a-fA-F0-9]+)", rptLine
)
148 fvInfo
['Base'] = int(match
.group(1), 16)
150 self
.fvList
.append(dict(fvInfo
))
154 # Create dictionaries
156 # param [in] fvDir FV's directory
157 # param [in] fvNames All FV's names
159 # retval 0 Created dictionaries successfully
161 def createDicts (self
, fvDir
, fvNames
):
163 # If the fvDir is not a directory, then raise an exception
165 if not os
.path
.isdir(fvDir
):
166 raise Exception ("'%s' is not a valid directory!" % FvDir
)
169 # If the Guid.xref is not existing in fvDir, then raise an exception
171 xrefFile
= os
.path
.join(fvDir
, "Guid.xref")
172 if not os
.path
.exists(xrefFile
):
173 raise Exception("Cannot open GUID Xref file '%s'!" % xrefFile
)
176 # Add GUID reference to dictionary
178 self
.dictGuidNameXref
= {}
179 self
.parseGuidXrefFile(xrefFile
)
182 # Split up each FV from fvNames and get the fdBase
184 fvList
= fvNames
.split(":")
185 fdBase
= fvList
.pop()
187 fvList
.append(fdBase
)
190 # If the FD file is not existing, then raise an exception
192 fdFile
= os
.path
.join(fvDir
, fdBase
.strip() + ".fd")
193 if not os
.path
.exists(fdFile
):
194 raise Exception("Cannot open FD file '%s'!" % fdFile
)
197 # Get the size of the FD file
200 self
.fdSize
= os
.path
.getsize(fdFile
)
203 # If the INF file, which is the first element of fvList, is not existing, then raise an exception
205 infFile
= os
.path
.join(fvDir
, fvList
[0].strip()) + ".inf"
206 if not os
.path
.exists(infFile
):
207 raise Exception("Cannot open INF file '%s'!" % infFile
)
210 # Parse INF file in order to get fdBase and then assign those values to dictVariable
212 self
.parseInfFile(infFile
)
213 self
.dictVariable
= {}
214 self
.dictVariable
["FDSIZE"] = self
.fdSize
215 self
.dictVariable
["FDBASE"] = self
.fdBase
218 # Collect information from FV MAP file and FV TXT file then
219 # put them into dictionaries
222 self
.dictSymbolAddress
= {}
223 self
.dictFfsOffset
= {}
227 # If the .Fv.map file is not existing, then raise an exception.
228 # Otherwise, parse FV MAP file
230 fvFile
= os
.path
.join(fvDir
, file.strip()) + ".Fv"
231 mapFile
= fvFile
+ ".map"
232 if not os
.path
.exists(mapFile
):
233 raise Exception("Cannot open MAP file '%s'!" % mapFile
)
235 infFile
= fvFile
[0:-3] + ".inf"
236 self
.parseFvInfFile(infFile
)
237 self
.parseFvMapFile(mapFile
)
240 # If the .Fv.txt file is not existing, then raise an exception.
241 # Otherwise, parse FV TXT file
243 fvTxtFile
= fvFile
+ ".txt"
244 if not os
.path
.exists(fvTxtFile
):
245 raise Exception("Cannot open FV TXT file '%s'!" % fvTxtFile
)
247 self
.parseFvTxtFile(fvTxtFile
)
249 for fv
in self
.fvList
:
250 self
.dictVariable
['_BASE_%s_' % fv
['Name']] = fv
['Base']
252 # Search all MAP files in FFS directory if it exists then parse MOD MAP file
254 ffsDir
= os
.path
.join(fvDir
, "Ffs")
255 if (os
.path
.isdir(ffsDir
)):
256 for item
in os
.listdir(ffsDir
):
257 if len(item
) <= 0x24:
259 mapFile
=os
.path
.join(ffsDir
, item
, "%s.map" % item
[0:0x24])
260 if not os
.path
.exists(mapFile
):
262 self
.parseModMapFile(item
[0x24:], mapFile
)
267 # Get FV offset in FD file
269 # param [in] fvFile FV file
271 # retval offset Got FV offset successfully
273 def getFvOffsetInFd(self
, fvFile
):
275 # Check if the first 0x70 bytes of fvFile can be found in fdFile
277 fvHandle
= open(fvFile
, "r+b")
278 fdHandle
= open(self
.fdFile
, "r+b")
279 offset
= fdHandle
.read().find(fvHandle
.read(0x70))
283 raise Exception("Could not locate FV file %s in FD!" % fvFile
)
289 # param [in] infFile INF file
291 # retval 0 Parsed INF file successfully
293 def parseInfFile(self
, infFile
):
295 # Get FV offset and search EFI_BASE_ADDRESS in the FD file
296 # then assign the value of EFI_BASE_ADDRESS to fdBase
298 fvOffset
= self
.getFvOffsetInFd(infFile
[0:-4] + ".Fv")
299 fdIn
= open(infFile
, "r")
300 rptLine
= fdIn
.readline()
301 self
.fdBase
= 0xFFFFFFFF
302 while (rptLine
!= "" ):
303 #EFI_BASE_ADDRESS = 0xFFFDF400
304 match
= re
.match("^EFI_BASE_ADDRESS\s*=\s*(0x[a-fA-F0-9]+)", rptLine
)
305 if match
is not None:
306 self
.fdBase
= int(match
.group(1), 16) - fvOffset
307 rptLine
= fdIn
.readline()
309 if self
.fdBase
== 0xFFFFFFFF:
310 raise Exception("Could not find EFI_BASE_ADDRESS in INF file!" % fvFile
)
316 # param [in] fvTxtFile .Fv.txt file
318 # retval 0 Parsed FV TXT file successfully
320 def parseFvTxtFile(self
, fvTxtFile
):
321 fvName
= os
.path
.basename(fvTxtFile
)[0:-7].upper()
323 # Get information from .Fv.txt in order to create a dictionary
325 # self.dictFfsOffset[912740BE-2284-4734-B971-84B027353F0C] = 0x000D4078
327 fvOffset
= self
.getFvOffsetInFd(fvTxtFile
[0:-4])
328 fdIn
= open(fvTxtFile
, "r")
329 rptLine
= fdIn
.readline()
330 while (rptLine
!= "" ):
331 match
= re
.match("(0x[a-fA-F0-9]+)\s([0-9a-fA-F\-]+)", rptLine
)
332 if match
is not None:
333 if match
.group(2) in self
.dictFfsOffset
:
334 self
.dictFfsOffset
[fvName
+ ':' + match
.group(2)] = "0x%08X" % (int(match
.group(1), 16) + fvOffset
)
336 self
.dictFfsOffset
[match
.group(2)] = "0x%08X" % (int(match
.group(1), 16) + fvOffset
)
337 rptLine
= fdIn
.readline()
344 # param [in] mapFile .Fv.map file
346 # retval 0 Parsed FV MAP file successfully
348 def parseFvMapFile(self
, mapFile
):
350 # Get information from .Fv.map in order to create dictionaries
352 # self.dictModBase[FspSecCore:BASE] = 4294592776 (0xfffa4908)
353 # self.dictModBase[FspSecCore:ENTRY] = 4294606552 (0xfffa7ed8)
354 # self.dictModBase[FspSecCore:TEXT] = 4294593080 (0xfffa4a38)
355 # self.dictModBase[FspSecCore:DATA] = 4294612280 (0xfffa9538)
356 # self.dictSymbolAddress[FspSecCore:_SecStartup] = 0x00fffa4a38
358 fdIn
= open(mapFile
, "r")
359 rptLine
= fdIn
.readline()
362 while (rptLine
!= "" ):
363 if rptLine
[0] != ' ':
364 #DxeIpl (Fixed Flash Address, BaseAddress=0x00fffb4310, EntryPoint=0x00fffb4958)
365 #(GUID=86D70125-BAA3-4296-A62F-602BEBBB9081 .textbaseaddress=0x00fffb4398 .databaseaddress=0x00fffb4178)
366 match
= re
.match("([_a-zA-Z0-9\-]+)\s\(.+BaseAddress=(0x[0-9a-fA-F]+),\s+EntryPoint=(0x[0-9a-fA-F]+)\)", rptLine
)
367 if match
is not None:
369 modName
= match
.group(1)
370 if len(modName
) == 36:
371 modName
= self
.dictGuidNameXref
[modName
.upper()]
372 self
.dictModBase
['%s:BASE' % modName
] = int (match
.group(2), 16)
373 self
.dictModBase
['%s:ENTRY' % modName
] = int (match
.group(3), 16)
374 match
= re
.match("\(GUID=([A-Z0-9\-]+)\s+\.textbaseaddress=(0x[0-9a-fA-F]+)\s+\.databaseaddress=(0x[0-9a-fA-F]+)\)", rptLine
)
375 if match
is not None:
379 modName
= match
.group(1)
380 if len(modName
) == 36:
381 modName
= self
.dictGuidNameXref
[modName
.upper()]
382 self
.dictModBase
['%s:TEXT' % modName
] = int (match
.group(2), 16)
383 self
.dictModBase
['%s:DATA' % modName
] = int (match
.group(3), 16)
385 # 0x00fff8016c __ModuleEntryPoint
387 match
= re
.match("^\s+(0x[a-z0-9]+)\s+([_a-zA-Z0-9]+)", rptLine
)
388 if match
is not None:
389 self
.dictSymbolAddress
["%s:%s"%(modName
, match
.group(2))] = match
.group(1)
390 rptLine
= fdIn
.readline()
397 # param [in] moduleName Module name
398 # param [in] mapFile .Fv.map file
400 # retval 0 Parsed MOD MAP file successfully
401 # retval 1 There is no moduleEntryPoint in modSymbols
403 def parseModMapFile(self
, moduleName
, mapFile
):
405 # Get information from mapFile by moduleName in order to create a dictionary
407 # self.dictSymbolAddress[FspSecCore:___guard_fids_count] = 0x00fffa4778
410 fdIn
= open(mapFile
, "r")
411 reportLines
= fdIn
.readlines()
414 moduleEntryPoint
= "__ModuleEntryPoint"
415 reportLine
= reportLines
[0]
416 if reportLine
.strip().find("Archive member included") != -1:
418 # 0x0000000000001d55 IoRead8
419 patchMapFileMatchString
= "\s+(0x[0-9a-fA-F]{16})\s+([^\s][^0x][_a-zA-Z0-9\-]+)\s"
420 matchKeyGroupIndex
= 2
421 matchSymbolGroupIndex
= 1
425 #0003:00000190 _gComBase 00007a50 SerialPo
426 patchMapFileMatchString
= "^\s[0-9a-fA-F]{4}:[0-9a-fA-F]{8}\s+(\w+)\s+([0-9a-fA-F]{8}\s+)"
427 matchKeyGroupIndex
= 1
428 matchSymbolGroupIndex
= 2
431 for reportLine
in reportLines
:
432 match
= re
.match(patchMapFileMatchString
, reportLine
)
433 if match
is not None:
434 modSymbols
[prefix
+ match
.group(matchKeyGroupIndex
)] = match
.group(matchSymbolGroupIndex
)
436 # Handle extra module patchable PCD variable in Linux map since it might have different format
437 # .data._gPcd_BinaryPatch_PcdVpdBaseAddress
438 # 0x0000000000003714 0x4 /tmp/ccmytayk.ltrans1.ltrans.o
440 if matchSymbolGroupIndex
== 1:
441 for reportLine
in reportLines
:
444 pcdName
= match
.group(1)
445 match
= re
.match("\s+(0x[0-9a-fA-F]{16})\s+", reportLine
)
446 if match
is not None:
447 modSymbols
[prefix
+ pcdName
] = match
.group(1)
449 match
= re
.match("^\s\.data\.(_gPcd_BinaryPatch[_a-zA-Z0-9\-]+)", reportLine
)
450 if match
is not None:
454 if not moduleEntryPoint
in modSymbols
:
457 modEntry
= '%s:%s' % (moduleName
,moduleEntryPoint
)
458 if not modEntry
in self
.dictSymbolAddress
:
459 modKey
= '%s:ENTRY' % moduleName
460 if modKey
in self
.dictModBase
:
461 baseOffset
= self
.dictModBase
['%s:ENTRY' % moduleName
] - int(modSymbols
[moduleEntryPoint
], 16)
465 baseOffset
= int(self
.dictSymbolAddress
[modEntry
], 16) - int(modSymbols
[moduleEntryPoint
], 16)
466 for symbol
in modSymbols
:
467 fullSym
= "%s:%s" % (moduleName
, symbol
)
468 if not fullSym
in self
.dictSymbolAddress
:
469 self
.dictSymbolAddress
[fullSym
] = "0x00%08x" % (baseOffset
+ int(modSymbols
[symbol
], 16))
473 # Parse Guid.xref file
475 # param [in] xrefFile the full directory of Guid.xref file
477 # retval 0 Parsed Guid.xref file successfully
479 def parseGuidXrefFile(self
, xrefFile
):
481 # Get information from Guid.xref in order to create a GuidNameXref dictionary
482 # The dictGuidNameXref, for example, will be like
483 # dictGuidNameXref [1BA0062E-C779-4582-8566-336AE8F78F09] = FspSecCore
485 fdIn
= open(xrefFile
, "r")
486 rptLine
= fdIn
.readline()
487 while (rptLine
!= "" ):
488 match
= re
.match("([0-9a-fA-F\-]+)\s([_a-zA-Z0-9]+)", rptLine
)
489 if match
is not None:
490 self
.dictGuidNameXref
[match
.group(1).upper()] = match
.group(2)
491 rptLine
= fdIn
.readline()
496 # Get current character
498 # retval elf.string[self.index]
499 # retval '' Exception
503 return self
.string
[self
.index
]
508 # Check to see if it is last index
513 return self
.index
== len(self
.string
)
525 while not self
.isLast():
526 if self
.getCurr() in ' \t':
536 def parseValue(self
):
539 while not self
.isLast():
540 char
= self
.getCurr()
541 if char
.lower() in '_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789:-':
548 partList
= var
.split(':')
549 lenList
= len(partList
)
550 if lenList
!= 2 and lenList
!= 3:
551 raise Exception("Unrecognized expression %s" % var
)
552 modName
= partList
[lenList
-2]
553 modOff
= partList
[lenList
-1]
554 if ('-' not in modName
) and (modOff
[0] in '0123456789'):
556 var
= self
.getModGuid(modName
) + ":" + modOff
557 if '-' in var
: # GUID:OFFSET
558 value
= self
.getGuidOff(var
)
560 value
= self
.getSymbols(var
)
563 if var
[0] in '0123456789':
564 value
= self
.getNumber(var
)
566 value
= self
.getVariable(var
)
570 # Parse single operation
572 # retval ~self.parseBrace() or self.parseValue()
574 def parseSingleOp(self
):
576 char
= self
.getCurr()
579 return ~self
.parseBrace()
581 return self
.parseValue()
584 # Parse symbol of Brace([, {, <)
586 # retval value or self.parseSingleOp()
588 def parseBrace(self
):
590 char
= self
.getCurr()
591 parenthesisType
= self
.parenthesisOpenSet
.find(char
)
592 if parenthesisType
>= 0:
594 value
= self
.parseExpr()
596 if self
.getCurr() != self
.parenthesisCloseSet
[parenthesisType
]:
597 raise Exception("No closing brace")
599 if parenthesisType
== 1: # [ : Get content
600 value
= self
.getContent(value
)
601 elif parenthesisType
== 2: # { : To address
602 value
= self
.toAddress(value
)
603 elif parenthesisType
== 3: # < : To offset
604 value
= self
.toOffset(value
)
607 return self
.parseSingleOp()
610 # Parse symbol of Multiplier(*)
612 # retval value or self.parseSingleOp()
615 values
= [self
.parseBrace()]
618 char
= self
.getCurr()
621 values
.append(self
.parseBrace())
630 # Parse symbol of And(&) and Or(|)
634 def parseAndOr(self
):
635 value
= self
.parseMul()
639 char
= self
.getCurr()
642 value
&= self
.parseMul()
644 div_index
= self
.index
646 value |
= self
.parseMul()
653 # Parse symbol of Add(+) and Minus(-)
657 def parseAddMinus(self
):
658 values
= [self
.parseAndOr()]
661 char
= self
.getCurr()
664 values
.append(self
.parseAndOr())
667 values
.append(-1 * self
.parseAndOr())
675 # retval self.parseAddMinus()
678 return self
.parseAddMinus()
686 value
= self
.parseExpr()
688 if not self
.isLast():
689 raise Exception("Unexpected character found '%s'" % self
.getCurr())
697 def getModGuid(self
, var
):
698 guid
= (guid
for guid
,name
in self
.dictGuidNameXref
.items() if name
==var
)
702 raise Exception("Unknown module name %s !" % var
)
710 def getVariable(self
, var
):
711 value
= self
.dictVariable
.get(var
, None)
713 raise Exception("Unrecognized variable '%s'" % var
)
721 def getNumber(self
, var
):
723 if var
.startswith('0x'): # HEX
736 def getContent(self
, value
):
737 return readDataFromFile (self
.fdFile
, self
.toOffset(value
), 4)
740 # Change value to address
746 def toAddress(self
, value
):
747 if value
< self
.fdSize
:
748 value
= value
+ self
.fdBase
752 # Change value to offset
758 def toOffset(self
, value
):
760 for fvInfo
in self
.fvList
:
761 if (value
>= fvInfo
['Base']) and (value
< fvInfo
['Base'] + fvInfo
['Size']):
762 offset
= value
- fvInfo
['Base'] + fvInfo
['Offset']
764 if (value
>= self
.fdBase
) and (value
< self
.fdBase
+ self
.fdSize
):
765 offset
= value
- self
.fdBase
768 if offset
>= self
.fdSize
:
769 raise Exception("Invalid file offset 0x%08x !" % value
)
779 def getGuidOff(self
, value
):
781 symbolName
= value
.split(':')
782 if len(symbolName
) == 3:
783 fvName
= symbolName
[0].upper()
784 keyName
= '%s:%s' % (fvName
, symbolName
[1])
785 offStr
= symbolName
[2]
786 elif len(symbolName
) == 2:
787 keyName
= symbolName
[0]
788 offStr
= symbolName
[1]
789 if keyName
in self
.dictFfsOffset
:
790 value
= (int(self
.dictFfsOffset
[keyName
], 16) + int(offStr
, 16)) & 0xFFFFFFFF
792 raise Exception("Unknown GUID %s !" % value
)
802 def getSymbols(self
, value
):
803 if value
in self
.dictSymbolAddress
:
805 ret
= int (self
.dictSymbolAddress
[value
], 16)
807 raise Exception("Unknown symbol %s !" % value
)
813 # param [in] expression
814 # param [in] isOffset
816 # retval value & 0xFFFFFFFF
818 def evaluate(self
, expression
, isOffset
):
821 self
.string
= expression
822 value
= self
.getResult()
825 # Consider it as an address first
826 value
= self
.toOffset(value
)
827 if value
& 0x80000000:
828 # Consider it as a negative offset next
829 offset
= (~value
& 0xFFFFFFFF) + 1
830 if offset
< self
.fdSize
:
831 value
= self
.fdSize
- offset
832 if value
>= self
.fdSize
:
833 raise Exception("Invalid offset expression !")
834 return value
& 0xFFFFFFFF
837 # Print out the usage
840 print ("PatchFv Version 0.50")
841 print ("Usage: \n\tPatchFv FvBuildDir [FvFileBaseNames:]FdFileBaseNameToPatch \"Offset, Value\"")
845 # Parse the options and args
847 symTables
= Symbols()
850 # If the arguments are less than 4, then return an error.
852 if len(sys
.argv
) < 4:
857 # If it fails to create dictionaries, then return an error.
859 if symTables
.createDicts(sys
.argv
[1], sys
.argv
[2]) != 0:
860 print ("ERROR: Failed to create symbol dictionary!!")
864 # Get FD file and size
866 fdFile
= symTables
.getFdFile()
867 fdSize
= symTables
.getFdSize()
871 # Check to see if FSP header is valid
873 ret
= IsFspHeaderValid(fdFile
)
875 raise Exception ("The FSP header is not valid. Stop patching FD.")
877 for fvFile
in sys
.argv
[3:]:
879 # Check to see if it has enough arguments
881 items
= fvFile
.split(",")
883 raise Exception("Expect more arguments for '%s'!" % fvFile
)
890 if item
.startswith("@"):
892 elif item
.startswith("$"):
900 # Parse symbols then append it to params
902 params
.append (symTables
.evaluate(item
, isOffset
))
905 # Patch a new value into FD file if it is not a command
909 if len (params
) == 2:
912 oldvalue
= readDataFromFile(fdFile
, offset
, 4)
913 ret
= patchDataInFile (fdFile
, offset
, value
, 4) - 4
915 raise Exception ("Patch command needs 2 parameters !")
918 raise Exception ("Patch failed for offset 0x%08X" % offset
)
920 print ("Patched offset 0x%08X:[%08X] with value 0x%08X # %s" % (offset
, oldvalue
, value
, comment
))
922 elif command
== "COPY":
924 # Copy binary block from source to destination
926 if len (params
) == 3:
927 src
= symTables
.toOffset(params
[0])
928 dest
= symTables
.toOffset(params
[1])
929 clen
= symTables
.toOffset(params
[2])
930 if (dest
+ clen
<= fdSize
) and (src
+ clen
<= fdSize
):
931 oldvalue
= readDataFromFile(fdFile
, src
, clen
)
932 ret
= patchDataInFile (fdFile
, dest
, oldvalue
, clen
) - clen
934 raise Exception ("Copy command OFFSET or LENGTH parameter is invalid !")
936 raise Exception ("Copy command needs 3 parameters !")
939 raise Exception ("Copy failed from offset 0x%08X to offset 0x%08X!" % (src
, dest
))
941 print ("Copied %d bytes from offset 0x%08X ~ offset 0x%08X # %s" % (clen
, src
, dest
, comment
))
943 raise Exception ("Unknown command %s!" % command
)
946 except Exception as ex
:
947 print ("ERROR: %s" % ex
)
950 if __name__
== '__main__':