1use core::cell::Cell;
8use kernel::utilities::cells::{OptionalCell, TakeCell};
9use kernel::utilities::registers::interfaces::{ReadWriteable, Readable, Writeable};
10use kernel::utilities::registers::{
11 register_bitfields, register_structs, ReadOnly, ReadWrite, WriteOnly,
12};
13use kernel::utilities::StaticRef;
14use kernel::ErrorCode;
15
16pub trait Client<'a> {
18 fn op_done(&'a self, result: Result<(), ErrorCode>, output: &'static mut [u8]);
22}
23
24register_structs! {
25 pub OtbnRegisters {
26 (0x00 => intr_state: ReadWrite<u32, INTR::Register>),
27 (0x04 => intr_enable: ReadWrite<u32, INTR::Register>),
28 (0x08 => intr_test: WriteOnly<u32, INTR::Register>),
29 (0x0C => alert_test: WriteOnly<u32, ALERT_TEST::Register>),
30 (0x10 => cmd: ReadWrite<u32, CMD::Register>),
31 (0x14 => ctrl: ReadWrite<u32, CTRL::Register>),
32 (0x18 => status: ReadOnly<u32, STATUS::Register>),
33 (0x1C => err_bits: ReadOnly<u32, ERR_BITS::Register>),
34 (0x20 => fatal_alert_cause: ReadOnly<u32, FATAL_ALERT_CAUSE::Register>),
35 (0x24 => insn_cnt: ReadWrite<u32>),
36 (0x28 => load_checksum: ReadWrite<u32>),
37 (0x2C => _reserved0),
38 (0x4000 => imem: [ReadWrite<u32>; 1024]),
39 (0x5000 => _reserved1),
40 (0x8000 => dmem: [ReadWrite<u32>; 768]),
41 (0x8C00 => @END),
42 }
43}
44
45register_bitfields![u32,
46 INTR [
47 DONE OFFSET(0) NUMBITS(1) [],
48 ],
49 ALERT_TEST [
50 FATAL OFFSET(0) NUMBITS(1) [],
51 RECOV OFFSET(1) NUMBITS(1) [],
52 ],
53 CMD [
54 CMD OFFSET(0) NUMBITS(8) [
55 EXECUTE = 0xD8,
56 SEC_WIPE_DMEM = 0xC3,
57 SEC_WIPE_IMEM = 0x1E,
58 ],
59 ],
60 CTRL [
61 SOFTWARE_ERRS_FATAL OFFSET(0) NUMBITS(1) [],
62 ],
63 STATUS [
64 STATUS OFFSET(0) NUMBITS(8) [
65 IDLE = 0x00,
66 BUSY_EXECUTE = 0x01,
67 BUSY_SEC_WIPE_DMEM = 0x02,
68 BUSY_SEC_WIPE_IMEM = 0x03,
69 BUSY_SEC_WIPE_INT = 0x04,
70 LOCKED = 0xFF,
71 ],
72 ],
73 ERR_BITS [
74 BAD_DATA_ADDR OFFSET(0) NUMBITS(1) [],
75 BAD_INSN_ADDR OFFSET(1) NUMBITS(1) [],
76 CALL_STACK OFFSET(2) NUMBITS(1) [],
77 ILLEGAL_INSN OFFSET(3) NUMBITS(1) [],
78 LOOP_BIT OFFSET(4) NUMBITS(1) [],
79 KEY_INVAL OFFSET(5) NUMBITS(1) [],
80 RND_REP_CHK_FAIL OFFSET(6) NUMBITS(1) [],
81 RND_FIPS_CHK_FAIL OFFSET(7) NUMBITS(1) [],
82 IMEM_INTG_VIOLATION OFFSET(16) NUMBITS(1) [],
83 DMEM_INTG_VIOLATION OFFSET(17) NUMBITS(1) [],
84 REG_INTG_VIOLATION OFFSET(18) NUMBITS(1) [],
85 BUS_INTG_VIOLATION OFFSET(19) NUMBITS(1) [],
86 BAD_INTERNAL_STATE OFFSET(20) NUMBITS(1) [],
87 ILLEGAL_BUS_ACCESS OFFSET(21) NUMBITS(1) [],
88 LIFECYCLE_ESCALATION OFFSET(22) NUMBITS(1) [],
89 FATAL_SOFTWARE OFFSET(23) NUMBITS(1) [],
90 ],
91 FATAL_ALERT_CAUSE [
92 IMEM_INTG_VIOLATION OFFSET(0) NUMBITS(1) [],
93 DMEM_INTG_VIOLATION OFFSET(1) NUMBITS(1) [],
94 REG_INTG_VIOLATION OFFSET(2) NUMBITS(1) [],
95 BUS_INTG_VIOLATION OFFSET(3) NUMBITS(1) [],
96 BAD_INTERNAL_STATE OFFSET(4) NUMBITS(1) [],
97 ILLEGAL_BUS_ACCESS OFFSET(5) NUMBITS(1) [],
98 LIFECYCLE_ESCALATION OFFSET(6) NUMBITS(1) [],
99 FATAL_SOFTWARE OFFSET(7) NUMBITS(1) [],
100 ],
101];
102
103pub struct Otbn<'a> {
104 registers: StaticRef<OtbnRegisters>,
105 client: OptionalCell<&'a dyn Client<'a>>,
106
107 out_buffer: TakeCell<'static, [u8]>,
108
109 copy_address: Cell<usize>,
110}
111
112impl<'a> Otbn<'a> {
113 pub fn new(base: StaticRef<OtbnRegisters>) -> Self {
114 Otbn {
115 registers: base,
116 client: OptionalCell::empty(),
117 out_buffer: TakeCell::empty(),
118 copy_address: Cell::new(0),
119 }
120 }
121
122 pub fn handle_interrupt(&self) {
123 self.registers.intr_enable.set(0x00);
124 self.registers.intr_state.set(0xFFFF_FFFF);
125
126 if self.registers.err_bits.get() > 0 {
128 self.client.map(|client| {
129 self.out_buffer.take().map(|buf| {
130 client.op_done(Err(ErrorCode::FAIL), buf);
131 })
132 });
133 return;
134 }
135
136 if self.registers.status.matches_all(STATUS::STATUS::IDLE) {
137 let out_buf = self.out_buffer.take().unwrap();
138
139 for i in 0..(out_buf.len() / 4) {
140 let idx = i * 4;
141 let d = self.registers.dmem[self.copy_address.get() / 4 + i]
142 .get()
143 .to_ne_bytes();
144
145 out_buf[idx + 0] = d[0];
146 out_buf[idx + 1] = d[1];
147 out_buf[idx + 2] = d[2];
148 out_buf[idx + 3] = d[3];
149 }
150
151 self.client.map(|client| {
152 client.op_done(Ok(()), out_buf);
153 });
154 }
155 }
156
157 pub fn set_client(&'a self, client: &'a dyn Client<'a>) {
159 self.client.set(client);
160 }
161
162 pub fn load_binary(&self, input: &[u8]) -> Result<(), ErrorCode> {
170 if !self.registers.status.matches_all(STATUS::STATUS::IDLE) {
171 return Err(ErrorCode::BUSY);
173 }
174 if (input.len() / 4) > self.registers.imem.len() {
176 return Err(ErrorCode::SIZE);
177 }
178
179 for i in 0..(input.len() / 4) {
180 let idx = i * 4;
181
182 let mut d = (input[idx + 0] as u32) << 0;
183 d |= (input[idx + 1] as u32) << 8;
184 d |= (input[idx + 2] as u32) << 16;
185 d |= (input[idx + 3] as u32) << 24;
186
187 self.registers.imem[i].set(d);
188 }
189
190 Ok(())
191 }
192
193 pub fn load_data(&self, address: usize, data: &[u8]) -> Result<(), ErrorCode> {
199 if !self.registers.status.matches_all(STATUS::STATUS::IDLE) {
200 return Err(ErrorCode::BUSY);
202 }
203
204 for i in 0..(data.len() / 4) {
205 let idx = i * 4;
206
207 let mut d = (data[idx + 0] as u32) << 0;
208 d |= (data[idx + 1] as u32) << 8;
209 d |= (data[idx + 2] as u32) << 16;
210 d |= (data[idx + 3] as u32) << 24;
211
212 self.registers.dmem[(address / 4) + i].set(d);
213 }
214
215 Ok(())
216 }
217
218 pub fn run(
229 &self,
230 address: usize,
231 output: &'static mut [u8],
232 ) -> Result<(), (ErrorCode, &'static mut [u8])> {
233 if !self.registers.status.matches_all(STATUS::STATUS::IDLE) {
234 return Err((ErrorCode::BUSY, output));
236 }
237
238 self.registers.ctrl.modify(CTRL::SOFTWARE_ERRS_FATAL::CLEAR);
239
240 self.registers.intr_state.modify(INTR::DONE::SET);
242 self.registers.intr_enable.modify(INTR::DONE::SET);
243
244 self.out_buffer.replace(output);
245 self.copy_address.set(address);
246
247 self.registers.cmd.modify(CMD::CMD::EXECUTE);
248
249 Ok(())
250 }
251
252 pub fn clear_data(&self) {
256 self.registers.cmd.write(CMD::CMD::SEC_WIPE_DMEM);
257 self.registers.cmd.write(CMD::CMD::SEC_WIPE_IMEM);
258 }
259}