sim: Move flash pointer up into Rust
Move the reference to the Flash device up into the Rust code instead of
trying to pass it back and forth to C. This will allow a future change
to use a fat pointer (such as a trait pointer), which ultimately will
allow different kinds of flash devices.
Signed-off-by: David Brown <david.brown@linaro.org>
diff --git a/sim/src/api.rs b/sim/src/api.rs
index 21806ce..7b81627 100644
--- a/sim/src/api.rs
+++ b/sim/src/api.rs
@@ -5,24 +5,47 @@
use log::LogLevel;
use std::slice;
+// The current active flash device. The 'static is a lie, and we manage the lifetime ourselves.
+static mut FLASH: Option<*mut Flash> = None;
+
+// Set the flash device to be used by the simulation. The pointer is unsafely stashed away.
+pub unsafe fn set_flash(dev: &mut Flash) {
+ FLASH = Some(dev);
+}
+
+pub unsafe fn clear_flash() {
+ FLASH = None;
+}
+
+// Retrieve the flash, returning an error from the enclosing function. We can't panic here because
+// we've called through C and unwinding is prohibited (it seems to just exit the program).
+macro_rules! get_flash {
+ () => {
+ match FLASH {
+ Some(x) => &mut *x,
+ None => return -19,
+ }
+ }
+}
+
// This isn't meant to call directly, but by a wrapper.
#[no_mangle]
-pub extern fn sim_flash_erase(dev: *mut Flash, offset: u32, size: u32) -> libc::c_int {
- let mut dev: &mut Flash = unsafe { &mut *dev };
+pub extern fn sim_flash_erase(offset: u32, size: u32) -> libc::c_int {
+ let dev = unsafe { get_flash!() };
map_err(dev.erase(offset as usize, size as usize))
}
#[no_mangle]
-pub extern fn sim_flash_read(dev: *const Flash, offset: u32, dest: *mut u8, size: u32) -> libc::c_int {
- let dev: &Flash = unsafe { &*dev };
+pub extern fn sim_flash_read(offset: u32, dest: *mut u8, size: u32) -> libc::c_int {
+ let dev = unsafe { get_flash!() };
let mut buf: &mut[u8] = unsafe { slice::from_raw_parts_mut(dest, size as usize) };
map_err(dev.read(offset as usize, &mut buf))
}
#[no_mangle]
-pub extern fn sim_flash_write(dev: *mut Flash, offset: u32, src: *const u8, size: u32) -> libc::c_int {
- let mut dev: &mut Flash = unsafe { &mut *dev };
+pub extern fn sim_flash_write(offset: u32, src: *const u8, size: u32) -> libc::c_int {
+ let dev = unsafe { get_flash!() };
let buf: &[u8] = unsafe { slice::from_raw_parts(src, size as usize) };
map_err(dev.write(offset as usize, &buf))
}
diff --git a/sim/src/c.rs b/sim/src/c.rs
index a770ca6..dd98c19 100644
--- a/sim/src/c.rs
+++ b/sim/src/c.rs
@@ -3,11 +3,14 @@
use area::AreaDesc;
use flash::Flash;
use libc;
+use api;
/// Invoke the bootloader on this flash device.
pub fn boot_go(flash: &mut Flash, areadesc: &AreaDesc) -> i32 {
- unsafe { raw::invoke_boot_go(flash as *mut _ as *mut libc::c_void,
- &areadesc.get_c() as *const _) as i32 }
+ unsafe { api::set_flash(flash) };
+ let result = unsafe { raw::invoke_boot_go(&areadesc.get_c() as *const _) as i32 };
+ unsafe { api::clear_flash(); };
+ result
}
/// Setter/getter for the flash counter. This isn't thread safe.
@@ -49,7 +52,7 @@
// This generates a warning about `CAreaDesc` not being foreign safe. There doesn't appear to
// be any way to get rid of this warning. See https://github.com/rust-lang/rust/issues/34798
// for information and tracking.
- pub fn invoke_boot_go(flash: *mut libc::c_void, areadesc: *const CAreaDesc) -> libc::c_int;
+ pub fn invoke_boot_go(areadesc: *const CAreaDesc) -> libc::c_int;
pub static mut flash_counter: libc::c_int;
pub static mut sim_flash_align: u8;