#!/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("