coreboot_fs/
lib.rs

1#![no_std]
2
3use core::mem;
4use plain;
5
6pub use self::big_endian::Be32;
7mod big_endian;
8
9pub use self::file::File;
10mod file;
11
12pub use self::fmap::Fmap;
13mod fmap;
14
15pub use self::header::Header;
16mod header;
17
18pub struct Rom<'a>(pub &'a [u8]);
19
20impl<'a> Rom<'a> {
21    pub fn new(data: &'a [u8]) -> Self {
22        Self(data)
23    }
24
25    pub fn fmap(&self) -> Option<&Fmap> {
26        let mut offset = 0;
27        while offset + mem::size_of::<Fmap>() < self.0.len() {
28            let fmap: &Fmap = plain::from_bytes(&self.0[offset..]).ok()?;
29
30            if &fmap.signature == b"__FMAP__" {
31                return Some(fmap);
32            }
33
34            offset += 8;
35        }
36        None
37    }
38
39    pub fn header_offset(&self) -> Option<usize> {
40        if self.0.len() < 4 {
41            return None;
42        }
43
44        // The location is stored as a negative offset from the end of flash.
45        let i = self.0.len() - 4;
46        let offset = i32::from_le_bytes([self.0[i], self.0[i + 1], self.0[i + 2], self.0[i + 3]]) as isize;
47        let header_pos = (self.0.len() as isize + offset) as usize;
48
49        Some(header_pos)
50    }
51
52    pub fn header(&self) -> Option<&Header> {
53        let offset = self.header_offset()?;
54
55        if offset >= self.0.len() {
56            return None;
57        }
58
59        let header: &Header = plain::from_bytes(&self.0[offset..]).ok()?;
60        if &header.magic == b"ORBC" {
61            Some(header)
62        } else {
63            None
64        }
65    }
66
67    pub fn file(&self, offset: usize) -> Option<&File> {
68        if offset >= self.0.len() {
69            return None;
70        }
71
72        let file: &File = plain::from_bytes(&self.0[offset..]).ok()?;
73        if &file.magic == b"LARCHIVE" {
74            Some(file)
75        } else {
76            None
77        }
78    }
79}