Browse Source
added a script to convert the elf file from gcc to TI Hex in order to use it with remote flasher etc. requires python to runfertito

3 changed files with 598 additions and 0 deletions
@ -0,0 +1,320 @@
|
||||
#!/usr/bin/env python |
||||
# $Id: elf.py,v 1.1 2006/04/11 18:35:23 cliechti Exp $ |
||||
|
||||
import struct |
||||
|
||||
# ELF object file reader |
||||
# (C) 2003 cliechti@gmx.net |
||||
# Python license |
||||
|
||||
# size alignment |
||||
# Elf32_Addr 4 4 Unsigned program address |
||||
# Elf32_Half 2 2 Unsigned medium integer |
||||
# Elf32_Off 4 4 Unsigned file offset |
||||
# Elf32_Sword 4 4 Signed large integer |
||||
# Elf32_Word 4 4 Unsigned large integer |
||||
# unsignedchar 1 1 Unsigned small integer |
||||
|
||||
#define EI_NIDENT 16 |
||||
#~ typedef struct{ |
||||
#~ unsigned char e_ident[EI_NIDENT]; |
||||
#~ Elf32_Half e_type; |
||||
#~ Elf32_Half e_machine; |
||||
#~ Elf32_Word e_version; |
||||
#~ Elf32_Addr e_entry; |
||||
#~ Elf32_Off e_phoff; |
||||
#~ Elf32_Off e_shoff; |
||||
#~ Elf32_Word e_flags; |
||||
#~ Elf32_Half e_ehsize; |
||||
#~ Elf32_Half e_phentsize; |
||||
#~ Elf32_Half e_phnum; |
||||
#~ Elf32_Half e_shentsize; |
||||
#~ Elf32_Half e_shnum; |
||||
#~ Elf32_Half e_shstrndx; |
||||
#~ } Elf32_Ehdr; |
||||
|
||||
|
||||
#Section Header |
||||
#~ typedef struct { |
||||
#~ Elf32_Word sh_name; |
||||
#~ Elf32_Word sh_type; |
||||
#~ Elf32_Word sh_flags; |
||||
#~ Elf32_Addr sh_addr; |
||||
#~ Elf32_Off sh_offset; |
||||
#~ Elf32_Word sh_size; |
||||
#~ Elf32_Word sh_link; |
||||
#~ Elf32_Word sh_info; |
||||
#~ Elf32_Word sh_addralign; |
||||
#~ Elf32_Word sh_entsize; |
||||
#~ } Elf32_Shdr; |
||||
|
||||
#~ typedef struct { |
||||
#~ Elf32_Word p_type; |
||||
#~ Elf32_Off p_offset; |
||||
#~ Elf32_Addr p_vaddr; |
||||
#~ Elf32_Addr p_paddr; |
||||
#~ Elf32_Word p_filesz; |
||||
#~ Elf32_Word p_memsz; |
||||
#~ Elf32_Word p_flags; |
||||
#~ Elf32_Word p_align; |
||||
#~ } Elf32_Phdr; |
||||
|
||||
|
||||
class ELFException(Exception): pass |
||||
|
||||
class ELFSection: |
||||
"""read and store a section""" |
||||
Elf32_Shdr = "<IIIIIIIIII" #header format |
||||
|
||||
#section types |
||||
SHT_NULL = 0 |
||||
SHT_PROGBITS = 1 |
||||
SHT_SYMTAB = 2 |
||||
SHT_STRTAB = 3 |
||||
SHT_RELA = 4 |
||||
SHT_HASH = 5 |
||||
SHT_DYNAMIC = 6 |
||||
SHT_NOTE = 7 |
||||
SHT_NOBITS = 8 |
||||
SHT_REL = 9 |
||||
SHT_SHLIB = 10 |
||||
SHT_DYNSYM = 11 |
||||
SHT_LOPROC = 0x70000000L |
||||
SHT_HIPROC = 0x7fffffffL |
||||
SHT_LOUSER = 0x80000000L |
||||
SHT_HIUSER = 0xffffffffL |
||||
#section attribute flags |
||||
SHF_WRITE = 0x1 |
||||
SHF_ALLOC = 0x2 |
||||
SHF_EXECINSTR = 0x4 |
||||
SHF_MASKPROC = 0xf0000000L |
||||
|
||||
def __init__(self): |
||||
"""creat a new empty section object""" |
||||
(self.sh_name, self.sh_type, self.sh_flags, self.sh_addr, |
||||
self.sh_offset, self.sh_size, self.sh_link, self.sh_info, |
||||
self.sh_addralign, self.sh_entsize) = [0]*10 |
||||
self.name = None |
||||
self.data = None |
||||
self.lma = None |
||||
|
||||
def fromString(self, s): |
||||
"""get section header from string""" |
||||
(self.sh_name, self.sh_type, self.sh_flags, self.sh_addr, |
||||
self.sh_offset, self.sh_size, self.sh_link, self.sh_info, |
||||
self.sh_addralign, self.sh_entsize) = struct.unpack(self.Elf32_Shdr, s) |
||||
|
||||
def __str__(self): |
||||
"""pretty print for debug...""" |
||||
return "%s(%s, sh_type=%s, sh_flags=%s, "\ |
||||
"sh_addr=0x%04x, sh_offset=0x%04x, sh_size=%s, sh_link=%s, "\ |
||||
"sh_info=%s, sh_addralign=%s, sh_entsize=%s, lma=0x%04x)" % ( |
||||
self.__class__.__name__, |
||||
self.name is not None and "%r" % self.name or "sh_name=%s" % self.sh_name, |
||||
self.sh_type, self.sh_flags, self.sh_addr, |
||||
self.sh_offset, self.sh_size, self.sh_link, self.sh_info, |
||||
self.sh_addralign, self.sh_entsize, self.lma) |
||||
|
||||
class ELFProgramHeader: |
||||
"""Store and parse a program header""" |
||||
Elf32_Phdr = "<IIIIIIII" #header format |
||||
|
||||
#segmet types |
||||
PT_NULL = 0 |
||||
PT_LOAD = 1 |
||||
PT_DYNAMIC = 2 |
||||
PT_INTERP = 3 |
||||
PT_NOTE = 4 |
||||
PT_SHLIB = 5 |
||||
PT_PHDR = 6 |
||||
PT_LOPROC = 0x70000000L |
||||
PT_HIPROC = 0x7fffffffL |
||||
|
||||
#segment flags |
||||
PF_R = 0x4 #segment is readable |
||||
PF_W = 0x2 #segment is writable |
||||
PF_X = 0x1 #segment is executable |
||||
|
||||
def __init__(self): |
||||
"""create a new, empty segment/program header""" |
||||
(self.p_type, self.p_offset, self.p_vaddr, self.p_paddr, |
||||
self.p_filesz, self.p_memsz, self.p_flags, self.p_align) = [0]*8 |
||||
self.data = None |
||||
|
||||
def fromString(self, s): |
||||
"""parse header info from string""" |
||||
(self.p_type, self.p_offset, self.p_vaddr, self.p_paddr, |
||||
self.p_filesz, self.p_memsz, self.p_flags, |
||||
self.p_align) = struct.unpack(self.Elf32_Phdr, s) |
||||
|
||||
def __str__(self): |
||||
"""pretty print for debug...""" |
||||
return "%s(p_type=%s, p_offset=0x%04x, p_vaddr=0x%04x, p_paddr=0x%04x, "\ |
||||
"p_filesz=%s, p_memsz=%s, p_flags=%s, "\ |
||||
"p_align=%s)" % ( |
||||
self.__class__.__name__, |
||||
self.p_type, self.p_offset, self.p_vaddr, self.p_paddr, |
||||
self.p_filesz, self.p_memsz, self.p_flags, |
||||
self.p_align) |
||||
|
||||
class ELFObject: |
||||
"""Object to read and handle an LEF object file""" |
||||
#header information |
||||
Elf32_Ehdr = "<16sHHIIIIIHHHHHH" |
||||
|
||||
#offsets within e_ident |
||||
EI_MAG0 = 0 #File identification |
||||
EI_MAG1 = 1 #File identification |
||||
EI_MAG2 = 2 #File identification |
||||
EI_MAG3 = 3 #File identification |
||||
EI_CLASS = 4 #File class |
||||
EI_DATA = 5 #Data encoding |
||||
EI_VERSION = 6 #File version |
||||
EI_PAD = 7 #Start of padding bytes |
||||
EI_NIDENT = 16 #Size of e_ident[] |
||||
#elf file type flags |
||||
ET_NONE = 0 #No file type |
||||
ET_REL = 1 #Relocatable file |
||||
ET_EXEC = 2 #Executable file |
||||
ET_DYN = 3 #Shared object file |
||||
ET_CORE = 4 #Core file |
||||
ET_LOPROC = 0xff00 #Processor-specific |
||||
ET_HIPROC = 0xffff #Processor-specific |
||||
#ELF format |
||||
ELFCLASSNONE = 0 #Invalid class |
||||
ELFCLASS32 = 1 #32-bit objects |
||||
ELFCLASS64 = 2 #64-bit objects |
||||
#encoding |
||||
ELFDATANONE = 0 #Invalid data encoding |
||||
ELFDATA2LSB = 1 #See below |
||||
ELFDATA2MSB = 2 #See below |
||||
|
||||
def __init__(self): |
||||
"""create a new elf object""" |
||||
(self.e_ident, self.e_type, self.e_machine, self.e_version, |
||||
self.e_entry, self.e_phoff, self.e_shoff, |
||||
self.e_flags, self.e_ehsize, self.e_phentsize, self.e_phnum, |
||||
self.e_shentsize, self.e_shnum, self.e_shstrndx) = [0]*14 |
||||
|
||||
def fromFile(self, fileobj): |
||||
"""read all relevant data from fileobj. |
||||
the file must be seekable""" |
||||
#get file header |
||||
(self.e_ident, self.e_type, self.e_machine, self.e_version, |
||||
self.e_entry, self.e_phoff, self.e_shoff, |
||||
self.e_flags, self.e_ehsize, self.e_phentsize, self.e_phnum, |
||||
self.e_shentsize, self.e_shnum, self.e_shstrndx) = struct.unpack( |
||||
self.Elf32_Ehdr, fileobj.read(struct.calcsize(self.Elf32_Ehdr))) |
||||
#verify if its a known format and realy an ELF file |
||||
if self.e_ident[0:4] != '\x7fELF' and\ |
||||
self.e_ident[self.EI_CLASS] != self.ELFCLASS32 and\ |
||||
self.e_ident[self.EI_DATA] != self.ELFDATA2LSB and\ |
||||
self.e_ident[self.EI_VERSION] != 1: |
||||
raise ELFException("Not a valid ELF file") |
||||
|
||||
#load programm headers |
||||
self.programmheaders = [] |
||||
if self.e_phnum: |
||||
#load program headers |
||||
fileobj.seek(self.e_phoff) |
||||
for sectionnum in range(self.e_phnum): |
||||
shdr = (fileobj.read(self.e_phentsize) + '\0'* struct.calcsize(ELFProgramHeader.Elf32_Phdr))[0:struct.calcsize(ELFProgramHeader.Elf32_Phdr)] |
||||
psection = ELFProgramHeader() |
||||
psection.fromString(shdr) |
||||
if psection.p_offset: #skip if section has invalid offset in file |
||||
self.programmheaders.append(psection) |
||||
#~ #get the segment data from the file for each prg header |
||||
#~ for phdr in self.programmheaders: |
||||
#~ fileobj.seek(phdr.p_offset) |
||||
#~ phdr.data = fileobj.read(phdr.p_filesz) |
||||
#~ #pad if needed |
||||
#~ if phdr.p_filesz < phdr.p_memsz: |
||||
#~ phdr.data = phdr.data + '\0' * (phdr.p_memsz-phdr.p_filesz) |
||||
|
||||
#load sections |
||||
self.sections = [] |
||||
fileobj.seek(self.e_shoff) |
||||
for sectionnum in range(self.e_shnum): |
||||
shdr = (fileobj.read(self.e_shentsize) + '\0'* struct.calcsize(ELFSection.Elf32_Shdr))[0:struct.calcsize(ELFSection.Elf32_Shdr)] |
||||
elfsection = ELFSection() |
||||
elfsection.fromString(shdr) |
||||
self.sections.append(elfsection) |
||||
|
||||
#load data for all sections |
||||
for section in self.sections: |
||||
fileobj.seek(section.sh_offset) |
||||
data = fileobj.read(section.sh_size) |
||||
section.data = data |
||||
if section.sh_type == ELFSection.SHT_STRTAB: |
||||
section.values = data.split('\0') |
||||
section.lma = self.getLMA(section) |
||||
|
||||
#get section names |
||||
for section in self.sections: |
||||
start = self.sections[self.e_shstrndx].data[section.sh_name:] |
||||
section.name = start.split('\0')[0] |
||||
|
||||
def getSection(self, name): |
||||
"""get section by name""" |
||||
for section in self.sections: |
||||
if section.name == '.text': |
||||
return section |
||||
|
||||
def getProgrammableSections(self): |
||||
"""get all program headers that are marked as executable and |
||||
have suitable attributes to be code""" |
||||
res = [] |
||||
for p in self.programmheaders: |
||||
#~ print p |
||||
#~ if section.sh_flags & self.SHF_ALLOC and section.name not in ('.data', '.data1', '.bss'): |
||||
#~ if p.p_type == ELFProgramHeader.PT_LOAD:# and p.p_paddr == p.p_vaddr and p.p_flags & ELFProgramHeader.PF_X: |
||||
if p.p_type == ELFProgramHeader.PT_LOAD: |
||||
res.append(p) |
||||
return res |
||||
|
||||
def getLMA(self, section): |
||||
#magic load memory address calculation ;-) |
||||
for p in self.programmheaders: |
||||
if (p.p_paddr != 0 and \ |
||||
p.p_type == ELFProgramHeader.PT_LOAD and \ |
||||
p.p_vaddr != p.p_paddr and \ |
||||
p.p_vaddr <= section.sh_addr and \ |
||||
(p.p_vaddr + p.p_memsz >= section.sh_addr + section.sh_size) \ |
||||
and (not (section.sh_flags & ELFSection.SHF_ALLOC and section.sh_type != ELFSection.SHT_NOBITS) \ |
||||
or (p.p_offset <= section.sh_offset \ |
||||
and (p.p_offset + p.p_filesz >= section.sh_offset + section.sh_size)))): |
||||
return section.sh_addr + p.p_paddr - p.p_vaddr |
||||
return section.sh_addr |
||||
|
||||
def getSections(self): |
||||
"""get sections relevant for the application""" |
||||
res = [] |
||||
for section in self.sections: |
||||
if section.sh_flags & ELFSection.SHF_ALLOC and section.sh_type != ELFSection.SHT_NOBITS: |
||||
res.append(section) |
||||
return res |
||||
|
||||
def __str__(self): |
||||
"""pretty print for debug...""" |
||||
return "%s(self.e_type=%r, self.e_machine=%r, self.e_version=%r, sections=%r)" % ( |
||||
self.__class__.__name__, |
||||
self.e_type, self.e_machine, self.e_version, |
||||
[section.name for section in self.sections]) |
||||
|
||||
|
||||
if __name__ == '__main__': |
||||
print "This is only a module test!" |
||||
elf = ELFObject() |
||||
elf.fromFile(open("test.elf")) |
||||
if elf.e_type != ELFObject.ET_EXEC: |
||||
raise Exception("No executable") |
||||
print elf |
||||
|
||||
#~ print repr(elf.getSection('.text').data) |
||||
#~ print [(s.name, hex(s.sh_addr)) for s in elf.getSections()] |
||||
print "-"*20 |
||||
for p in elf.sections: print p |
||||
print "-"*20 |
||||
for p in elf.getSections(): print p |
||||
print "-"*20 |
||||
for p in elf.getProgrammableSections(): print p |
@ -0,0 +1,278 @@
|
||||
#!/usr/bin/env python |
||||
# $Id: memory.py,v 1.4.2.1 2009/05/19 09:07:21 rlim Exp $ |
||||
import sys |
||||
import elf |
||||
|
||||
DEBUG = 0 |
||||
|
||||
class FileFormatError(IOError): |
||||
"""file is not in the expected format""" |
||||
|
||||
|
||||
class Segment: |
||||
"""store a string with memory contents along with its startaddress""" |
||||
def __init__(self, startaddress = 0, data=None): |
||||
if data is None: |
||||
self.data = '' |
||||
else: |
||||
self.data = data |
||||
self.startaddress = startaddress |
||||
|
||||
def __getitem__(self, index): |
||||
return self.data[index] |
||||
|
||||
def __len__(self): |
||||
return len(self.data) |
||||
|
||||
def __repr__(self): |
||||
return "Segment(startaddress=0x%04x, data=%r)" % (self.startaddress, self.data) |
||||
|
||||
class Memory: |
||||
"""represent memory contents. with functions to load files""" |
||||
def __init__(self, filename=None): |
||||
self.segments = [] |
||||
if filename: |
||||
self.filename = filename |
||||
self.loadFile(filename) |
||||
|
||||
def append(self, seg): |
||||
self.segments.append(seg) |
||||
|
||||
def __getitem__(self, index): |
||||
return self.segments[index] |
||||
|
||||
def __len__(self): |
||||
return len(self.segments) |
||||
|
||||
def __repr__(self): |
||||
return "Memory:\n%s" % ('\n'.join([repr(seg) for seg in self.segments]),) |
||||
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
||||
|
||||
def loadIHex(self, file): |
||||
"""load data from a (opened) file in Intel-HEX format""" |
||||
segmentdata = [] |
||||
currentAddr = 0 |
||||
startAddr = 0 |
||||
extendAddr = 0 |
||||
lines = file.readlines() |
||||
for l in lines: |
||||
if not l.strip(): continue #skip empty lines |
||||
if l[0] != ':': raise FileFormatError("line not valid intel hex data: '%s...'" % l[0:10]) |
||||
l = l.strip() #fix CR-LF issues... |
||||
length = int(l[1:3],16) |
||||
address = int(l[3:7],16) + extendAddr |
||||
type = int(l[7:9],16) |
||||
check = int(l[-2:],16) |
||||
if type == 0x00: |
||||
if currentAddr != address: |
||||
if segmentdata: |
||||
self.segments.append( Segment(startAddr, ''.join(segmentdata)) ) |
||||
startAddr = currentAddr = address |
||||
segmentdata = [] |
||||
for i in range(length): |
||||
segmentdata.append( chr(int(l[9+2*i:11+2*i],16)) ) |
||||
currentAddr = length + currentAddr |
||||
elif type == 0x02: |
||||
extendAddr = int(l[9:13],16) << 4 |
||||
elif type in (0x01, 0x03, 0x04, 0x05): |
||||
pass |
||||
else: |
||||
sys.stderr.write("Ignored unknown field (type 0x%02x) in ihex file.\n" % type) |
||||
if segmentdata: |
||||
self.segments.append( Segment(startAddr, ''.join(segmentdata)) ) |
||||
|
||||
def loadTIText(self, file): |
||||
"""load data from a (opened) file in TI-Text format""" |
||||
startAddr = 0 |
||||
segmentdata = [] |
||||
#Convert data for MSP430, TXT-File is parsed line by line |
||||
for line in file: #Read one line |
||||
if not line: break #EOF |
||||
l = line.strip() |
||||
if l[0] == 'q': break |
||||
elif l[0] == '@': #if @ => new address => send frame and set new addr. |
||||
#create a new segment |
||||
if segmentdata: |
||||
self.segments.append( Segment(startAddr, ''.join(segmentdata)) ) |
||||
startAddr = int(l[1:],16) |
||||
segmentdata = [] |
||||
else: |
||||
for i in l.split(): |
||||
try: |
||||
segmentdata.append(chr(int(i,16))) |
||||
except ValueError, e: |
||||
raise FileFormatError('File is no valid TI-Text (%s)' % e) |
||||
if segmentdata: |
||||
self.segments.append( Segment(startAddr, ''.join(segmentdata)) ) |
||||
|
||||
def loadELF(self, file): |
||||
"""load data from a (opened) file in ELF object format. |
||||
File must be seekable""" |
||||
obj = elf.ELFObject() |
||||
obj.fromFile(file) |
||||
if obj.e_type != elf.ELFObject.ET_EXEC: |
||||
raise Exception("No executable") |
||||
for section in obj.getSections(): |
||||
if DEBUG: |
||||
sys.stderr.write("ELF section %s at 0x%04x %d bytes\n" % (section.name, section.lma, len(section.data))) |
||||
if len(section.data): |
||||
self.segments.append( Segment(section.lma, section.data) ) |
||||
|
||||
def loadFile(self, filename, fileobj=None): |
||||
"""fill memory with the contents of a file. file type is determined from extension""" |
||||
close = 0 |
||||
if fileobj is None: |
||||
fileobj = open(filename, "rb") |
||||
close = 1 |
||||
try: |
||||
#first check extension |
||||
try: |
||||
if filename[-4:].lower() == '.txt': |
||||
self.loadTIText(fileobj) |
||||
return |
||||
elif filename[-4:].lower() in ('.a43', '.hex'): |
||||
self.loadIHex(fileobj) |
||||
return |
||||
except FileFormatError: |
||||
pass #do contents based detection below |
||||
#then do a contents based detection |
||||
try: |
||||
self.loadELF(fileobj) |
||||
except elf.ELFException: |
||||
fileobj.seek(0) |
||||
try: |
||||
self.loadIHex(fileobj) |
||||
except FileFormatError: |
||||
fileobj.seek(0) |
||||
try: |
||||
self.loadTIText(fileobj) |
||||
except FileFormatError: |
||||
raise FileFormatError('file could not be loaded (not ELF, Intel-Hex, or TI-Text)') |
||||
finally: |
||||
if close: |
||||
fileobj.close() |
||||
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
||||
def saveIHex(self, filelike): |
||||
"""write a string containing intel hex to given file object""" |
||||
noeof=0 |
||||
for seg in self.segments: |
||||
address = seg.startaddress |
||||
data = seg.data |
||||
start = 0 |
||||
while start<len(data): |
||||
end = start + 16 |
||||
if end > len(data): end = len(data) |
||||
filelike.write(self._ihexline(address, data[start:end])) |
||||
start += 16 |
||||
address += 16 |
||||
filelike.write(self._ihexline(0, [], end=1)) #append no data but an end line |
||||
|
||||
def _ihexline(self, address, buffer, end=0): |
||||
"""internal use: generate a line with intel hex encoded data""" |
||||
out = [] |
||||
if end: |
||||
type = 1 |
||||
else: |
||||
type = 0 |
||||
out.append( ':%02X%04X%02X' % (len(buffer),address&0xffff,type) ) |
||||
sum = len(buffer) + ((address>>8)&255) + (address&255) + (type&255) |
||||
for b in [ord(x) for x in buffer]: |
||||
out.append('%02X' % (b&255) ) |
||||
sum += b&255 |
||||
out.append('%02X\r\n' %( (-sum)&255)) |
||||
return ''.join(out) |
||||
|
||||
def saveTIText(self, filelike): |
||||
"""output TI-Text to given file object""" |
||||
for segment in self.segments: |
||||
filelike.write("@%04x\n" % segment.startaddress) |
||||
for i in range(0, len(segment.data), 16): |
||||
filelike.write("%s\n" % " ".join(["%02x" % ord(x) for x in segment.data[i:i+16]])) |
||||
filelike.write("q\n") |
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
||||
|
||||
def getMemrange(self, fromadr, toadr): |
||||
"""get a range of bytes from the memory. unavailable values are filled with 0xff.""" |
||||
res = '' |
||||
toadr = toadr + 1 #python indexes are excluding end, so include it |
||||
while fromadr < toadr: |
||||
for seg in self.segments: |
||||
segend = seg.startaddress + len(seg.data) |
||||
if seg.startaddress <= fromadr and fromadr < segend: |
||||
if toadr > segend: #not all data in segment |
||||
catchlength = segend - fromadr |
||||
else: |
||||
catchlength = toadr - fromadr |
||||
res = res + seg.data[fromadr-seg.startaddress : fromadr-seg.startaddress+catchlength] |
||||
fromadr = fromadr + catchlength #adjust start |
||||
if len(res) >= toadr-fromadr: |
||||
break #return res |
||||
else: #undefined memory is filled with 0xff |
||||
res = res + chr(255) |
||||
fromadr = fromadr + 1 #adjust start |
||||
return res |
||||
|
||||
def getMem(self, address, size): |
||||
"""get a range of bytes from the memory. a ValueError is raised if |
||||
unavailable addresses are tried to read""" |
||||
data = [] |
||||
for seg in self.segments: |
||||
#~ print "0x%04x " * 2 % (seg.startaddress, seg.startaddress + len(seg.data)) |
||||
if seg.startaddress <= address and seg.startaddress + len(seg.data) >= address: |
||||
#segment contains data in the address range |
||||
offset = address - seg.startaddress |
||||
length = min(len(seg.data)-offset, size) |
||||
data.append(seg.data[offset:offset+length]) |
||||
address += length |
||||
value = ''.join(data) |
||||
if len(value) != size: |
||||
raise ValueError("could not collect the requested data") |
||||
return value |
||||
|
||||
def setMem(self, address, contents): |
||||
"""write a range of bytes to the memory. a segment covering the address |
||||
range to be written has to be existent. a ValueError is raised if not |
||||
all data could be written (attention: a part of the data may have been |
||||
written!)""" |
||||
#~ print "%04x: %r" % (address, contents) |
||||
for seg in self.segments: |
||||
#~ print "0x%04x " * 3 % (address, seg.startaddress, seg.startaddress + len(seg.data)) |
||||
if seg.startaddress <= address and seg.startaddress + len(seg.data) >= address: |
||||
#segment contains data in the address range |
||||
offset = address - seg.startaddress |
||||
length = min(len(seg.data)-offset, len(contents)) |
||||
seg.data = seg.data[:offset] + contents[:length] + seg.data[offset+length:] |
||||
contents = contents[length:] #cut away what is used |
||||
if not contents: return #stop if done |
||||
address += length |
||||
raise ValueError("could not write all data") |
||||
|
||||
if __name__ == "__main__": |
||||
from optparse import OptionParser |
||||
parser = OptionParser() |
||||
parser.add_option("-i", "--input", dest="input", |
||||
help="read file") |
||||
parser.add_option("-o", "--output", |
||||
dest="output", help="output file") |
||||
parser.add_option("-f", "--format", |
||||
dest="format", help="output format [titxt,ihex]", |
||||
choices=["titxt", "ihex"], |
||||
default="titxt") |
||||
|
||||
(options, args) = parser.parse_args() |
||||
|
||||
if not options.output or not options.input: |
||||
parser.error("input and output are required") |
||||
|
||||
mem = Memory() |
||||
mem.loadFile(options.input) |
||||
fp = open(options.output, "w") |
||||
if options.format == "titxt": |
||||
print "convert to TI Hex" |
||||
mem.saveTIText(fp) |
||||
elif options.format == "ihex": |
||||
print "convert to Intel Hex" |
||||
mem.saveIHex(fp) |
||||
fp.close() |
Loading…
Reference in new issue