From bdb6db723dcc4dd77e64b758908da4f9d7c92f8f Mon Sep 17 00:00:00 2001 From: David Brown Date: Thu, 6 Jul 2017 10:14:37 -0600 Subject: [PATCH] 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 --- sim/csupport/run.c | 18 +++++++++--------- sim/src/api.rs | 35 +++++++++++++++++++++++++++++------ sim/src/c.rs | 9 ++++++--- 3 files changed, 44 insertions(+), 18 deletions(-) diff --git a/sim/csupport/run.c b/sim/csupport/run.c index 467b21a4..e1f02319 100644 --- a/sim/csupport/run.c +++ b/sim/csupport/run.c @@ -13,11 +13,10 @@ #define BOOT_LOG_LEVEL BOOT_LOG_LEVEL_ERROR #include -extern int sim_flash_erase(void *flash, uint32_t offset, uint32_t size); -extern int sim_flash_read(void *flash, uint32_t offset, uint8_t *dest, uint32_t size); -extern int sim_flash_write(void *flash, uint32_t offset, const uint8_t *src, uint32_t size); +extern int sim_flash_erase(uint32_t offset, uint32_t size); +extern int sim_flash_read(uint32_t offset, uint8_t *dest, uint32_t size); +extern int sim_flash_write(uint32_t offset, const uint8_t *src, uint32_t size); -static void *flash_device; static jmp_buf boot_jmpbuf; int flash_counter; @@ -43,18 +42,19 @@ struct area_desc { static struct area_desc *flash_areas; -int invoke_boot_go(void *flash, struct area_desc *adesc) +int invoke_boot_go(struct area_desc *adesc) { int res; struct boot_rsp rsp; - flash_device = flash; flash_areas = adesc; if (setjmp(boot_jmpbuf) == 0) { res = boot_go(&rsp); + flash_areas = NULL; /* printf("boot_go off: %d (0x%08x)\n", res, rsp.br_image_off); */ return res; } else { + flash_areas = NULL; return -0x13579; } } @@ -64,7 +64,7 @@ int hal_flash_read(uint8_t flash_id, uint32_t address, void *dst, { // printf("hal_flash_read: %d, 0x%08x (0x%x)\n", // flash_id, address, num_bytes); - return sim_flash_read(flash_device, address, dst, num_bytes); + return sim_flash_read(address, dst, num_bytes); } int hal_flash_write(uint8_t flash_id, uint32_t address, @@ -76,7 +76,7 @@ int hal_flash_write(uint8_t flash_id, uint32_t address, jumped++; longjmp(boot_jmpbuf, 1); } - return sim_flash_write(flash_device, address, src, num_bytes); + return sim_flash_write(address, src, num_bytes); } int hal_flash_erase(uint8_t flash_id, uint32_t address, @@ -88,7 +88,7 @@ int hal_flash_erase(uint8_t flash_id, uint32_t address, jumped++; longjmp(boot_jmpbuf, 1); } - return sim_flash_erase(flash_device, address, num_bytes); + return sim_flash_erase(address, num_bytes); } uint8_t hal_flash_align(uint8_t flash_id) diff --git a/sim/src/api.rs b/sim/src/api.rs index 21806ce4..7b81627b 100644 --- a/sim/src/api.rs +++ b/sim/src/api.rs @@ -5,24 +5,47 @@ use libc; 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 a770ca65..dd98c191 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 @@ mod raw { // 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;