Skip to content

Commit

Permalink
scripts: add tool to convert elf to asw for GR716
Browse files Browse the repository at this point in the history
JIRA: RTOS-406
  • Loading branch information
lukileczo committed Jun 7, 2023
1 parent fb7253d commit 7402f76
Showing 1 changed file with 140 additions and 0 deletions.
140 changes: 140 additions & 0 deletions scripts/gr716-convert.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
#!/usr/bin/env python3
#
# Script to convert ELF file to ASW format for GR716
#
# Copyright 2023 Phoenix Systems
# Author: Lukasz Leczkowski
#

import argparse
import os


READELF = "sparc-phoenix-readelf"


def parse_args():
parser = argparse.ArgumentParser(
description="Convert ELF file to ASW format for GR716"
)
parser.add_argument("filename", help="ELF file to convert")
parser.add_argument("-o", "--output", help="output file")
parser.add_argument("-e", "--entrypoint", help="entry point address (hex)")
return parser.parse_args()


def validate_file(filename: str):
if not os.path.isfile(filename):
print(f'Error: file "{filename}" not found')
exit(1)


def read_phdrs(filename: str):
# Get offset and size of LOAD program headers
phdrs = os.popen(f"{READELF} -l {filename} | grep LOAD").read()

# PLO has only one LOAD program header
# Get offset and size of LOAD program headers
phdrs = phdrs.split()
phdrs.remove("LOAD")

offset = int(phdrs[0], 16)
filesize = int(phdrs[3], 16)

return offset, filesize


def crc_encode(data: bytearray):
"""16-bit CRC according to ECSS-E-70-41A"""

def crc(byte: int, chk: int):
for i in range(8):
if (byte & 0x80) ^ ((chk & 0x8000) >> 8):
chk = ((chk << 1) ^ 0x1021) & 0xFFFF
else:
chk = (chk << 1) & 0xFFFF
byte = byte << 1
return chk

chk = 0xFFFF
for val in data:
chk = crc(val, chk)

return chk


def convert_file(inputfn: str, outputfn: str, entry: int):
offset, filesize = read_phdrs(inputfn)

with open(args.filename, "rb") as inputfile, open(outputfn, "w+b") as outputfile:
inputfile.seek(offset)
data = inputfile.read(filesize)

# Define image header:
# user defined id
# entry point
# image section headers
# image header checksum

usr_id = 0xDEADBEEF

outputfile.write(usr_id.to_bytes(4, "big"))
outputfile.write(entry.to_bytes(4, "big"))

# entry point magic - undocumented errata - instead of section 0
magic = (
(0x0).to_bytes(4, "big")
+ "EP->".encode("ascii")
+ entry.to_bytes(4, "big")
+ " GR716 \0".encode("ascii")
)
outputfile.write(magic)

# Define image section header:
# flags: 0x1 - copy to RAM
# relative offset to data: 0x2B (in 32-bit words)
# absolute destination address: entry point
# length of image (in 32-bit words)
# checksum of image data

outputfile.write((0x1).to_bytes(4, "big"))
outputfile.write((0x2B).to_bytes(4, "big"))
outputfile.write(entry.to_bytes(4, "big"))
outputfile.write((filesize // 4).to_bytes(4, "big"))

data_chk = crc_encode(bytearray(data))
outputfile.write(data_chk.to_bytes(2, "big"))
outputfile.write(b"\x00\x00")

# write 6 clear sections (unused)
for i in range(6):
for j in range(5):
outputfile.write((0x0).to_bytes(4, "big"))

outputfile.write(b"\x00\x00") # padding

hdr_chk_pos = outputfile.tell()
outputfile.seek(0, 0)

# calculate checksum over image section header
hdrs = bytearray(outputfile.read())
hdr_chk = crc_encode(hdrs)
outputfile.seek(hdr_chk_pos, 0)
outputfile.write(hdr_chk.to_bytes(2, "big"))

outputfile.write(data)

print(f"Converted {inputfn} to {outputfn}")


if __name__ == "__main__":
args = parse_args()
try:
entry = int(args.entrypoint, 16) if args.entrypoint else 0x31000000
except ValueError as e:
print(f"Error: {args.entrypoint} is not a valid entry point address")
exit(1)

validate_file(args.filename)
outputfn = args.output if args.output else args.filename.replace(".elf", ".asw")
convert_file(args.filename, outputfn, entry)

0 comments on commit 7402f76

Please sign in to comment.