|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
Streaming ELF32 segment, vector-base, and warm-reboot services. More...
#include "emu_elf.h"#include <stdint.h>#include <string.h>#include "emu_elf_source_internal.h"#include "emu_host_io_internal.h"#include "emu_memory_access.h"Go to the source code of this file.
Data Structures | |
| struct | emu_elf_program_table_t |
| Decoded program-header table geometry. More... | |
| struct | emu_elf_load_ctx_t |
| Context for streaming PT_LOAD bytes into one Unicorn engine. More... | |
| struct | emu_elf_vector_ctx_t |
| Accumulator for the lowest executable segment VMA. More... | |
Enumerations | |
| enum | emu_elf_stream_limit_t : uint32_t { k_elf_program_header_min = 32U , k_elf_stream_scratch = 4096U , k_elf_word_high_shift = 24U , k_elf_data_offset = 5U } |
| Bounded parser and PT_LOAD transfer dimensions. More... | |
Functions | |
| static uint16_t | internal_u16 (const uint8_t *bytes) |
| Decode one little-endian 16-bit ELF field. | |
| static uint32_t | internal_u32 (const uint8_t *bytes) |
| Decode one little-endian 32-bit ELF field. | |
| static bool | internal_program_table (const emu_elf_source_t *source, emu_elf_program_table_t *table, uint16_t *machine) |
| Read and validate the ELF32 ARM header and program-table geometry. | |
| static bool | internal_load_segment (const emu_elf_source_t *source, const emu_elf_program_table_t *table, uint16_t index, elf_exec_segment_t *segment) |
| Decode one bounds-checked PT_LOAD entry. | |
| uint32_t | elf_foreach_load_segment (const emu_elf_source_t *elf, elf_exec_segment_fn fn, void *ctx) |
| Walk every non-empty, bounds-checked PT_LOAD segment. | |
| static bool | internal_stream_segment (const elf_exec_segment_t *segment, void *opaque) |
| Stream one PT_LOAD segment into Unicorn in bounded chunks. | |
| int | load_elf (uc_engine *uc, const emu_elf_source_t *elf) |
| Load ELF32 PT_LOAD segments into emulated memory at their LMA. | |
| uint32_t | elf_foreach_exec_segment (const emu_elf_source_t *elf, elf_exec_segment_fn fn, void *ctx) |
| Walk every executable PT_LOAD segment of an ELF32 image. | |
| static bool | internal_vector_segment (const elf_exec_segment_t *segment, void *opaque) |
| Fold one executable segment into the lowest-VMA accumulator. | |
| uint32_t | elf_vector_base (const emu_elf_source_t *elf) |
| Vector-table base of an ELF: lowest executable PT_LOAD VMA. | |
Streaming ELF32 segment, vector-base, and warm-reboot services.
Program headers and PT_LOAD bytes are read from an independently owned raw descriptor through bounded stack scratch. No complete image is allocated, mapped, or retained in process memory.
Definition in file emu_elf.c.
| enum emu_elf_stream_limit_t : uint32_t |
| uint32_t elf_foreach_exec_segment | ( | const emu_elf_source_t * | elf, |
| elf_exec_segment_fn | fn, | ||
| void * | ctx ) |
Walk every executable PT_LOAD segment of an ELF32 image.
Decodes the program-header table once, skips any segment that is not a non-empty executable PT_LOAD or that would run past the end of the image, and invokes fn for each survivor. Factored out because the seam installers and the profiler each need exactly this walk; duplicating it left the same twenty statements of bounds-checking in several functions, where a fix to one copy would silently miss the others.
| [in] | elf | Open source; every read is bounded by its captured length. |
| [in] | fn | Callback invoked per executable segment. |
| [in,out] | ctx | Opaque pointer forwarded to fn. |
fn. | 0 | The image is too short, the header table is truncated, or the image carries no executable PT_LOAD segment. |
elf remains open for the complete walk. fn is non-NULL. fn returns false.Definition at line 265 of file emu_elf.c.
References emu_elf_program_table_t::count, elf_exec_segment_t::flags, internal_load_segment(), internal_program_table(), and k_elf_pf_x.
Referenced by div0_seam_install(), elf_vector_base(), and long_shift_seam_install().
| uint32_t elf_foreach_load_segment | ( | const emu_elf_source_t * | elf, |
| elf_exec_segment_fn | fn, | ||
| void * | ctx ) |
Walk every non-empty, bounds-checked PT_LOAD segment.
Decodes each usable load header and publishes only source offsets.
| [in] | elf | Open immutable ELF source. |
| [in] | fn | Callback invoked for each segment. |
| [in,out] | ctx | Opaque callback context. |
fn. | 0 | The header is malformed or no load segment was delivered. |
elf remains open for the complete walk. fn is non-null. fn returns false. Definition at line 172 of file emu_elf.c.
References emu_elf_program_table_t::count, internal_load_segment(), and internal_program_table().
Referenced by internal_cpu1_image_present(), and load_elf().
| uint32_t elf_vector_base | ( | const emu_elf_source_t * | elf | ) |
Vector-table base of an ELF: lowest executable PT_LOAD VMA.
Walks the program headers and returns the lowest p_vaddr among non-empty, executable (PF_X) PT_LOAD segments. On Cortex-M the vector table is linked at the start of the executable text region, so this is the image's vector base: 0x32100000 for the RAM-resident NS layout (a single RWE segment runs from the NS_SRAM2 alias) and 0x90000000 for the OSPI-XIP layout (the R-E segment executes in place from the flash window). The executable filter is essential for XIP: that image also carries a writable .data segment whose VMA is 0x32100000 (its initialisers live in flash, copied to RAM at NS startup) – lower than the vectors – so a plain minimum-VMA scan would wrongly pick the RAM alias. ra8_emulator feeds the result to the TrustZone NS vector-base tracking so the BLXNS world switch reads the NS MSP/reset from wherever the loaded image placed them.
| [in] | elf | Open ELF source (little-endian ELF32 ARM). |
| 0 | No executable PT_LOAD segment, or a truncated header table. |
elf remains open throughout the bounded header walk. Definition at line 320 of file emu_elf.c.
References emu_elf_vector_ctx_t::base, elf_foreach_exec_segment(), emu_elf_vector_ctx_t::found, and internal_vector_segment().
Referenced by internal_main_load_ns().
|
static |
Decode one bounds-checked PT_LOAD entry.
Reads only the fixed ELF32 header prefix and validates its payload range.
| [in] | source | Open ELF source. |
| [in] | table | Validated program-table geometry. |
| [in] | index | Entry index below table->count. |
| [out] | segment | Receives the decoded PT_LOAD descriptor. |
| true | A usable load segment was published. |
| false | The entry is unreadable, not loadable, empty, or out of range. |
index is in range. source remains open during the exact read. segment untouched. Definition at line 142 of file emu_elf.c.
References emu_elf_program_table_t::entry_size, internal_u32(), k_elf_ph_filesz_off, k_elf_ph_flags_off, k_elf_ph_offset_off, k_elf_ph_paddr_off, k_elf_ph_vaddr_off, k_elf_program_header_min, k_elf_pt_load, k_emu_elf_io_ok, emu_elf_source_t::length, emu_elf_program_table_t::offset, priv_emu_elf_read(), and RA8_INTERNAL.
Referenced by elf_foreach_exec_segment(), and elf_foreach_load_segment().
|
static |
Read and validate the ELF32 ARM header and program-table geometry.
Rejects wrong magic, class, byte order, machine, and table bounds.
| [in] | source | Open source to inspect. |
| [out] | table | Receives validated program-header geometry. |
| [out] | machine | Receives e_machine when the fixed header was readable. |
| true | Both the fixed header and complete table geometry are valid. |
| false | The source read or any validation failed. |
table and machine are non-null. source remains open during the exact header read. Definition at line 90 of file emu_elf.c.
References emu_elf_program_table_t::count, emu_elf_program_table_t::entry_size, internal_u16(), internal_u32(), k_elf_data_offset, k_elf_e_machine_off, k_elf_e_phentsize_off, k_elf_e_phnum_off, k_elf_e_phoff_off, k_elf_ehdr_size, k_elf_em_arm, k_elf_program_header_min, k_emu_elf_io_ok, emu_elf_source_t::length, memcmp(), emu_elf_program_table_t::offset, priv_emu_elf_read(), and RA8_INTERNAL.
Referenced by elf_foreach_exec_segment(), elf_foreach_load_segment(), and load_elf().
|
static |
Stream one PT_LOAD segment into Unicorn in bounded chunks.
Alternates exact positioned reads and Unicorn writes until complete.
| [in] | segment | Bounds-checked load segment. |
| [in,out] | opaque | emu_elf_load_ctx_t destination state. |
| true | Every source byte was written successfully. |
| false | A source read or Unicorn write failed. |
segment source remains open. Definition at line 218 of file emu_elf.c.
References emu_elf_view_t::bytes, emu_mem_write(), emu_elf_load_ctx_t::failed, elf_exec_segment_t::filesz, k_elf_stream_scratch, k_emu_elf_io_ok, emu_elf_load_ctx_t::loaded, elf_exec_segment_t::offset, elf_exec_segment_t::paddr, priv_emu_elf_read(), priv_emu_io_errf(), RA8_INTERNAL, elf_exec_segment_t::source, emu_elf_io_result_t::status, and emu_elf_load_ctx_t::uc.
Referenced by load_elf().
|
static |
Decode one little-endian 16-bit ELF field.
Combines bytes explicitly so host byte order is irrelevant.
| [in] | bytes | At least two readable bytes. |
| uint16_t | The decoded unsigned field. |
bytes is non-null and two-byte bounded. Definition at line 50 of file emu_elf.c.
References RA8_INTERNAL.
Referenced by internal_program_table().
|
static |
Decode one little-endian 32-bit ELF field.
Combines bytes explicitly so host byte order is irrelevant.
| [in] | bytes | At least four readable bytes. |
| uint32_t | The decoded unsigned field. |
bytes is non-null and four-byte bounded. Definition at line 68 of file emu_elf.c.
References k_elf_word_high_shift, and RA8_INTERNAL.
Referenced by internal_load_segment(), and internal_program_table().
|
static |
Fold one executable segment into the lowest-VMA accumulator.
Replaces the candidate only when this segment has a lower VMA.
| [in] | segment | Bounds-checked executable segment. |
| [in,out] | opaque | emu_elf_vector_ctx_t accumulator. |
| true | Every valid segment is accepted for comparison. |
segment is non-null. opaque points to a writable accumulator. Definition at line 310 of file emu_elf.c.
References emu_elf_vector_ctx_t::base, emu_elf_vector_ctx_t::found, RA8_INTERNAL, and elf_exec_segment_t::vaddr.
Referenced by elf_vector_base().
| int load_elf | ( | uc_engine * | uc, |
| const emu_elf_source_t * | elf ) |
Load ELF32 PT_LOAD segments into emulated memory at their LMA.
Validates the ELF magic, class (ELFCLASS32) and machine (EM_ARM), then walks the program headers and writes each non-empty PT_LOAD segment's file bytes to its physical load address (p_paddr) in uc memory – exactly what a flash programmer does with the image. One loaded ... @ ... injected error sink line is emitted per segment. .bss is untouched (the firmware's own Reset_Handler zeroes it), matching real boot.
| [in,out] | uc | Unicorn engine whose memory receives the segments. |
| [in] | elf | Open immutable ELF source. |
| 0 | At least one PT_LOAD segment was written. |
| -1 | Not a 32-bit ARM ELF, or a segment write failed, or no segment was loadable. |
uc has every segment's target region mapped. elf remains open for the complete segment walk. Definition at line 248 of file emu_elf.c.
References elf_foreach_load_segment(), emu_elf_load_ctx_t::failed, internal_program_table(), internal_stream_segment(), k_elf_em_arm, emu_elf_load_ctx_t::loaded, and priv_emu_io_errf().
Referenced by internal_cpu1_engine_init(), internal_main_load_ns(), internal_main_load_primary(), and warm_reboot().