Allow multiple flash devices in bootutil wrapper
A new type `FlashMap` that stores a HashMap of [device_id -> Flash trait] was added, which enables multi-flash devices to be passed around. The previously existing static FLASH value that was used to simulate the raw device, was updated to using a FlashMap which enables bootutil to interface with more than one flash device. Signed-off-by: Fabio Utzig <utzig@apache.org>
This commit is contained in:
parent
1caef137c4
commit
1c9aea5814
|
@ -1,15 +1,22 @@
|
|||
//! HAL api for MyNewt applications
|
||||
|
||||
use simflash::{Result, Flash};
|
||||
use simflash::{Result, Flash, FlashPtr};
|
||||
use libc;
|
||||
use log::LogLevel;
|
||||
use std::mem;
|
||||
use std::slice;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Mutex;
|
||||
use std::ops::Deref;
|
||||
|
||||
// The current active flash device. The 'static is a lie, and we manage the lifetime ourselves.
|
||||
static mut FLASH: Option<*mut Flash> = None;
|
||||
/// A FlashMap maintain a table of [device_id -> Flash trait]
|
||||
type FlashMap = HashMap<u8, FlashPtr>;
|
||||
|
||||
lazy_static! {
|
||||
static ref FLASH: Mutex<FlashMap> = {
|
||||
Mutex::new(HashMap::new())
|
||||
};
|
||||
}
|
||||
|
||||
struct FlashParams {
|
||||
align: u8,
|
||||
|
@ -31,44 +38,50 @@ pub unsafe fn set_flash(dev_id: u8, dev: &mut Flash) {
|
|||
});
|
||||
|
||||
let dev: &'static mut Flash = mem::transmute(dev);
|
||||
FLASH = Some(dev as *mut Flash);
|
||||
let mut flash = FLASH.lock().unwrap();
|
||||
flash.insert(dev_id, FlashPtr{ptr: dev as *mut Flash});
|
||||
}
|
||||
|
||||
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,
|
||||
}
|
||||
}
|
||||
pub unsafe fn clear_flash(dev_id: u8) {
|
||||
let mut flash = FLASH.lock().unwrap();
|
||||
flash.remove(&dev_id);
|
||||
}
|
||||
|
||||
// This isn't meant to call directly, but by a wrapper.
|
||||
|
||||
#[no_mangle]
|
||||
pub extern fn sim_flash_erase(_id: u8, offset: u32, size: u32) -> libc::c_int {
|
||||
let dev = unsafe { get_flash!() };
|
||||
map_err(dev.erase(offset as usize, size as usize))
|
||||
pub extern fn sim_flash_erase(dev_id: u8, offset: u32, size: u32) -> libc::c_int {
|
||||
if let Ok(guard) = FLASH.lock() {
|
||||
if let Some(flash) = guard.deref().get(&dev_id) {
|
||||
let dev = unsafe { &mut *(flash.ptr) };
|
||||
return map_err(dev.erase(offset as usize, size as usize));
|
||||
}
|
||||
}
|
||||
-19
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern fn sim_flash_read(_id: u8, 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))
|
||||
pub extern fn sim_flash_read(dev_id: u8, offset: u32, dest: *mut u8, size: u32) -> libc::c_int {
|
||||
if let Ok(guard) = FLASH.lock() {
|
||||
if let Some(flash) = guard.deref().get(&dev_id) {
|
||||
let mut buf: &mut[u8] = unsafe { slice::from_raw_parts_mut(dest, size as usize) };
|
||||
let dev = unsafe { &mut *(flash.ptr) };
|
||||
return map_err(dev.read(offset as usize, &mut buf));
|
||||
}
|
||||
}
|
||||
-19
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern fn sim_flash_write(_id: u8, 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))
|
||||
pub extern fn sim_flash_write(dev_id: u8, offset: u32, src: *const u8, size: u32) -> libc::c_int {
|
||||
if let Ok(guard) = FLASH.lock() {
|
||||
if let Some(flash) = guard.deref().get(&dev_id) {
|
||||
let buf: &[u8] = unsafe { slice::from_raw_parts(src, size as usize) };
|
||||
let dev = unsafe { &mut *(flash.ptr) };
|
||||
return map_err(dev.write(offset as usize, &buf));
|
||||
}
|
||||
}
|
||||
-19
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
|
|
@ -30,7 +30,7 @@ pub fn boot_go(flash: &mut Flash, areadesc: &AreaDesc, counter: Option<&mut i32>
|
|||
let asserts = unsafe { raw::c_asserts };
|
||||
unsafe {
|
||||
counter.map(|c| *c = raw::flash_counter as i32);
|
||||
api::clear_flash();
|
||||
api::clear_flash(0);
|
||||
};
|
||||
(result, asserts)
|
||||
}
|
||||
|
|
|
@ -33,6 +33,11 @@ error_chain! {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct FlashPtr {
|
||||
pub ptr: *mut Flash,
|
||||
}
|
||||
unsafe impl Send for FlashPtr {}
|
||||
|
||||
pub trait Flash {
|
||||
fn erase(&mut self, offset: usize, len: usize) -> Result<()>;
|
||||
fn write(&mut self, offset: usize, payload: &[u8]) -> Result<()>;
|
||||
|
|
Loading…
Reference in New Issue