multiboot2_host/header/
mod.rs

1use byteorder::{ReadBytesExt, LE};
2use std::io::{Read, Seek, SeekFrom};
3
4mod tag;
5pub use tag::{Tag, TagType};
6
7// Defined by Multiboot2 spec
8pub const HEADER_MAGIC: u32 = 0xE85250D6;
9pub const SEARCH_END: u64 = 32768;
10pub const ALIGNMENT: usize = 8;
11
12#[derive(Debug, Copy, Clone)]
13pub struct Header {
14    pub magic: u32,
15    pub architecture: u32,
16    pub header_length: u32,
17    pub checksum: u32,
18}
19
20impl Header {
21    pub fn is_valid(&self) -> bool {
22        if self.magic != HEADER_MAGIC {
23            return false;
24        }
25        self.checksum
26            .wrapping_add(self.magic)
27            .wrapping_add(self.architecture)
28            .wrapping_add(self.header_length)
29            == 0
30    }
31}
32
33pub fn find_header<R: Read + Seek>(mut image: R) -> std::io::Result<Option<(u64, Header)>> {
34    for offset in (0..SEARCH_END).step_by(ALIGNMENT) {
35        image.seek(SeekFrom::Start(offset))?;
36
37        let magic = image.read_u32::<LE>()?;
38        if magic == HEADER_MAGIC {
39            let header = Header {
40                magic,
41                architecture: image.read_u32::<LE>()?,
42                header_length: image.read_u32::<LE>()?,
43                checksum: image.read_u32::<LE>()?,
44            };
45            if header.is_valid() {
46                return Ok(Some((offset, header)));
47            }
48        }
49    }
50    Ok(None)
51}
52
53#[derive(Debug, Clone)]
54pub struct TagIter<R> {
55    done: bool,
56    data: R,
57}
58
59impl<R: Read> TagIter<R> {
60    pub fn new(data: R) -> Self {
61        Self { done: false, data }
62    }
63}
64
65impl<R: Read> Iterator for TagIter<R> {
66    type Item = std::io::Result<Tag>;
67    fn next(&mut self) -> Option<Self::Item> {
68        if self.done {
69            return None;
70        }
71
72        let tag = match Tag::from_reader(&mut self.data) {
73            Ok(t) => t,
74            Err(e) => return Some(Err(e)),
75        };
76        if tag == Tag::End {
77            self.done = true;
78        }
79
80        Some(Ok(tag))
81    }
82}