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}