Primary Git Repository for the Zephyr Project. Zephyr is a new generation, scalable, optimized, secure RTOS for multiple hardware architectures.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

99 lines
2.7 KiB

#!/usr/bin/env python3
# Copyright 2023 The ChromiumOS Authors
# SPDX-License-Identifier: Apache-2.0
import struct
import sys
import elftools.elf.elffile
import elftools.elf.sections
# Converts a zephyr.elf file into an extremely simple "image format"
# for device loading. Really we should just load the ELF file
# directly, but the python ChromeOS test image lacks elftools. Longer
# term we should probably just use rimage, but that's significantly
# harder to parse.
#
# Format:
#
# 1. Three LE 32 bit words: MagicNumber, SRAM len, BootAddress
# 2. Two byte arrays: SRAM (length specified), and DRAM (remainder of file)
#
# No padding or uninterpreted bytes.
FILE_MAGIC = 0xE463BE95
elf_file = sys.argv[1]
out_file = sys.argv[2]
sram = bytearray()
dram = bytearray()
# Returns the offset of a segment within the sram region, or -1 if it
# doesn't appear to be SRAM. SRAM is mapped differently for different
# SOCs, but it's always a <=1M region in 0x4xxxxxxx. Just use what we
# get, but validate that it fits.
sram_block = 0
def sram_off(addr):
global sram_block
if addr < 0x40000000 or addr >= 0x50000000:
return -1
block = addr & ~0xFFFFF
assert sram_block in (0, block)
sram_block = block
off = addr - sram_block
assert off < 0x100000
return off
# Similar heuristics: current platforms put DRAM either at 0x60000000
# or 0x90000000 with no more than 16M of range
def dram_off(addr):
if (addr >> 28 not in [6, 9]) or (addr & 0x0F000000 != 0):
return -1
return addr & 0xFFFFFF
def read_elf(efile):
ef = elftools.elf.elffile.ELFFile(efile)
for seg in ef.iter_segments():
h = seg.header
if h.p_type == "PT_LOAD":
soff = sram_off(h.p_paddr)
doff = dram_off(h.p_paddr)
if soff >= 0:
buf = sram
off = soff
elif doff >= 0:
buf = dram
off = doff
else:
print(f"Invalid PT_LOAD address {h.p_paddr:x}")
sys.exit(1)
dat = seg.data()
end = off + len(dat)
if end > len(buf):
buf.extend(b'\x00' * (end - len(buf)))
# pylint: disable=consider-using-enumerate
for i in range(len(dat)):
buf[i + off] = dat[i]
for sec in ef.iter_sections():
if isinstance(sec, elftools.elf.sections.SymbolTableSection):
for sym in sec.iter_symbols():
if sym.name == "mtk_adsp_boot_entry":
boot_vector = sym.entry['st_value']
with open(out_file, "wb") as of:
of.write(struct.pack("<III", FILE_MAGIC, len(sram), boot_vector))
of.write(sram)
of.write(dram)
with open(elf_file, "rb") as f:
read_elf(f)