1use super::error::{Error, ErrorKind};
2use core::ops::{Range, RangeInclusive};
3use core::slice::from_ref;
4const ZONE_READWRITE_32: u8 = 0x80;
6
7#[derive(Copy, Clone, Debug)]
9pub enum Size {
10 Word = 0x04,
11 Block = 0x20,
12}
13
14impl Size {
15 pub(crate) fn len(&self) -> usize {
16 match self {
17 Self::Word => Self::Word as usize,
18 Self::Block => Self::Block as usize,
19 }
20 }
21}
22
23#[derive(Copy, Clone, Debug)]
24pub enum Zone {
25 Config = 0x00,
26 Data = 0x01,
27 Otp = 0x02,
28}
29
30impl Zone {
31 pub fn locate_index(index: usize) -> (u8, u8, u8) {
33 let block = index / Size::Block.len();
34 let offset = index % Size::Block.len() / Size::Word.len();
35 let position = index % Size::Word.len();
36 (block as u8, offset as u8, position as u8)
37 }
38
39 pub(crate) fn get_slot_addr(&self, slot: Slot, block: u8) -> Result<u16, Error> {
40 match self {
41 Self::Data if slot.is_private_key() && block == 0 => Ok((slot as u16) << 3),
42 Self::Data if slot.is_certificate() && block <= 2 => {
43 Ok((slot as u16) << 3 | (block as u16) << 8)
44 }
45 _ => Err(ErrorKind::BadParam.into()),
46 }
47 }
48
49 pub(crate) fn get_addr(&self, block: u8, offset: u8) -> Result<u16, Error> {
50 if block.leading_zeros() < 3 || offset.leading_zeros() < 4 {
51 return Err(ErrorKind::BadParam.into());
52 }
53 let block = (block as u16) << 3;
54 let offset = (offset & 0x07) as u16;
55 let addr = block | offset;
56 match self {
57 Self::Config | Self::Otp => Ok(addr),
58 Self::Data => Err(ErrorKind::BadParam.into()),
60 }
61 }
62
63 pub(crate) fn encode(&self, size: Size) -> u8 {
64 match size {
65 Size::Word => *self as u8,
66 Size::Block => *self as u8 | ZONE_READWRITE_32,
67 }
68 }
69}
70
71#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
72pub enum Slot {
73 PrivateKey00 = 0x00,
75 PrivateKey01 = 0x01,
76 PrivateKey02 = 0x02,
77 PrivateKey03 = 0x03,
78 PrivateKey04 = 0x04,
79 PrivateKey05 = 0x05,
80 PrivateKey06 = 0x06,
81 PrivateKey07 = 0x07,
82 Data08 = 0x08,
84 Certificate09 = 0x09,
86 Certificate0a = 0x0a,
87 Certificate0b = 0x0b,
88 Certificate0c = 0x0c,
89 Certificate0d = 0x0d,
90 Certificate0e = 0x0e,
91 Certificate0f = 0x0f,
92}
93
94impl Slot {
95 pub fn is_private_key(&self) -> bool {
97 *self <= Self::PrivateKey07
98 }
99
100 pub fn is_certificate(&self) -> bool {
102 Self::Certificate09 <= *self
103 }
104
105 pub fn keys() -> KeysIter {
106 KeysIter(0x00..=0x0f)
107 }
108}
109
110pub struct KeysIter(RangeInclusive<usize>);
111
112impl Iterator for KeysIter {
113 type Item = Slot;
114 fn next(&mut self) -> Option<Self::Item> {
115 use Slot::*;
116 self.0.next().and_then(|i| match i {
117 x if x == PrivateKey00 as usize => PrivateKey00.into(),
118 x if x == PrivateKey01 as usize => PrivateKey01.into(),
119 x if x == PrivateKey02 as usize => PrivateKey02.into(),
120 x if x == PrivateKey03 as usize => PrivateKey03.into(),
121 x if x == PrivateKey04 as usize => PrivateKey04.into(),
122 x if x == PrivateKey05 as usize => PrivateKey05.into(),
123 x if x == PrivateKey06 as usize => PrivateKey06.into(),
124 x if x == PrivateKey07 as usize => PrivateKey07.into(),
125 x if x == Data08 as usize => Data08.into(),
126 x if x == Certificate09 as usize => Certificate09.into(),
127 x if x == Certificate0a as usize => Certificate0a.into(),
128 x if x == Certificate0b as usize => Certificate0b.into(),
129 x if x == Certificate0c as usize => Certificate0c.into(),
130 x if x == Certificate0d as usize => Certificate0d.into(),
131 x if x == Certificate0e as usize => Certificate0e.into(),
132 x if x == Certificate0f as usize => Certificate0f.into(),
133 _ => None,
134 })
135 }
136}
137
138pub(crate) struct CertificateRepr(RangeInclusive<usize>);
139
140impl CertificateRepr {
141 pub(crate) fn new() -> Self {
142 Self(0..=2)
143 }
144}
145
146impl Iterator for CertificateRepr {
147 type Item = &'static [Range<usize>];
148 fn next(&mut self) -> Option<Self::Item> {
149 self.0.next().and_then(|i| match i {
150 0 => from_ref(&(0x04..0x20)).into(),
151 1 => [0x00..0x04, 0x08..0x20].as_ref().into(),
152 2 => from_ref(&(0x00..0x08)).into(),
153 _ => None,
154 })
155 }
156}
157
158#[cfg(test)]
159mod tests {
160 use super::*;
161 use crate::client::Memory;
162 use core::convert::identity;
163 use core::iter::repeat;
164 use heapless::Vec;
165 use Slot::*;
166 use Zone::*;
167
168 #[test]
169 fn locate_index() {
170 assert_eq!(
171 (0, 5, 0),
172 Zone::locate_index(Memory::<(), ()>::SLOT_CONFIG_INDEX)
173 );
174 assert_eq!(
175 (2, 6, 2),
176 Zone::locate_index(Memory::<(), ()>::CHIP_OPTIONS_INDEX)
177 );
178 assert_eq!(
179 (3, 0, 0),
180 Zone::locate_index(Memory::<(), ()>::KEY_CONFIG_INDEX)
181 );
182 }
183
184 #[test]
185 fn get_slot_addr() {
186 assert_eq!(0x0038, Data.get_slot_addr(PrivateKey07, 0).unwrap());
187 for (&addr, block) in [0x0078, 0x0178, 0x0278].iter().zip(0..=2) {
188 let result = Data.get_slot_addr(Certificate0f, block).unwrap();
189 assert_eq!(addr, result);
190 }
191 }
192
193 #[test]
194 fn get_addr() {
195 assert_eq!(0x0005, Config.get_addr(0, 5).unwrap());
196 assert_eq!(0x0016, Config.get_addr(2, 6).unwrap());
197 assert_eq!(0x0018, Config.get_addr(3, 0).unwrap());
198 }
199
200 #[test]
201 fn certificate_representation() {
202 let slot_buffer = repeat(0)
203 .take(4)
204 .chain(0x00..0x20)
205 .chain(repeat(0).take(4))
206 .chain(0x20..0x40)
207 .chain(repeat(0).take(24))
208 .collect::<Vec<u8, 96>>();
209 assert_eq!(Size::Block.len() * 3, slot_buffer.len());
210 slot_buffer
211 .chunks(Size::Block.len())
212 .zip(CertificateRepr::new())
213 .scan(0, |i, (chunk, ranges)| {
214 for range in ranges {
215 for j in &chunk[range.clone()] {
216 assert_eq!(i, j);
217 *i += 1;
218 }
219 }
220 Some(())
221 })
222 .for_each(identity)
223 }
224}