blob: 26f4c93245e6fd8e0bb92aa472f940456c71242b [file] [log] [blame]
#!/usr/bin/env python
#
# Copyright (c) 2012, Sony Mobile Communications AB
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Sony Mobile Communications AB nor the names
# of its contributors may be used to endorse or promote products
# derived from this software without specific prior written
# permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# DESCRIPTION
#
# Combine one or more files to a elf file.
#
# SYNOPSIS
#
# mkelf.py -o elf file@addr[,ramdisk] ...
#
# elf The path to the output file
# file Input file
# addr ELF vaddr and paddr of this file
# ramdisk Mark this segment to be presented in ATAG list as ramdisk (optional)
# ipl Mark this segment to be handled by the boot code as IPL (optional)
# cmdline Mark this segment to be handled by the boot code as kernel cmdline (optional)
#
import re
import os
import sys
import struct
from optparse import OptionParser
# Elf definitions
PT_NULL = 0
PT_LOAD = 1
PT_NOTE = 4
# SEMC Elf definitions
P_FLAGS_RAMDISK = 0x80000000
P_FLAGS_IPL = 0x40000000 # used for STE U8500
P_FLAGS_CMDLINE = 0x20000000
P_FLAGS_RPM = 0x01000000 # used for QCT MSM8x60
def fatal(message):
print >> sys.stderr, '%s: %s' % (os.path.basename(sys.argv[0]), message)
sys.exit(1)
def parse_inputs(args):
segs = []
for arg in args:
try:
seg = {}
tokens = arg.split('@')
if len(tokens) != 2:
fatal('Incorrect format of input parameter: ' + arg)
seg['file'] = tokens[0]
if tokens[1] == 'cmdline':
seg['addr'] = '0'
seg['flags'] = 'cmdline'
else:
input = re.match("^(0x[0-9a-fA-F]+)(?:,(ramdisk|ipl|entry|rpm))?$", tokens[1]).groups()
seg['addr'] = input[0]
seg['flags'] = input[1]
segs.append(seg)
except AttributeError:
fatal("Incorrect format of input parameter: " + arg)
return segs
def write_elf_header(elf, entry, phnum):
elfhdr = {
'e_ident': '\x7fELF\x01\x01\x01\x61',
'e_type': 2,
'e_machine': 40,
'e_version': 1,
'e_entry': long(entry, 16),
'e_phoff': 52,
'e_shoff': 0,
'e_flags': 0,
'e_ehsize': 52,
'e_phentsize': 32,
'e_phnum': phnum,
'e_shentsize': 0,
'e_shnum': 0,
'e_shstrndx': 0
}
elf.write(struct.pack('<8s8xHHLLLLLHHHHHH',
elfhdr['e_ident'], elfhdr['e_type'], elfhdr['e_machine'],
elfhdr['e_version'], elfhdr['e_entry'], elfhdr['e_phoff'],
elfhdr['e_shoff'], elfhdr['e_flags'], elfhdr['e_ehsize'],
elfhdr['e_phentsize'], elfhdr['e_phnum'], elfhdr['e_shentsize'],
elfhdr['e_shnum'], elfhdr['e_shstrndx']))
def write_elf_phdr(elf, seg):
type = PT_LOAD
flags = 0
if seg['flags'] == 'ramdisk':
flags = P_FLAGS_RAMDISK
elif seg['flags'] == 'ipl':
flags = P_FLAGS_IPL
elif seg['flags'] == 'cmdline':
flags = P_FLAGS_CMDLINE
type = PT_NOTE
elif seg['flags'] == 'rpm':
flags = P_FLAGS_RPM
elfphdr = {
'p_type': type,
'p_offset': seg['offset'],
'p_vaddr': long(seg['addr'], 16),
'p_paddr': long(seg['addr'], 16),
'p_filesz': seg['size'],
'p_memsz': seg['size'],
'p_flags': flags,
'p_align': 0
}
elf.write(struct.pack('<LLLLLLLL',
elfphdr['p_type'],
elfphdr['p_offset'],
elfphdr['p_vaddr'],
elfphdr['p_paddr'],
elfphdr['p_filesz'],
elfphdr['p_memsz'],
elfphdr['p_flags'],
elfphdr['p_align']))
def main(args):
parser = OptionParser("usage: %prog options")
parser.add_option("-o", dest="outputfile", help="path to the output file")
(opts, args) = parser.parse_args()
if not opts.outputfile:
fatal("Missing -o on command line")
if len(args) < 1:
fatal("Missing input files")
offset = 4096
segments = []
for seg in parse_inputs(args):
size = os.path.getsize(seg['file'])
seg['offset'] = offset
seg['size'] = size
segments.append(seg)
offset += size
elf = open(opts.outputfile, 'wb')
write_elf_header(elf, segments[0]['addr'], len(segments))
for seg in segments:
write_elf_phdr(elf, seg)
for seg in segments:
elf.seek(seg['offset'])
f = open(seg['file'], 'rb')
data = f.read()
elf.write(data)
f.close()
elf.close()
if __name__ == "__main__":
main(sys.argv[1:])