#![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 { if data.len() < size_of::() { 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 { if data.len() < size_of::() + size_of::() { return None; } let header_offset = size_of::(); 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::(); 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 { if data.len() < header.segment_header_pointer as usize + size_of::() + (index * size_of::()) { return None; } let header_offset = header.segment_header_pointer as usize + (index * size_of::()); 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::()); 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 { if data.len() < header.relocation_header_pointer as usize + size_of::() + (index * size_of::()) { return None; } let header_offset = header.relocation_header_pointer as usize + (index * size_of::()); 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::()); 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()); }