175 lines
4.5 KiB
Python
175 lines
4.5 KiB
Python
import argparse
|
|
import sys
|
|
|
|
from elftools.elf.elffile import ELFFile
|
|
|
|
# Use 64k page size for rounding. This should cover 4k/16k/64k kernels
|
|
PAGE_SIZE = 65536
|
|
AARCH64_LOAD_ADDR = '0x80000000'
|
|
|
|
def write_header(ofile, bundle_name):
|
|
ofile.write('#include <stddef.h>\n')
|
|
ofile.write('__attribute__ ((aligned ({}))) char {}_BUNDLE[] = \n"'.format(PAGE_SIZE, bundle_name))
|
|
|
|
|
|
def write_padding(ofile, padding, col):
|
|
while padding > 0:
|
|
ofile.write('\\x0')
|
|
|
|
if col == 15:
|
|
ofile.write('"\n"')
|
|
col = 0
|
|
else:
|
|
col = col + 1
|
|
|
|
padding = padding - 1
|
|
|
|
|
|
def write_elf_cbundle(ifile, ofile) -> int:
|
|
elffile = ELFFile(ifile)
|
|
entry_addr = elffile['e_entry']
|
|
|
|
load_segments = [ ]
|
|
for segment in elffile.iter_segments():
|
|
if segment['p_type'] == 'PT_LOAD':
|
|
load_segments.append(segment)
|
|
|
|
col = 0
|
|
total_size = 0
|
|
prev_paddr = None
|
|
|
|
for segment in load_segments:
|
|
if prev_paddr == None:
|
|
load_addr = segment['p_vaddr'] & 0xfffffff
|
|
else:
|
|
padding = segment['p_paddr'] - prev_paddr - prev_filesz
|
|
write_padding(ofile, padding, col)
|
|
total_size = total_size + padding
|
|
|
|
assert((segment['p_paddr'] - load_addr) == total_size)
|
|
|
|
for byte in segment.data():
|
|
ofile.write('\\x{:x}'.format(byte))
|
|
|
|
if col == 15:
|
|
ofile.write('"\n"')
|
|
col = 0
|
|
else:
|
|
col = col + 1
|
|
|
|
prev_paddr = segment['p_paddr']
|
|
prev_filesz = segment['p_filesz']
|
|
total_size = total_size + prev_filesz
|
|
|
|
rounded_size = int((total_size + PAGE_SIZE - 1) / PAGE_SIZE) * PAGE_SIZE
|
|
padding = rounded_size - total_size
|
|
write_padding(ofile, padding, col)
|
|
|
|
return load_addr, entry_addr
|
|
|
|
|
|
def write_raw_cbundle(ifile, ofile) -> int:
|
|
col = 0
|
|
total_size = 0
|
|
byte = ifile.read(1)
|
|
while byte:
|
|
ofile.write('\\x{:x}'.format(byte[0]))
|
|
|
|
if col == 15:
|
|
ofile.write('"\n"')
|
|
col = 0
|
|
else:
|
|
col = col + 1
|
|
|
|
total_size = total_size + 1
|
|
byte = ifile.read(1)
|
|
|
|
rounded_size = int((total_size + PAGE_SIZE - 1) / PAGE_SIZE) * PAGE_SIZE
|
|
padding = rounded_size - total_size
|
|
write_padding(ofile, padding, col)
|
|
|
|
|
|
def write_footer_generic(ofile, bundle_name):
|
|
footer = """
|
|
char * krunfw_get_{}(size_t *size)
|
|
{{
|
|
*size = sizeof({}_BUNDLE) - 1;
|
|
return &{}_BUNDLE[0];
|
|
}}
|
|
"""
|
|
ofile.write('";\n')
|
|
ofile.write(footer.format(bundle_name.lower(), bundle_name, bundle_name))
|
|
|
|
|
|
def write_footer_kernel(ofile, load_addr, entry_addr):
|
|
footer = """
|
|
char * krunfw_get_kernel(size_t *load_addr, size_t *entry_addr, size_t *size)
|
|
{{
|
|
*load_addr = {};
|
|
*entry_addr = {};
|
|
*size = sizeof(KERNEL_BUNDLE) - 1;
|
|
return &KERNEL_BUNDLE[0];
|
|
}}
|
|
|
|
int krunfw_get_version()
|
|
{{
|
|
return ABI_VERSION;
|
|
}}
|
|
"""
|
|
ofile.write('";\n')
|
|
ofile.write(footer.format(load_addr, entry_addr))
|
|
|
|
|
|
def main() -> int:
|
|
parser = argparse.ArgumentParser(description='Generate C blob from a binary')
|
|
|
|
parser.add_argument('input_file', type=str,
|
|
help='Input file')
|
|
parser.add_argument('output_file', type=str,
|
|
help='Output file')
|
|
parser.add_argument('-t', type=str, help='Bundle type (vmlinux, Image, qboot, initrd)')
|
|
|
|
args = parser.parse_args()
|
|
|
|
bundle_name = None
|
|
ifmt = None
|
|
if args.t == 'vmlinux':
|
|
bundle_name = 'KERNEL'
|
|
ifmt = 'elf'
|
|
elif args.t == 'Image':
|
|
bundle_name = 'KERNEL'
|
|
ifmt = 'raw'
|
|
elif args.t == 'qboot':
|
|
bundle_name = 'QBOOT'
|
|
ifmt = 'raw'
|
|
elif args.t == 'initrd':
|
|
bundle_name = 'INITRD'
|
|
ifmt = 'raw'
|
|
else:
|
|
print('Invalid bundle type')
|
|
return -1
|
|
|
|
ifile = open(args.input_file, 'rb')
|
|
ofile = open(args.output_file, 'w')
|
|
|
|
write_header(ofile, bundle_name)
|
|
|
|
if ifmt == 'elf':
|
|
load_addr, entry_addr = write_elf_cbundle(ifile, ofile)
|
|
elif ifmt == 'raw':
|
|
write_raw_cbundle(ifile, ofile)
|
|
|
|
if bundle_name == 'KERNEL':
|
|
if ifmt == 'raw':
|
|
load_addr = AARCH64_LOAD_ADDR;
|
|
entry_addr = AARCH64_LOAD_ADDR;
|
|
write_footer_kernel(ofile, load_addr, entry_addr)
|
|
else:
|
|
write_footer_generic(ofile, bundle_name)
|
|
|
|
return 0
|
|
|
|
|
|
if __name__ == '__main__':
|
|
sys.exit(main())
|