ADD ELF SUPPORT
This commit is contained in:
67
src/execload.rs
Normal file
67
src/execload.rs
Normal file
@@ -0,0 +1,67 @@
|
||||
// Copyright (c) 2025 taitep
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
// This file is part of TRVE (https://gitea.taitep.se/taitep/trve)
|
||||
// See LICENSE file in the project root for full license text.
|
||||
|
||||
use std::{fs, path::Path};
|
||||
|
||||
use anyhow::{Result, bail};
|
||||
use goblin::{
|
||||
Object,
|
||||
elf::{
|
||||
header::{EM_RISCV, ET_EXEC},
|
||||
program_header::PT_LOAD,
|
||||
},
|
||||
};
|
||||
use trve::consts::Addr;
|
||||
|
||||
pub fn load<P: AsRef<Path>>(path: P, ram: &mut [u8], ram_start: Addr) -> Result<Addr> {
|
||||
let buf = fs::read(path)?;
|
||||
|
||||
match Object::parse(&buf)? {
|
||||
Object::Elf(elf) => {
|
||||
if elf.header.e_type != ET_EXEC {
|
||||
bail!("Executable type incorrect, may not be an executable or may be dynamic");
|
||||
}
|
||||
if elf.header.e_machine != EM_RISCV {
|
||||
bail!("Executable architecture is not RISC-V");
|
||||
}
|
||||
if !elf.is_64 {
|
||||
bail!("Executable is not 64-bit");
|
||||
}
|
||||
if !elf.little_endian {
|
||||
bail!("Executable is not little-endian");
|
||||
}
|
||||
|
||||
for ph in elf.program_headers {
|
||||
if ph.p_type == PT_LOAD {
|
||||
let start = (ph.p_vaddr - ram_start) as usize;
|
||||
let end = start + ph.p_memsz as usize;
|
||||
let file_end = start + ph.p_filesz as usize;
|
||||
|
||||
if end > ram_start as usize + ram.len() {
|
||||
bail!("Segment at 0x{:x} does not fit in RAM", ph.p_vaddr);
|
||||
}
|
||||
|
||||
ram[start..file_end].copy_from_slice(
|
||||
&buf[ph.p_offset as usize..(ph.p_offset + ph.p_filesz) as usize],
|
||||
);
|
||||
|
||||
ram[file_end..end].fill(0);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(elf.entry)
|
||||
}
|
||||
Object::Unknown(_) => {
|
||||
eprintln!("Unrecognized executable format identifier, assuming raw binary");
|
||||
if buf.len() > ram.len() {
|
||||
bail!("Program too large for RAM");
|
||||
}
|
||||
ram[..buf.len()].copy_from_slice(&buf);
|
||||
Ok(ram_start)
|
||||
}
|
||||
_ => bail!("Unsupported executable format"),
|
||||
}
|
||||
}
|
||||
24
src/main.rs
24
src/main.rs
@@ -22,25 +22,7 @@ use anyhow::{Result, bail};
|
||||
|
||||
use crate::basic_uart::BasicUart;
|
||||
|
||||
fn read_file_to_buffer(path: &str, buffer: &mut [u8]) -> io::Result<usize> {
|
||||
let mut file = File::open(path)?;
|
||||
let mut total_read = 0;
|
||||
|
||||
while total_read < buffer.len() {
|
||||
let n = file.read(&mut buffer[total_read..])?;
|
||||
if n == 0 {
|
||||
return Ok(total_read);
|
||||
}
|
||||
total_read += n;
|
||||
}
|
||||
|
||||
let mut tmp = [0u8; 1];
|
||||
if file.read(&mut tmp)? != 0 {
|
||||
return Err(io::Error::other("RAM too small for file"));
|
||||
}
|
||||
|
||||
Ok(total_read)
|
||||
}
|
||||
mod execload;
|
||||
|
||||
fn main() -> Result<()> {
|
||||
let mut ram = Ram::try_new(16 * 1024 * 1024 / 4096)?;
|
||||
@@ -53,7 +35,7 @@ fn main() -> Result<()> {
|
||||
bail!("Wrong number of arguments");
|
||||
}
|
||||
|
||||
read_file_to_buffer(&args[1], buf)?;
|
||||
let entry_point = execload::load(&args[1], buf, 0x8000_0000)?;
|
||||
|
||||
let uart = BasicUart::new();
|
||||
let uart = uart.spawn_poller(Duration::from_millis(10));
|
||||
@@ -76,7 +58,7 @@ fn main() -> Result<()> {
|
||||
};
|
||||
|
||||
let mut core = Core::new(mem_cfg);
|
||||
core.reset(0x8000_0000);
|
||||
core.reset(entry_point);
|
||||
core.run();
|
||||
|
||||
Ok(())
|
||||
|
||||
Reference in New Issue
Block a user