ecc608_linux/
address.rs

1use crate::{Error, Result};
2use bitfield::bitfield;
3use std::{fmt, str::FromStr};
4
5#[derive(Debug, Clone, PartialEq, Eq)]
6pub enum Zone {
7    Data,
8    Config,
9}
10
11impl FromStr for Zone {
12    type Err = Error;
13
14    fn from_str(s: &str) -> Result<Self> {
15        match s.to_lowercase().as_str() {
16            "data" => Ok(Self::Data),
17            "config" => Ok(Self::Config),
18            _ => Err(Error::invalid_address()),
19        }
20    }
21}
22
23impl fmt::Display for Zone {
24    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25        match self {
26            Self::Config => f.write_str("config"),
27            Self::Data => f.write_str("data"),
28        }
29    }
30}
31
32#[derive(Debug, PartialEq, Eq, Clone, Copy)]
33pub enum DataBuffer {
34    TempKey,
35    MessageDigest,
36    AlternateKey,
37}
38
39impl From<&DataBuffer> for u8 {
40    fn from(v: &DataBuffer) -> Self {
41        match v {
42            DataBuffer::TempKey => 0,
43            DataBuffer::MessageDigest => 1,
44            DataBuffer::AlternateKey => 2,
45        }
46    }
47}
48
49impl From<u8> for DataBuffer {
50    fn from(v: u8) -> Self {
51        match v & 3 {
52            0 => Self::TempKey,
53            1 => Self::MessageDigest,
54            2 => Self::AlternateKey,
55            _ => unreachable!(),
56        }
57    }
58}
59
60#[derive(Debug, PartialEq, Eq, Clone, Copy)]
61pub enum Address {
62    Otp(OffsetAddress),
63    Config(OffsetAddress),
64    Data(DataAddress),
65}
66
67bitfield! {
68    #[derive(PartialEq, Eq, Clone, Copy)]
69    pub struct OffsetAddress(u16);
70    impl Debug;
71    u8, offset, set_offset: 10, 8;
72    u8, block, set_block: 12, 11;
73}
74
75bitfield! {
76    #[derive(PartialEq, Clone, Copy, Eq)]
77    pub struct DataAddress(u16);
78    impl Debug;
79    u8, block, set_block: 3, 0;
80    u8, offset, set_offset: 10, 8;
81    u8, slot, set_slot: 14, 11;
82}
83
84impl From<&Address> for u16 {
85    fn from(v: &Address) -> Self {
86        match v {
87            Address::Otp(addr) => addr.0,
88            Address::Config(addr) => addr.0,
89            Address::Data(addr) => addr.0,
90        }
91    }
92}
93
94impl Address {
95    pub fn otp(block: u8, offset: u8) -> Result<Self> {
96        if block > 4 || offset > 7 {
97            return Err(Error::invalid_address());
98        }
99        let mut address = OffsetAddress(0);
100        address.set_block(block);
101        address.set_offset(offset);
102        Ok(Self::Otp(address))
103    }
104
105    pub fn config(block: u8, offset: u8) -> Result<Self> {
106        if block > 4 || offset > 7 {
107            return Err(Error::invalid_address());
108        }
109        let mut address = OffsetAddress(0);
110        address.set_block(block);
111        address.set_offset(offset);
112        Ok(Self::Config(address))
113    }
114
115    pub fn slot_config(slot: u8) -> Result<Self> {
116        if slot > 15 {
117            return Err(Error::invalid_address());
118        }
119        let (block, offset) = if slot <= 5 {
120            (0, (20 + slot * 2) >> 2)
121        } else {
122            (1, ((slot - 5) * 2) >> 2)
123        };
124        Self::config(block, offset)
125    }
126
127    pub fn key_config(slot: u8) -> Result<Self> {
128        if slot > 15 {
129            return Err(Error::invalid_address());
130        }
131        Self::config(3, (slot * 2) >> 2)
132    }
133
134    pub fn data(slot: u8, block: u8, offset: u8) -> Result<Self> {
135        if slot > 15
136            || (slot < 8 && block > 1)
137            || (slot == 8 && block > 15)
138            || (slot > 8 && block > 7)
139        {
140            return Err(Error::invalid_address());
141        }
142        let mut address = DataAddress(0);
143        address.set_block(block);
144        address.set_offset(offset);
145        address.set_slot(slot);
146        Ok(Self::Data(address))
147    }
148
149    pub fn zone(&self) -> u8 {
150        match self {
151            Self::Config(_) => 0x00,
152            Self::Otp(_) => 0x01,
153            Self::Data(_) => 0x02,
154        }
155    }
156}