irv_loader/
lib.rs

1use irv_traits::{Bus, BusError};
2
3/// An error returned by [`load`].
4#[derive(Debug)]
5pub enum Error {
6    /// An error encountered while writing to the bus.
7    Bus(BusError),
8    /// An error encountered while parsing the ELF file.
9    Goblin(goblin::error::Error),
10}
11
12impl From<goblin::error::Error> for Error {
13    fn from(e: goblin::error::Error) -> Self {
14        Error::Goblin(e)
15    }
16}
17
18impl From<BusError> for Error {
19    fn from(e: BusError) -> Self {
20        Error::Bus(e)
21    }
22}
23
24/// Attempts to parse `elf_data` as an ELF file and store the contents of all
25/// of its loadable segments into appropriate addresses on the `bus`.
26pub fn load<B>(bus: &B, elf_data: &[u8]) -> Result<(), Error>
27where B: Bus<u64, u8>
28{
29    let elf = goblin::elf::Elf::parse(elf_data)?;
30
31    for phdr in elf.program_headers {
32        let data = &elf_data[phdr.file_range()];
33        let vm_range = phdr.vm_range();
34
35        let mut vm_addr = phdr.vm_range().start as u64;
36        for byte in data {
37            if vm_addr == vm_range.end as u64 {
38                break
39            }
40
41            bus.store(vm_addr, *byte)?;
42
43            vm_addr += 1;
44        }
45    }
46
47    Ok(())
48}