add file conversion
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
parent
99e17c1afd
commit
9c3b0e2315
@ -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