lifeblood_os/ddi/src/lib.rs
2025-09-08 20:56:44 -07:00

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());
}