esp_partition_table/
types.rs

1use crate::PartitionError;
2
3/// Partition type and subtype
4#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
5pub enum PartitionType {
6    /// Application partition
7    App(AppPartitionType),
8
9    /// Data partition
10    Data(DataPartitionType),
11
12    /// Any type
13    #[default]
14    Any,
15
16    /// User-defined type
17    User(u8, u8),
18}
19
20impl From<AppPartitionType> for PartitionType {
21    fn from(subtype: AppPartitionType) -> Self {
22        Self::App(subtype)
23    }
24}
25
26impl From<DataPartitionType> for PartitionType {
27    fn from(subtype: DataPartitionType) -> Self {
28        Self::Data(subtype)
29    }
30}
31
32impl TryFrom<(u8, u8)> for PartitionType {
33    type Error = PartitionError;
34
35    fn try_from((raw_type, raw_subtype): (u8, u8)) -> Result<Self, Self::Error> {
36        Ok(match raw_type {
37            0x00 => Self::App(raw_subtype.try_into()?),
38            0x01 => Self::Data(raw_subtype.try_into()?),
39            0x40..=0xfe => Self::User(raw_type, raw_subtype),
40            0xff => Self::Any,
41            _ => return Err(PartitionError::InvalidType(raw_type)),
42        })
43    }
44}
45
46impl TryFrom<&[u8; 2]> for PartitionType {
47    type Error = PartitionError;
48
49    fn try_from([raw_type, raw_subtype]: &[u8; 2]) -> Result<Self, Self::Error> {
50        (*raw_type, *raw_subtype).try_into()
51    }
52}
53
54impl TryFrom<[u8; 2]> for PartitionType {
55    type Error = PartitionError;
56
57    fn try_from([raw_type, raw_subtype]: [u8; 2]) -> Result<Self, Self::Error> {
58        (raw_type, raw_subtype).try_into()
59    }
60}
61
62impl TryFrom<&[u8]> for PartitionType {
63    type Error = PartitionError;
64
65    fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
66        <[u8; 2]>::try_from(slice)
67            .map_err(|_| PartitionError::NotEnoughData)?
68            .try_into()
69    }
70}
71
72impl TryFrom<PartitionType> for (u8, u8) {
73    type Error = PartitionError;
74
75    fn try_from(ty: PartitionType) -> Result<Self, Self::Error> {
76        use PartitionType::*;
77        Ok(match ty {
78            App(subtype) => (0x00, subtype.try_into()?),
79            Data(subtype) => (0x01, subtype.into()),
80            User(usertype @ 0x40..=0xfe, subtype) => (usertype, subtype),
81            User(usertype, _) => return Err(PartitionError::InvalidUserType(usertype)),
82            Any => (0xff, 0x00),
83        })
84    }
85}
86
87impl TryFrom<PartitionType> for [u8; 2] {
88    type Error = PartitionError;
89
90    fn try_from(ty: PartitionType) -> Result<Self, Self::Error> {
91        let (type_, subtype) = ty.try_into()?;
92        Ok([type_, subtype])
93    }
94}
95
96impl PartitionType {
97    /// Application partition alignment
98    const APP_ALIGN: u32 = 0x10000;
99
100    /// Data partition alignment
101    const DATA_ALIGN: u32 = 0x1000;
102
103    /// Get partition alignment
104    pub fn align(&self) -> u32 {
105        match self {
106            PartitionType::App(_) => Self::APP_ALIGN,
107            _ => Self::DATA_ALIGN,
108        }
109    }
110
111    /// Check offset for alignment
112    pub fn check_offset(&self, offset: u32) -> Result<(), PartitionError> {
113        if offset & (self.align() - 1) == 0 {
114            Ok(())
115        } else {
116            Err(PartitionError::InvalidAlignment)
117        }
118    }
119
120    /// Convert type and subtype from binary representation
121    pub fn from_bytes(data: &[u8; 2]) -> Result<Self, PartitionError> {
122        data.try_into()
123    }
124
125    /// Convert type and subtype to binary representation
126    pub fn to_bytes(&self, data: &mut [u8; 2]) -> Result<(), PartitionError> {
127        let (type_, subtype) = (*self).try_into()?;
128        data[0] = type_;
129        data[1] = subtype;
130        Ok(())
131    }
132}
133
134/// Application partition subtype
135#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
136pub enum AppPartitionType {
137    /// Factory application
138    #[default]
139    Factory,
140
141    /// OTA application
142    Ota(u8),
143
144    /// Test application
145    Test,
146}
147
148impl TryFrom<u8> for AppPartitionType {
149    type Error = PartitionError;
150
151    fn try_from(raw: u8) -> Result<Self, Self::Error> {
152        Ok(match raw {
153            0x00 => Self::Factory,
154            0x10..=0x1f => Self::Ota(raw - 0x10),
155            0x20 => Self::Test,
156            _ => return Err(PartitionError::InvalidSubType(raw)),
157        })
158    }
159}
160
161impl TryFrom<AppPartitionType> for u8 {
162    type Error = PartitionError;
163
164    fn try_from(ty: AppPartitionType) -> Result<Self, Self::Error> {
165        use AppPartitionType::*;
166        Ok(match ty {
167            Factory => 0x00,
168            Ota(number @ 0x00..=0x0f) => number + 0x10,
169            Ota(number) => return Err(PartitionError::InvalidOtaNumber(number)),
170            Test => 0x20,
171        })
172    }
173}
174
175/// Data partition subtype
176#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
177#[repr(u8)]
178pub enum DataPartitionType {
179    /// OTA data
180    #[default]
181    Ota = 0x00,
182
183    /// Phy data
184    Phy = 0x01,
185
186    /// Non-volatile storage data
187    Nvs = 0x02,
188
189    /// Core dump
190    CoreDump = 0x03,
191
192    /// Encrypted non-volatile storage keys
193    NvsKeys = 0x04,
194
195    /// Efuse data
196    EfuseEm = 0x05,
197
198    /// Undefined data
199    Undefined = 0x06,
200
201    /// ESP HTTPd data
202    EspHttpd = 0x80,
203
204    /// FAT partition
205    Fat = 0x81,
206
207    /// SPIFFS partition
208    SpiFfs = 0x82,
209
210    /// LittleFS partition
211    LittleFS = 0x83,
212}
213
214impl TryFrom<u8> for DataPartitionType {
215    type Error = PartitionError;
216
217    fn try_from(raw: u8) -> Result<Self, Self::Error> {
218        Ok(match raw {
219            0x00 => Self::Ota,
220            0x01 => Self::Phy,
221            0x02 => Self::Nvs,
222            0x03 => Self::CoreDump,
223            0x04 => Self::NvsKeys,
224            0x05 => Self::EfuseEm,
225            0x06 => Self::Undefined,
226            0x80 => Self::EspHttpd,
227            0x81 => Self::Fat,
228            0x82 => Self::SpiFfs,
229            0x83 => Self::LittleFS,
230            _ => return Err(PartitionError::InvalidSubType(raw)),
231        })
232    }
233}
234
235impl From<DataPartitionType> for u8 {
236    fn from(ty: DataPartitionType) -> Self {
237        ty as _
238    }
239}