diff --git a/src/cell_conv.rs b/src/cell_conv.rs new file mode 100644 index 0000000..30f2e45 --- /dev/null +++ b/src/cell_conv.rs @@ -0,0 +1,50 @@ +/// A cell is a single FORTH stack value, all arguments and return values given to OpenFirmware +/// must fit in a cell. +pub type Cell = i32; + +/// # DoubleWord +/// a structure containing a low and high cell +/// # example +/// ``` +/// use ofw::cell_conv::DoubleWord; +/// let value: u64 = 0xabcdef0123456789; +/// let dw: DoubleWord = value.into(); +/// assert_eq!(dw.high as u32, 0xabcdef01); +/// assert_eq!(dw.low as u32, 0x23456789); +/// ``` +#[repr(C)] +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub struct DoubleWord { + pub low: Cell, + pub high: Cell, +} + +impl From for DoubleWord { + fn from(dw: i64) -> Self { + Self { + low: dw as Cell, + high: (dw >> 32) as Cell, + } + } +} + +impl From for DoubleWord { + fn from(dw: u64) -> Self { + Self { + low: dw as Cell, + high: (dw >> 32) as Cell, + } + } +} + +impl From for i64 { + fn from(dw: DoubleWord) -> Self { + (dw.high as i64) << 32 | dw.low as i64 + } +} + +impl From for u64 { + fn from(dw: DoubleWord) -> Self { + (dw.high as u64) << 32 | dw.low as u64 + } +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index c6f16ae..8449360 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -34,6 +34,9 @@ pub mod ntstr; /// module for architecture-specific code pub mod arch; +/// # cell_conv +/// module for converting between OpenFirmware cells and Rust integers +pub mod cell_conv; #[cfg(test)] mod tests; diff --git a/src/tests.rs b/src/tests.rs index 54387c2..7185696 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -1,5 +1,6 @@ use crate::arch::EntryFunction; use crate::{Args, call, call_method, IHandle, method_service_result, ntstr, OFW_FALSE, OFW_TRUE, service_result}; +use crate::cell_conv::DoubleWord; use crate::ntstr::NTSTR; #[test] @@ -9,6 +10,16 @@ fn ntstr_macro() { assert_eq!(a, b); } +#[test] +fn doubleword_conversion() { + let a: u64 = 0xabcdef0123456789; + let a_dw: DoubleWord = a.into(); + let b: u64 = a_dw.into(); + assert_eq!(a, b); + assert_eq!(a_dw.high as u32, 0xabcdef01); + assert_eq!(a_dw.low as u32, 0x23456789); +} + #[test] fn call_ofw() { pub extern "C" fn test_entry_function(args: *mut Args) -> i32 {