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