-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathselftest.rs
82 lines (66 loc) · 2.2 KB
/
selftest.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
use core::intrinsics::{transmute, size_of};
use core::fmt::Write;
use arch;
pub use drv;
extern {
static _selftest_start: u8;
static _selftest_end: u8;
}
pub type TestFn = fn (mut uart : &mut drv::uart::UartWriter) -> bool;
#[repr(C, packed)]
pub struct TestEntry {
pub func : TestFn,
pub name : &'static str,
}
#[macro_export]
macro_rules! selftest {
(fn $name:ident ($uart:ident) $code:block) => {
/* FIXME: TODO: Rustc will not always emit this :(
* We need __attribute__((used)) or a workaround. */
#[allow(dead_code)]
#[allow(non_upper_case_globals)]
#[linkage="external"]
#[cfg_attr(feature = "selftest", link_section = ".titanium.selftest")]
#[cfg_attr(not(feature = "selftest"), link_section = ".titanium.discard")]
pub static $name : &'static ::titanium::selftest::TestEntry = &::titanium::selftest::TestEntry {
func: { fn f($uart: &mut ::titanium::drv::uart::UartWriter) -> bool {
$code
} ;f},
name: stringify!($name),
};
}
}
/// Start selftest
#[allow(dead_code)]
fn selftest_run(mut uart : &mut drv::uart::UartWriter) {
let start : usize = &_selftest_start as *const _ as usize;
let end : usize = &_selftest_end as *const _ as usize;
let mut err_i = 0u32;
let mut ok_i = 0u32;
write!(uart, "SELFTEST START\n").unwrap();
for addr in (start..end).step_by(unsafe {size_of::<usize>()}) {
let t : &TestEntry = {
unsafe {
let addr : &usize = transmute(addr);
transmute(*addr)
}
};
write!(uart, "{}...", t.name).unwrap();
let ret = (t.func)(uart);
if ret {
ok_i += 1;
write!(uart, " OK\n").unwrap();
} else {
err_i += 1;
write!(uart, " FAIL\n").unwrap();
}
}
write!(uart, "SELFTEST END: {} ERR; {} OK; {} TOTAL\n", err_i, ok_i, ok_i + err_i).unwrap();
arch::semihosting::exit();
}
#[cfg(feature = "selftest")]
pub fn selftest(uart : &'static mut drv::uart::UartWriter) {
selftest_run(uart);
}
#[cfg(not(feature = "selftest"))]
pub fn selftest(_ : &'static mut drv::uart::UartWriter) {}