apple_nvram/
lib.rs

1// SPDX-License-Identifier: MIT
2use std::{
3    borrow::Cow,
4    fmt::{Debug, Display, Formatter},
5};
6
7pub mod mtd;
8
9pub mod v1v2;
10pub mod v3;
11
12fn chrp_checksum_add(lhs: u8, rhs: u8) -> u8 {
13    let (out, carry) = lhs.overflowing_add(rhs);
14    if carry {
15        out + 1
16    } else {
17        out
18    }
19}
20
21fn slice_rstrip<'a, T: PartialEq<T>>(mut ts: &'a [T], t: &T) -> &'a [T] {
22    while let Some(last) = ts.last() {
23        if last == t {
24            ts = ts.split_last().unwrap().1;
25        } else {
26            break;
27        }
28    }
29    ts
30}
31
32fn slice_find<T: PartialEq<T>>(ts: &[T], t: &T) -> Option<usize> {
33    let mut ret = None;
34    for (i, v) in ts.iter().enumerate() {
35        if v == t {
36            ret = Some(i);
37            break;
38        }
39    }
40    ret
41}
42
43#[derive(Debug)]
44pub enum Error {
45    ParseError,
46    SectionTooBig,
47    ApplyError(std::io::Error),
48}
49
50type Result<T> = std::result::Result<T, Error>;
51
52#[derive(Clone, Copy, PartialEq)]
53pub enum VarType {
54    Common,
55    System,
56}
57
58impl Display for VarType {
59    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
60        match self {
61            &VarType::Common => write!(f, "common"),
62            &VarType::System => write!(f, "system"),
63        }
64    }
65}
66
67pub fn nvram_parse<'a>(nvr: &'a [u8]) -> Result<Box<dyn Nvram<'a> + 'a>> {
68    match (v3::Nvram::parse(nvr), v1v2::Nvram::parse(nvr)) {
69        (Ok(nvram_v3), Err(_)) => Ok(Box::new(nvram_v3)),
70        (Err(_), Ok(nvram_v1v2)) => Ok(Box::new(nvram_v1v2)),
71        _ => Err(Error::ParseError),
72    }
73}
74
75pub trait NvramWriter {
76    fn erase_if_needed(&mut self, offset: u32, size: usize);
77    fn write_all(&mut self, offset: u32, buf: &[u8]) -> std::io::Result<()>;
78}
79
80pub trait Nvram<'a> {
81    fn prepare_for_write(&mut self);
82    fn active_part_mut(&mut self) -> &mut dyn Partition<'a>;
83    fn partitions(&self) -> Box<dyn Iterator<Item = &dyn Partition<'a>> + '_>;
84    fn serialize(&self) -> Result<Vec<u8>>;
85    fn apply(&mut self, w: &mut dyn NvramWriter) -> Result<()>;
86}
87
88pub trait Partition<'a>: Display {
89    fn variables(&self) -> Box<dyn Iterator<Item = &dyn Variable<'a>> + '_>;
90    fn get_variable(&self, key: &[u8], typ: VarType) -> Option<&dyn Variable<'a>>;
91    fn insert_variable(&mut self, key: &[u8], value: Cow<'a, [u8]>, typ: VarType);
92    fn remove_variable(&mut self, key: &[u8], typ: VarType);
93}
94
95pub trait Variable<'a>: Display {
96    fn value(&self) -> Cow<'a, [u8]>;
97}