ADD ELF SUPPORT
This commit is contained in:
79
Cargo.lock
generated
79
Cargo.lock
generated
@@ -26,12 +26,29 @@ version = "0.2.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
|
checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "goblin"
|
||||||
|
version = "0.10.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4db6758c546e6f81f265638c980e5e84dfbda80cfd8e89e02f83454c8e8124bd"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
"plain",
|
||||||
|
"scroll",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.176"
|
version = "0.2.176"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "58f929b4d672ea937a23a1ab494143d968337a5f47e56d0815df1e0890ddf174"
|
checksum = "58f929b4d672ea937a23a1ab494143d968337a5f47e56d0815df1e0890ddf174"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "log"
|
||||||
|
version = "0.4.29"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memmap2"
|
name = "memmap2"
|
||||||
version = "0.9.8"
|
version = "0.9.8"
|
||||||
@@ -53,11 +70,73 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "plain"
|
||||||
|
version = "0.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.103"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.42"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scroll"
|
||||||
|
version = "0.13.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c1257cd4248b4132760d6524d6dda4e053bc648c9070b960929bf50cfb1e7add"
|
||||||
|
dependencies = [
|
||||||
|
"scroll_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scroll_derive"
|
||||||
|
version = "0.13.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ed76efe62313ab6610570951494bdaa81568026e0318eaa55f167de70eeea67d"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "2.0.111"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "trve"
|
name = "trve"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
|
"goblin",
|
||||||
"memmap2",
|
"memmap2",
|
||||||
"nix",
|
"nix",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.22"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
|
||||||
|
|||||||
@@ -5,5 +5,6 @@ edition = "2024"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.100"
|
anyhow = "1.0.100"
|
||||||
|
goblin = "0.10.4"
|
||||||
memmap2 = "0.9.8"
|
memmap2 = "0.9.8"
|
||||||
nix = { version = "0.30.1", features = ["fs"] }
|
nix = { version = "0.30.1", features = ["fs"] }
|
||||||
|
|||||||
2
echo.S
2
echo.S
@@ -1,4 +1,4 @@
|
|||||||
.section .text._start
|
.section .text
|
||||||
.globl _start
|
.globl _start
|
||||||
|
|
||||||
.equ UART_DATA, 0
|
.equ UART_DATA, 0
|
||||||
|
|||||||
1
link.ld
1
link.ld
@@ -6,7 +6,6 @@ MEMORY {
|
|||||||
|
|
||||||
SECTIONS {
|
SECTIONS {
|
||||||
.text : ALIGN(4) {
|
.text : ALIGN(4) {
|
||||||
*(.text._start)
|
|
||||||
*(.text*)
|
*(.text*)
|
||||||
} > RAM
|
} > RAM
|
||||||
|
|
||||||
|
|||||||
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;
|
use crate::basic_uart::BasicUart;
|
||||||
|
|
||||||
fn read_file_to_buffer(path: &str, buffer: &mut [u8]) -> io::Result<usize> {
|
mod execload;
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
fn main() -> Result<()> {
|
||||||
let mut ram = Ram::try_new(16 * 1024 * 1024 / 4096)?;
|
let mut ram = Ram::try_new(16 * 1024 * 1024 / 4096)?;
|
||||||
@@ -53,7 +35,7 @@ fn main() -> Result<()> {
|
|||||||
bail!("Wrong number of arguments");
|
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 = BasicUart::new();
|
||||||
let uart = uart.spawn_poller(Duration::from_millis(10));
|
let uart = uart.spawn_poller(Duration::from_millis(10));
|
||||||
@@ -76,7 +58,7 @@ fn main() -> Result<()> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let mut core = Core::new(mem_cfg);
|
let mut core = Core::new(mem_cfg);
|
||||||
core.reset(0x8000_0000);
|
core.reset(entry_point);
|
||||||
core.run();
|
core.run();
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
Reference in New Issue
Block a user