amebazii/types/enums.rs
1use serde::{Deserialize, Serialize};
2
3use crate::{
4 error::Error,
5 util::{hmac_md5, hmac_sha256, md5, sha256},
6};
7
8/// Enum representing different image types.
9///
10/// This enum defines various image types used within the system. The image types
11/// are associated with different identifiers, and the enum also includes a fallback
12/// type for unknown image types.
13///
14/// However, note that *image type* refers to the `SubImage` of the firmware image.
15#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
16#[repr(u8)]
17pub enum ImageType {
18 Parttab,
19 Boot,
20 FHWSS,
21 FHWSNS,
22 FWLS,
23 Isp,
24 Voe, // Video output encoder
25 Wln, // Wireless network ?
26 Xip, // Executable in place
27 Wowln, // Wake-on-Wireless-LAN ?
28 Cinit, // Custom initialization ?
29 Cpfw,
30 Unknown = 0x3F,
31}
32
33impl TryFrom<u8> for ImageType {
34 type Error = Error;
35
36 /// Attempts to convert a `u8` value to an `ImageType` variant.
37 ///
38 /// This method tries to map a `u8` value to the corresponding `ImageType` enum variant.
39 /// If the value is not valid, it returns an error of type `Error::UnknownImageType`.
40 ///
41 /// # Parameters
42 /// - `value`: The `u8` value representing the image type.
43 ///
44 /// # Returns
45 /// - `ImageType`: A valid `ImageType` variant if the value matches.
46 /// - `Error::UnknownImageType`: An error if the value does not match any known image type.
47 ///
48 /// # Example
49 /// ```
50 /// use amebazii::types::enums::ImageType;
51 /// let image_type = ImageType::try_from(1).unwrap();
52 /// assert_eq!(image_type, ImageType::Boot); // Valid conversion.
53 /// ```
54 fn try_from(value: u8) -> Result<Self, Self::Error> {
55 match value {
56 0 => Ok(ImageType::Parttab),
57 1 => Ok(ImageType::Boot),
58 2 => Ok(ImageType::FHWSS),
59 3 => Ok(ImageType::FHWSNS),
60 4 => Ok(ImageType::FWLS),
61 // REVISIT: mark unsupported images
62 5 => Ok(ImageType::Isp),
63 6 => Ok(ImageType::Voe),
64 7 => Ok(ImageType::Wln),
65 8 => Ok(ImageType::Xip),
66 9 => Ok(ImageType::Wowln),
67 10 => Ok(ImageType::Cinit),
68 11 => Ok(ImageType::Cpfw),
69 0x3F => Ok(ImageType::Unknown),
70 _ => Err(Error::UnknownImageType(value)),
71 }
72 }
73}
74
75/// Enum representing different section types in memory.
76///
77/// This enum defines the types of memory sections that can exist, each represented
78/// by a specific identifier (u8 value). These sections correspond to various types of
79/// memory regions, such as data cache memory (DTCM), instruction cache memory (ITCM),
80/// and other specialized memory regions.
81///
82/// # Variants
83/// - `DTCM`: Data tightly coupled memory (0x80).
84/// - `ITCM`: Instruction tightly coupled memory (0x81).
85/// - `SRAM`: Static RAM (0x82).
86/// - `PSRAM`: Pseudo-static RAM (0x83).
87/// - `LPDDR`: Low power DDR memory (0x84).
88/// - `XIP`: Execute-In-Place memory (0x85), containing raw binary with compiled code.
89///
90/// The `XIP` variant refers to memory regions that can execute code directly from the memory,
91/// without the need to copy the code into RAM.
92///
93/// # Example
94/// ```
95/// use amebazii::types::enums::SectionType;
96///
97/// let section = SectionType::try_from(0x80).unwrap();
98/// assert_eq!(section, SectionType::DTCM); // Successfully converts to DTCM.
99/// ```
100///
101/// # Error Handling
102/// If the provided value doesn't correspond to a known section type, an error
103/// (`Error::UnknownSectionType`) will be returned.
104#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
105#[repr(u8)]
106pub enum SectionType {
107 DTCM = 0x80,
108 ITCM,
109 SRAM,
110 PSRAM,
111 LPDDR,
112 /// Execute-In-Place (XIP) contains the raw binary with all
113 /// compiled code.
114 XIP,
115}
116
117impl TryFrom<u8> for SectionType {
118 type Error = Error;
119
120 /// Tries to convert a `u8` value into a corresponding `SectionType` variant.
121 ///
122 /// This function maps a `u8` value to its corresponding `SectionType` enum variant.
123 /// If the value does not match a valid section type, it returns an error with
124 /// the message indicating an invalid section type.
125 ///
126 /// # Parameters
127 /// - `value`: The `u8` value representing the section type.
128 ///
129 /// # Returns
130 /// - `SectionType`: A valid `SectionType` variant if the value matches.
131 /// - `Error::UnknownSectionType`: An error if the value doesn't match a known section type.
132 ///
133 /// # Example
134 /// ```
135 /// use amebazii::types::enums::SectionType;
136 ///
137 /// let section = SectionType::try_from(0x84).unwrap();
138 /// assert_eq!(section, SectionType::LPDDR); // Successfully converts to LPDDR.
139 /// ```
140 fn try_from(value: u8) -> Result<Self, Self::Error> {
141 match value {
142 0x80 => Ok(SectionType::DTCM),
143 0x81 => Ok(SectionType::ITCM),
144 0x82 => Ok(SectionType::SRAM),
145 0x83 => Ok(SectionType::PSRAM),
146 0x84 => Ok(SectionType::LPDDR),
147 0x85 => Ok(SectionType::XIP),
148 _ => Err(Error::UnknownSectionType(format!(
149 "Invalid section type: {}",
150 value
151 ))),
152 }
153 }
154}
155
156/// Available sizes for XIP (Execute-In-Place) page remapping.
157///
158/// This enum defines different page sizes used in XIP remapping, with each variant
159/// representing a specific page size in kilobytes.
160///
161/// # Variants
162/// - `_16K`: Represents a 16 KB page size (0).
163/// - `_32K`: Represents a 32 KB page size (1).
164/// - `_64K`: Represents a 64 KB page size (2).
165#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, Default)]
166#[repr(u8)]
167pub enum XipPageRemapSize {
168 #[default]
169 _16K = 0,
170 _32K,
171 _64K,
172}
173
174impl TryFrom<u8> for XipPageRemapSize {
175 type Error = Error;
176
177 /// Attempts to convert a `u8` value to an `XipPageRemapSize` variant.
178 ///
179 /// This method maps a `u8` value to the corresponding `XipPageRemapSize` variant.
180 /// If the value is not valid, it returns an error with a message indicating the
181 /// invalid page remap size.
182 ///
183 /// # Parameters
184 /// - `value`: The `u8` value representing the XIP page remap size.
185 ///
186 /// # Returns
187 /// - `XipPageRemapSize`: The corresponding `XipPageRemapSize` variant if the value matches.
188 /// - `Error::InvalidEnumValue`: An error if the value doesn't match a valid remap size.
189 ///
190 /// # Example
191 /// ```
192 /// use amebazii::types::enums::XipPageRemapSize;
193 ///
194 /// let size = XipPageRemapSize::try_from(2).unwrap();
195 /// assert_eq!(size, XipPageRemapSize::_64K); // Successfully converts to 64 KB.
196 /// ```
197 fn try_from(value: u8) -> Result<Self, Self::Error> {
198 match value {
199 0 => Ok(XipPageRemapSize::_16K),
200 1 => Ok(XipPageRemapSize::_32K),
201 2 => Ok(XipPageRemapSize::_64K),
202 _ => Err(Error::InvalidEnumValue(format!(
203 "Invalid XIP page remap size: {}",
204 value
205 ))),
206 }
207 }
208}
209
210impl XipPageRemapSize {
211 /// Returns the size of the page in bytes for the given `XipPageRemapSize` variant.
212 ///
213 /// This function returns the page size corresponding to the variant in bytes.
214 /// The page sizes are predefined as 16 KB, 32 KB, and 64 KB.
215 ///
216 /// # Returns
217 /// - `u32`: The page size in bytes.
218 pub fn page_size(&self) -> u32 {
219 match self {
220 XipPageRemapSize::_16K => 0x4000,
221 XipPageRemapSize::_32K => 0x8000,
222 XipPageRemapSize::_64K => 0x10000,
223 }
224 }
225}
226
227// Defined in parse_json_config
228/// Supported encryption algorithms.
229///
230/// This enum defines the supported encryption algorithms, each represented by a specific
231/// identifier (u16 value). The available algorithms include `Ecb` (Electronic Codebook),
232/// `Cbc` (Cipher Block Chaining), and `Other` for any unspecified or custom algorithms.
233///
234/// # Variants
235/// - `Ecb`: Electronic Codebook mode encryption (0).
236/// - `Cbc`: Cipher Block Chaining mode encryption (1).
237/// - `Other`: Represents other custom or unsupported encryption algorithms (0xFF).
238#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Default, Serialize, Deserialize)]
239#[repr(u16)]
240pub enum EncryptionAlgo {
241 Ecb,
242 Cbc,
243 #[default]
244 Other = 0xFF,
245}
246
247impl TryFrom<u16> for EncryptionAlgo {
248 type Error = Error;
249
250 /// Tries to convert a `u16` value to an `EncryptionAlgo` variant.
251 ///
252 /// # Parameters
253 /// - `value`: The `u16` value representing the encryption algorithm.
254 ///
255 /// # Returns
256 /// - `Ok(EncryptionAlgo)`: The corresponding `EncryptionAlgo` variant if the value matches.
257 /// - `Err(Error::InvalidEnumValue)`: An error if the value doesn't match a valid encryption algorithm.
258 ///
259 /// # Example
260 /// ```
261 /// use amebazii::types::enums::EncryptionAlgo;
262 ///
263 /// let algo = EncryptionAlgo::try_from(0).unwrap();
264 /// assert_eq!(algo, EncryptionAlgo::Ecb); // Successfully converts to Ecb.
265 /// ```
266 fn try_from(value: u16) -> Result<Self, Self::Error> {
267 match value {
268 0 => Ok(EncryptionAlgo::Ecb),
269 1 => Ok(EncryptionAlgo::Cbc),
270 0xFF => Ok(EncryptionAlgo::Other),
271 _ => Err(Error::InvalidEnumValue(format!(
272 "Invalid encryption algorithm: {}",
273 value
274 ))),
275 }
276 }
277}
278
279// --- Hash Algorithms ---
280
281// Defined in parse_json_config
282/// Supported various hash algorithms.
283///
284/// This enum defines the supported hash algorithms, each represented by a specific
285/// identifier (u16 value). The available algorithms include `Md5`, `Sha256`, and `Other`
286/// for unspecified or custom algorithms.
287///
288/// # Variants
289/// - `Md5`: MD5 hash algorithm (0x00).
290/// - `Sha256`: SHA-256 hash algorithm (0x01).
291/// - `Other`: Represents other custom or unsupported hash algorithms (0xFF).
292///
293/// # Example
294/// ```
295/// use amebazii::types::enums::HashAlgo;
296///
297/// let algo = HashAlgo::try_from(1).unwrap();
298/// assert_eq!(algo, HashAlgo::Sha256); // Successfully converts to Sha256.
299/// ```
300#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Default, Serialize, Deserialize)]
301#[repr(u16)]
302pub enum HashAlgo {
303 Md5 = 0x00,
304 Sha256,
305 #[default]
306 Other = 0xFF,
307}
308
309impl TryFrom<u16> for HashAlgo {
310 type Error = Error;
311
312 /// Tries to convert a `u16` value to a corresponding `HashAlgo` variant.
313 ///
314 /// # Parameters
315 /// - `value`: The `u16` value representing the hash algorithm.
316 ///
317 /// # Returns
318 /// - `Ok(HashAlgo)`: The corresponding `HashAlgo` variant if the value matches.
319 /// - `Err(Error::InvalidEnumValue)`: An error if the value doesn't match a valid hash algorithm.
320 fn try_from(value: u16) -> Result<Self, Self::Error> {
321 match value {
322 0 => Ok(HashAlgo::Md5),
323 1 => Ok(HashAlgo::Sha256),
324 0xFF => Ok(HashAlgo::Other),
325 _ => Err(Error::InvalidEnumValue(format!(
326 "Invalid hash algorithm: {}",
327 value
328 ))),
329 }
330 }
331}
332
333impl HashAlgo {
334 /// Computes the hash of the provided buffer using the specified algorithm.
335 ///
336 /// If a key is provided, HMAC (Hash-based Message Authentication Code) is used.
337 ///
338 /// # Parameters
339 /// - `buffer`: A byte slice containing the data to be hashed.
340 /// - `key`: An optional byte slice containing the key for HMAC. If `None`, the raw hash is computed.
341 ///
342 /// # Returns
343 /// - `Ok(Vec<u8>)`: The computed hash as a vector of bytes.
344 /// - `Err(Error::UnsupportedHashAlgo)`: An error if an unsupported hash algorithm is chosen.
345 ///
346 /// # Example
347 /// ```
348 /// use amebazii::types::enums::HashAlgo;
349 ///
350 /// let data = b"some data to hash";
351 /// let algo = HashAlgo::Md5;
352 /// let result = algo.compute_hash(data, None).unwrap();
353 /// assert_eq!(result.len(), 16); // MD5 produces a 16-byte hash.
354 /// ```
355 pub fn compute_hash(&self, buffer: &[u8], key: Option<&[u8]>) -> Result<Vec<u8>, Error> {
356 match self {
357 HashAlgo::Sha256 => match key {
358 Some(key_data) => {
359 return Ok(hmac_sha256(&key_data, &buffer)?.to_vec());
360 }
361 None => {
362 return Ok(sha256(&buffer)?.to_vec());
363 }
364 },
365 HashAlgo::Md5 => match key {
366 Some(key_data) => {
367 return Ok(hmac_md5(&key_data, &buffer)?.to_vec());
368 }
369 None => {
370 return Ok(md5(&buffer)?.to_vec());
371 }
372 },
373 _ => {
374 return Err(Error::UnsupportedHashAlgo(*self as u8));
375 }
376 }
377 }
378}
379
380/// Enum representing all different types of partitions. (as per _convert_pt_type)
381///
382/// # Variants
383/// - `PartTab`: Partition table (0).
384/// - `Boot`: Boot partition (1).
385/// - `Sys`: System partition (2).
386///
387/// - `Fw1`: Firmware partition 1.
388/// - `Fw2`: Firmware partition 2.
389
390/// - `Cal`: Calibration partition (5).
391/// - `User`: User data partition (6).
392/// - `Var`: Variable partition (7).
393/// - `MP`: Main partition (8).
394/// - `Rdp`: Reserved partition (9).
395///
396/// # Example
397/// ```
398/// use amebazii::types::enums::PartitionType;
399///
400/// let part = PartitionType::try_from(1).unwrap();
401/// assert_eq!(part, PartitionType::Boot); // Successfully converts to Boot partition.
402/// ```
403#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
404#[repr(u8)]
405pub enum PartitionType {
406 /// Partition table (0).
407 PartTab = 0,
408 /// Boot partition (1).
409 Boot,
410
411 /// System partition (4).
412 Sys,
413 /// Calibration partition (5).
414 Cal,
415 /// User data partition (6).
416 User,
417
418 /// Firmware partition 1 (2).
419 Fw1,
420 /// Firmware partition 2 (3).
421 Fw2,
422
423 /// Variable partition (7).
424 Var,
425 /// Main partition (8).
426 MP,
427 /// Reserved partition (9).
428 Rdp,
429
430 Unknown = 10,
431}
432
433impl TryFrom<u8> for PartitionType {
434 type Error = Error;
435
436 /// Attempts to convert a `u8` value to the corresponding `PartitionType` variant.
437 ///
438 /// This method maps a `u8` value to the appropriate `PartitionType` variant.
439 /// If the value is not valid, it returns an error indicating that the partition type
440 /// is invalid.
441 ///
442 /// # Parameters
443 /// - `value`: The `u8` value representing the partition type.
444 ///
445 /// # Returns
446 /// - `Ok(PartitionType)`: The corresponding `PartitionType` variant if the value matches.
447 /// - `Err(Error::InvalidEnumValue)`: An error if the value doesn't match a valid partition type.
448 fn try_from(value: u8) -> Result<Self, Self::Error> {
449 match value {
450 0 => Ok(PartitionType::PartTab),
451 1 => Ok(PartitionType::Boot),
452 2 => Ok(PartitionType::Sys),
453 3 => Ok(PartitionType::Cal),
454 4 => Ok(PartitionType::User),
455 5 => Ok(PartitionType::Fw1),
456 6 => Ok(PartitionType::Fw2),
457 7 => Ok(PartitionType::Var),
458 8 => Ok(PartitionType::MP),
459 9 => Ok(PartitionType::Rdp),
460 10 => Ok(PartitionType::Unknown),
461 _ => Err(Error::InvalidEnumValue(format!(
462 "Invalid partition type: {}",
463 value
464 ))),
465 }
466 }
467}
468
469/// Enum representing different key export operations.
470///
471/// This enum defines the operations for key export, represented by a specific `u8` value.
472/// The available operations include:
473/// - `None`: No key export operation (0).
474/// - `Latest`: Export the latest key (1).
475/// - `Both`: Export both keys (2).
476///
477/// # Variants
478/// - `None`: No key export operation (0).
479/// - `Latest`: Only export the latest key (1).
480/// - `Both`: Export both the latest and previous keys (2).
481///
482#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, Default)]
483#[repr(u8)]
484pub enum KeyExportOp {
485 /// No key export operation (0).
486 #[default]
487 None = 0,
488 /// Export the latest key (1).
489 Latest,
490 /// Export both keys (2).
491 Both,
492}
493
494impl TryFrom<u8> for KeyExportOp {
495 type Error = Error;
496
497 /// Tries to convert a `u8` value to the corresponding `KeyExportOp` variant.
498 ///
499 /// # Parameters
500 /// - `value`: The `u8` value representing the key export operation.
501 ///
502 /// # Returns
503 /// - `Ok(KeyExportOp)`: The corresponding `KeyExportOp` variant if the value matches.
504 /// - `Err(Error::InvalidEnumValue)`: An error if the value doesn't match a valid key export operation.
505 fn try_from(value: u8) -> Result<Self, Self::Error> {
506 match value {
507 0 => Ok(KeyExportOp::None),
508 1 => Ok(KeyExportOp::Latest),
509 2 => Ok(KeyExportOp::Both),
510 _ => Err(Error::InvalidEnumValue(format!(
511 "Invalid key export type: {}",
512 value
513 ))),
514 }
515 }
516}
517
518/// Represents different flash sizes based on the corresponding size codes.
519///
520/// This enum defines the possible flash sizes, each represented by a specific
521/// 16-bit value. The sizes range from 2MB to 1MB, with different values for each
522/// size. The default value corresponds to a 2MB flash size.
523#[allow(non_camel_case_types)]
524#[derive(Debug, Copy, Clone, Serialize, Deserialize, Default)]
525#[repr(u16)]
526pub enum FlashSize {
527 #[default]
528 Size_2M = 0xFFFF,
529 Size_32M = 0x7FFF,
530 Size_16M = 0x3FFF,
531 Size_8M = 0x1FFF,
532 Size_4M = 0x0FFF,
533 Size_1M = 0x07FF,
534}
535
536impl From<u16> for FlashSize {
537 /// Converts a 16-bit value into a `FlashSize` enum.
538 ///
539 /// # Arguments:
540 /// - `value`: A 16-bit unsigned integer representing a flash size.
541 ///
542 /// # Returns:
543 /// - The corresponding `FlashSize` enum variant.
544 fn from(value: u16) -> Self {
545 match value {
546 0xFFFF => FlashSize::Size_2M,
547 0x7FFF => FlashSize::Size_32M,
548 0x3FFF => FlashSize::Size_16M,
549 0x1FFF => FlashSize::Size_8M,
550 0x0FFF => FlashSize::Size_4M,
551 0x07FF => FlashSize::Size_1M,
552 _ => FlashSize::Size_2M,
553 }
554 }
555}
556
557/// Represents different SPI I/O modes used for communication with flash memory.
558///
559/// This enum defines the supported SPI I/O modes for flash memory. These modes
560/// control how data is transferred between the device and the memory. The default
561/// value is `Quad_IO`, which uses four data lines for transfer.
562#[allow(non_camel_case_types)]
563#[derive(Debug, Copy, Clone, Serialize, Deserialize, Default)]
564#[repr(u16)]
565pub enum SpiIOMode {
566 #[default]
567 Quad_IO = 0xFFFF,
568 Quad_Output = 0x7FFF,
569 Dual_IO = 0x3FFF,
570 Dual_Output = 0x1FFF,
571 One_IO = 0x0FFF,
572}
573
574impl From<u16> for SpiIOMode {
575 /// Converts a 16-bit value into a `SpiIOMode` enum.
576 ///
577 /// # Arguments:
578 /// - `value`: A 16-bit unsigned integer representing an SPI I/O mode.
579 ///
580 /// # Returns:
581 /// - The corresponding `SpiIOMode` enum variant.
582 fn from(value: u16) -> Self {
583 match value {
584 0xFFFF => SpiIOMode::Quad_IO,
585 0x7FFF => SpiIOMode::Quad_Output,
586 0x3FFF => SpiIOMode::Dual_IO,
587 0x1FFF => SpiIOMode::Dual_Output,
588 0x0FFF => SpiIOMode::One_IO,
589 _ => SpiIOMode::Quad_IO,
590 }
591 }
592}
593
594/// Represents different SPI clock speeds for communication with flash memory.
595///
596/// This enum defines the supported SPI speeds for flash memory communication.
597/// The speeds range from 100MHz down to 25MHz, with 100MHz being the default.
598///
599/// C Structure:
600/// - [hal_sys_ctrl.h#L94](https://github.com/Ameba-AIoT/ameba-rtos-z2/blob/302d27d3a393e7ef3739d94d0bb0cf2a4c9bc40d/component/soc/realtek/8710c/fwlib/include/hal_sys_ctrl.h#L94)
601#[derive(Debug, Copy, Clone, Serialize, Deserialize, Default)]
602#[repr(u16)]
603pub enum SpiSpeed {
604 #[default]
605 _100MHz = 0xFFFF,
606 _50MHz = 0x7FFF,
607 _25MHz = 0x3FFF,
608}
609
610impl From<u16> for SpiSpeed {
611 /// Converts a 16-bit value into a `SpiSpeed` enum.
612 ///
613 /// # Arguments:
614 /// - `value`: A 16-bit unsigned integer representing an SPI clock speed.
615 ///
616 /// # Returns:
617 /// - The corresponding `SpiSpeed` enum variant.
618 fn from(value: u16) -> Self {
619 match value {
620 0xFFFF => SpiSpeed::_100MHz,
621 0x7FFF => SpiSpeed::_50MHz,
622 0x3FFF => SpiSpeed::_25MHz,
623 _ => SpiSpeed::_100MHz,
624 }
625 }
626}