blob: 2fa6b3187560a1e487e5f2becbc85c093b432c0c [file] [log] [blame]
David Brownde7729e2017-01-09 10:41:35 -07001//! HAL api for MyNewt applications
2
3use flash::{Result, Flash};
4use libc;
David Brown2d1d7cf2017-05-10 08:55:09 -06005use log::LogLevel;
David Brown7ddec0b2017-07-06 10:47:35 -06006use mem;
David Brownde7729e2017-01-09 10:41:35 -07007use std::slice;
8
David Brownbdb6db72017-07-06 10:14:37 -06009// The current active flash device. The 'static is a lie, and we manage the lifetime ourselves.
10static mut FLASH: Option<*mut Flash> = None;
11
12// Set the flash device to be used by the simulation. The pointer is unsafely stashed away.
13pub unsafe fn set_flash(dev: &mut Flash) {
David Brown7ddec0b2017-07-06 10:47:35 -060014 let dev: &'static mut Flash = mem::transmute(dev);
15 FLASH = Some(dev as *mut Flash);
David Brownbdb6db72017-07-06 10:14:37 -060016}
17
18pub unsafe fn clear_flash() {
19 FLASH = None;
20}
21
22// Retrieve the flash, returning an error from the enclosing function. We can't panic here because
23// we've called through C and unwinding is prohibited (it seems to just exit the program).
24macro_rules! get_flash {
25 () => {
26 match FLASH {
27 Some(x) => &mut *x,
28 None => return -19,
29 }
30 }
31}
32
David Brownde7729e2017-01-09 10:41:35 -070033// This isn't meant to call directly, but by a wrapper.
34
35#[no_mangle]
David Brownbdb6db72017-07-06 10:14:37 -060036pub extern fn sim_flash_erase(offset: u32, size: u32) -> libc::c_int {
37 let dev = unsafe { get_flash!() };
David Brownde7729e2017-01-09 10:41:35 -070038 map_err(dev.erase(offset as usize, size as usize))
39}
40
41#[no_mangle]
David Brownbdb6db72017-07-06 10:14:37 -060042pub extern fn sim_flash_read(offset: u32, dest: *mut u8, size: u32) -> libc::c_int {
43 let dev = unsafe { get_flash!() };
David Brownde7729e2017-01-09 10:41:35 -070044 let mut buf: &mut[u8] = unsafe { slice::from_raw_parts_mut(dest, size as usize) };
45 map_err(dev.read(offset as usize, &mut buf))
46}
47
48#[no_mangle]
David Brownbdb6db72017-07-06 10:14:37 -060049pub extern fn sim_flash_write(offset: u32, src: *const u8, size: u32) -> libc::c_int {
50 let dev = unsafe { get_flash!() };
David Brownde7729e2017-01-09 10:41:35 -070051 let buf: &[u8] = unsafe { slice::from_raw_parts(src, size as usize) };
52 map_err(dev.write(offset as usize, &buf))
53}
54
55fn map_err(err: Result<()>) -> libc::c_int {
56 match err {
57 Ok(()) => 0,
Fabio Utzig19b2c1a2017-04-20 07:32:44 -030058 Err(e) => {
59 warn!("{}", e);
60 -1
61 },
David Brownde7729e2017-01-09 10:41:35 -070062 }
63}
David Brown2d1d7cf2017-05-10 08:55:09 -060064
65/// Called by C code to determine if we should log at this level. Levels are defined in
66/// bootutil/bootutil_log.h. This makes the logging from the C code controlled by bootsim::api, so
67/// for example, it can be enabled with something like:
68/// RUST_LOG=bootsim::api=info cargo run --release runall
69/// or
70/// RUST_LOG=bootsim=info cargo run --release runall
71#[no_mangle]
72pub extern fn sim_log_enabled(level: libc::c_int) -> libc::c_int {
73 let res = match level {
74 1 => log_enabled!(LogLevel::Error),
75 2 => log_enabled!(LogLevel::Warn),
76 3 => log_enabled!(LogLevel::Info),
77 4 => log_enabled!(LogLevel::Trace),
78 _ => false,
79 };
80 if res {
81 1
82 } else {
83 0
84 }
85}