multiboot2_host/header/
mod.rs1use byteorder::{ReadBytesExt, LE};
2use std::io::{Read, Seek, SeekFrom};
3
4mod tag;
5pub use tag::{Tag, TagType};
6
7pub 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}