126 lines
No EOL
5.8 KiB
Rust
126 lines
No EOL
5.8 KiB
Rust
#![no_std]
|
|
//! どこでも一緒、いつまでも!〜
|
|
|
|
pub mod arch;
|
|
|
|
#[repr(C)]
|
|
pub struct DDIHeader {
|
|
pub magic: [u8; 4], // "ddI\0"
|
|
pub version: u8,
|
|
pub ddi_type: u8,
|
|
}
|
|
|
|
#[repr(u8)]
|
|
pub enum DDIType {
|
|
LBOSRiscV = b'R',
|
|
}
|
|
|
|
#[repr(C)]
|
|
pub struct DDILBOSHeader {
|
|
pub entrypoint: u32,
|
|
pub segment_header_pointer: u32,
|
|
pub segment_header_count: u32,
|
|
pub relocation_header_pointer: u32,
|
|
pub relocation_header_count: u32,
|
|
pub entrypoint_segment: u32,
|
|
}
|
|
|
|
#[repr(C)]
|
|
pub struct DDISegmentHeader {
|
|
pub segment_pointer: u32,
|
|
pub segment_size: u32,
|
|
}
|
|
|
|
#[repr(C)]
|
|
pub struct DDIRelocationHeader {
|
|
pub relocation_segment: u32, // what segment this relocation is for
|
|
pub relocation_pointer: u32, // offset from the start of the segment
|
|
pub target_segment: u32, // what segment this relocation points to
|
|
pub target_pointer: u16, // offset from the start of the target segment
|
|
pub relocation_type: u16, // arch specific, see arch/riscv32/mod.rs
|
|
}
|
|
|
|
pub fn read_ddi_header(data: &[u8]) -> Option<DDIHeader> {
|
|
if data.len() < size_of::<DDIHeader>() {
|
|
return None;
|
|
}
|
|
Some(DDIHeader {
|
|
magic: data[0..4].try_into().ok()?,
|
|
version: data[4],
|
|
ddi_type: match data[5] {
|
|
x if x == DDIType::LBOSRiscV as u8 => DDIType::LBOSRiscV as u8,
|
|
_ => return None,
|
|
}
|
|
})
|
|
}
|
|
|
|
pub fn write_ddi_header(data: &mut [u8], header: &DDIHeader) {
|
|
data[0..4].copy_from_slice(&header.magic);
|
|
data[4] = header.version;
|
|
data[5] = header.ddi_type;
|
|
}
|
|
|
|
pub fn read_ddi_lbos_header(data: &[u8]) -> Option<DDILBOSHeader> {
|
|
if data.len() < size_of::<DDIHeader>() + size_of::<DDILBOSHeader>() {
|
|
return None;
|
|
}
|
|
let header_offset = size_of::<DDIHeader>();
|
|
Some(DDILBOSHeader {
|
|
entrypoint: u32::from_be_bytes((&data[header_offset..header_offset+4]).try_into().ok()?),
|
|
segment_header_pointer: u32::from_be_bytes((&data[header_offset+4..header_offset+8]).try_into().ok()?),
|
|
segment_header_count: u32::from_be_bytes((&data[header_offset+8..header_offset+12]).try_into().ok()?),
|
|
relocation_header_pointer: u32::from_be_bytes((&data[header_offset+12..header_offset+16]).try_into().ok()?),
|
|
relocation_header_count: u32::from_be_bytes((&data[header_offset+16..header_offset+20]).try_into().ok()?),
|
|
entrypoint_segment: u32::from_be_bytes((&data[header_offset+20..header_offset+24]).try_into().ok()?),
|
|
})
|
|
}
|
|
|
|
pub fn write_ddi_lbos_header(data: &mut [u8], header: &DDILBOSHeader) {
|
|
let header_offset = size_of::<DDIHeader>();
|
|
data[header_offset..header_offset+4].copy_from_slice(&header.entrypoint.to_be_bytes());
|
|
data[header_offset+4..header_offset+8].copy_from_slice(&header.segment_header_pointer.to_be_bytes());
|
|
data[header_offset+8..header_offset+12].copy_from_slice(&header.segment_header_count.to_be_bytes());
|
|
data[header_offset+12..header_offset+16].copy_from_slice(&header.relocation_header_pointer.to_be_bytes());
|
|
data[header_offset+16..header_offset+20].copy_from_slice(&header.relocation_header_count.to_be_bytes());
|
|
data[header_offset+20..header_offset+24].copy_from_slice(&header.entrypoint_segment.to_be_bytes());
|
|
}
|
|
|
|
pub fn read_ddi_segment_header(data: &[u8], header: &DDILBOSHeader, index: usize) -> Option<DDISegmentHeader> {
|
|
if data.len() < header.segment_header_pointer as usize + size_of::<DDISegmentHeader>() + (index * size_of::<DDISegmentHeader>()) {
|
|
return None;
|
|
}
|
|
let header_offset = header.segment_header_pointer as usize + (index * size_of::<DDISegmentHeader>());
|
|
Some(DDISegmentHeader {
|
|
segment_pointer: u32::from_be_bytes((&data[header_offset..header_offset+4]).try_into().ok()?),
|
|
segment_size: u32::from_be_bytes((&data[header_offset+4..header_offset+8]).try_into().ok()?),
|
|
})
|
|
}
|
|
|
|
pub fn write_ddi_segment_header(data: &mut [u8], header: &DDILBOSHeader, index: usize, datum: &DDISegmentHeader) {
|
|
let header_offset = header.segment_header_pointer as usize + (index * size_of::<DDISegmentHeader>());
|
|
data[header_offset..header_offset+4].copy_from_slice(&datum.segment_pointer.to_be_bytes());
|
|
data[header_offset+4..header_offset+8].copy_from_slice(&datum.segment_size.to_be_bytes());
|
|
}
|
|
|
|
pub fn read_ddi_relocation_header(data: &[u8], header: &DDILBOSHeader, index: usize) -> Option<DDIRelocationHeader> {
|
|
if data.len() < header.relocation_header_pointer as usize + size_of::<DDIRelocationHeader>() + (index * size_of::<DDIRelocationHeader>()) {
|
|
return None;
|
|
}
|
|
let header_offset = header.relocation_header_pointer as usize + (index * size_of::<DDIRelocationHeader>());
|
|
Some(DDIRelocationHeader {
|
|
relocation_segment: u32::from_be_bytes((&data[header_offset..header_offset+4]).try_into().ok()?),
|
|
relocation_pointer: u32::from_be_bytes((&data[header_offset+4..header_offset+8]).try_into().ok()?),
|
|
target_segment: u32::from_be_bytes((&data[header_offset+8..header_offset+12]).try_into().ok()?),
|
|
target_pointer: u16::from_be_bytes((&data[header_offset+12..header_offset+14]).try_into().ok()?),
|
|
relocation_type: u16::from_be_bytes((&data[header_offset+14..header_offset+16]).try_into().ok()?),
|
|
})
|
|
}
|
|
|
|
pub fn write_ddi_relocation_header(data: &mut [u8], header: &DDILBOSHeader, index: usize, datum: &DDIRelocationHeader) {
|
|
let header_offset = header.relocation_header_pointer as usize + (index * size_of::<DDIRelocationHeader>());
|
|
data[header_offset..header_offset+4].copy_from_slice(&datum.relocation_segment.to_be_bytes());
|
|
data[header_offset+4..header_offset+8].copy_from_slice(&datum.relocation_pointer.to_be_bytes());
|
|
data[header_offset+8..header_offset+12].copy_from_slice(&datum.target_segment.to_be_bytes());
|
|
data[header_offset+12..header_offset+14].copy_from_slice(&datum.target_pointer.to_be_bytes());
|
|
data[header_offset+14..header_offset+16].copy_from_slice(&datum.relocation_type.to_be_bytes());
|
|
} |