blob: 9f364cb3e2969d5ef002491c2867cf9196bee521 [file] [log] [blame]
David Brownde7729e2017-01-09 10:41:35 -07001/// Interface wrappers to C API entering to the bootloader
2
3use area::AreaDesc;
David Brown2cbc4702017-07-06 14:18:58 -06004use simflash::Flash;
David Brownde7729e2017-01-09 10:41:35 -07005use libc;
David Brownbdb6db72017-07-06 10:14:37 -06006use api;
David Brown353610d2017-11-06 11:31:31 -07007use std::sync::Mutex;
8
9lazy_static! {
10 /// Mutex to lock the simulation. The C code for the bootloader uses
11 /// global variables, and is therefore non-reentrant.
12 static ref BOOT_LOCK: Mutex<()> = Mutex::new(());
13}
David Brownde7729e2017-01-09 10:41:35 -070014
15/// Invoke the bootloader on this flash device.
David Brown541860c2017-11-06 11:25:42 -070016pub fn boot_go(flash: &mut Flash, areadesc: &AreaDesc, counter: Option<&mut i32>, align: u8) -> i32 {
David Brown353610d2017-11-06 11:31:31 -070017 let _lock = BOOT_LOCK.lock().unwrap();
18
David Brownee61c832017-11-06 11:13:25 -070019 unsafe {
20 api::set_flash(flash);
David Brown541860c2017-11-06 11:25:42 -070021 raw::sim_flash_align = align;
David Brownee61c832017-11-06 11:13:25 -070022 raw::flash_counter = match counter {
23 None => 0,
24 Some(ref c) => **c as libc::c_int
25 };
26 }
David Brownbdb6db72017-07-06 10:14:37 -060027 let result = unsafe { raw::invoke_boot_go(&areadesc.get_c() as *const _) as i32 };
David Brownee61c832017-11-06 11:13:25 -070028 unsafe {
29 counter.map(|c| *c = raw::flash_counter as i32);
30 api::clear_flash();
31 };
David Brownbdb6db72017-07-06 10:14:37 -060032 result
David Brownde7729e2017-01-09 10:41:35 -070033}
34
David Brown541860c2017-11-06 11:25:42 -070035pub fn boot_trailer_sz(align: u8) -> u32 {
36 unsafe { raw::boot_slots_trailer_sz(align) }
David Brownde7729e2017-01-09 10:41:35 -070037}
38
Fabio Utziga0bc9b52017-06-28 09:19:55 -030039pub fn boot_magic_sz() -> usize {
40 unsafe { raw::BOOT_MAGIC_SZ as usize }
41}
42
43pub fn boot_max_align() -> usize {
44 unsafe { raw::BOOT_MAX_ALIGN as usize }
45}
46
Fabio Utzig92be3fb2017-12-05 08:52:53 -020047pub fn ecdsa256_sign(privkey: &[u8], hash: &[u8]) -> Result<[u8; 64], &'static str> {
48 unsafe {
49 let mut signature: [u8; 64] = [0; 64];
50 if raw::ecdsa256_sign_(privkey.as_ptr(), hash.as_ptr(),
51 hash.len() as u32, signature.as_mut_ptr()) == 1 {
52 return Ok(signature);
53 }
54 return Err("Failed signature generation");
55 }
56}
57
David Brownde7729e2017-01-09 10:41:35 -070058mod raw {
59 use area::CAreaDesc;
60 use libc;
61
62 extern "C" {
63 // This generates a warning about `CAreaDesc` not being foreign safe. There doesn't appear to
64 // be any way to get rid of this warning. See https://github.com/rust-lang/rust/issues/34798
65 // for information and tracking.
David Brownbdb6db72017-07-06 10:14:37 -060066 pub fn invoke_boot_go(areadesc: *const CAreaDesc) -> libc::c_int;
David Brownde7729e2017-01-09 10:41:35 -070067 pub static mut flash_counter: libc::c_int;
68
69 pub static mut sim_flash_align: u8;
Fabio Utzig7ebb7c22017-04-26 10:59:31 -030070 pub fn boot_slots_trailer_sz(min_write_sz: u8) -> u32;
Fabio Utziga0bc9b52017-06-28 09:19:55 -030071
72 pub static BOOT_MAGIC_SZ: u32;
73 pub static BOOT_MAX_ALIGN: u32;
Fabio Utzig92be3fb2017-12-05 08:52:53 -020074
75 pub fn ecdsa256_sign_(privkey: *const u8, hash: *const u8,
76 hash_len: libc::c_uint,
77 signature: *mut u8) -> libc::c_int;
David Brownde7729e2017-01-09 10:41:35 -070078 }
79}