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>
This commit is contained in:
David Brown 2017-07-06 10:14:37 -06:00 committed by David Brown
parent 2784a2e2f2
commit bdb6db723d
3 changed files with 44 additions and 18 deletions

View File

@ -13,11 +13,10 @@
#define BOOT_LOG_LEVEL BOOT_LOG_LEVEL_ERROR
#include <bootutil/bootutil_log.h>
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)

View File

@ -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))
}

View File

@ -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;