1use super::super::boot::{BaseBootCatalog, BootSectionHeaderEntry};
2use super::super::io::LogicalSector;
3use hadris_common::types::endian::Endian;
4
5use super::super::io::{self, IsoCursor, Read, Seek, SeekFrom};
6use super::IsoImage;
7use bytemuck::Zeroable;
8use spin::Mutex;
9
10#[derive(Debug, Clone)]
11pub struct BootInfo {
13 pub(crate) catalog: BaseBootCatalog,
16 pub(crate) catalog_ptr: LogicalSector,
19}
20
21impl BootInfo {
22 pub fn sections<'a, R: Read + Seek>(
24 &'a self,
25 image: &'a IsoImage<R>,
26 ) -> BootSectionIter<'a, R> {
27 let catalog_byte_offset = (self.catalog_ptr.0 as u64) * 2048 + 64;
33 BootSectionIter {
34 data: &image.data,
35 current_seek: catalog_byte_offset,
36 has_more: true,
37 }
38 }
39
40 pub fn default_entry(&self) -> Option<BootEntryInfo> {
44 let entry = &self.catalog.default_entry;
45 if !entry.is_valid() {
46 return None;
47 }
48 Some(BootEntryInfo {
49 bootable: entry.boot_indicator == 0x88,
50 media_type: entry.boot_media_type,
51 load_segment: entry.load_segment.get(),
52 sector_count: entry.sector_count.get(),
53 load_rba: entry.load_rba.get(),
54 })
55 }
56}
57
58#[derive(Debug, Clone)]
59pub struct BootEntryInfo {
61 pub bootable: bool,
63 pub media_type: u8,
65 pub load_segment: u16,
67 pub sector_count: u16,
69 pub load_rba: u32,
71}
72
73io_transform! {
74
75pub struct BootSectionIter<'data, DATA: Read + Seek> {
77 data: &'data Mutex<IsoCursor<DATA>>,
78 current_seek: u64,
79 has_more: bool,
80}
81
82impl<DATA: Read + Seek> BootSectionIter<'_, DATA> {
83 pub async fn next_section(&mut self) -> io::Result<Option<BootSectionHeaderEntry>> {
85 let mut data = self.data.lock();
86 if !self.has_more {
87 return Ok(None);
88 }
89 data
90 .seek(SeekFrom::Start(self.current_seek))
91 .await
92 .map_err(io::Error::erase)?;
93 let mut header = BootSectionHeaderEntry::zeroed();
94
95 const MAX_ENTRIES_PER_SECTOR: usize = 64; for _ in 0..MAX_ENTRIES_PER_SECTOR {
98 data.read_exact(bytemuck::bytes_of_mut(&mut header)).await?;
99 self.current_seek += 32; match header.header_type {
102 0x00 => {
103 self.has_more = false;
105 return Ok(None);
106 }
107 0x90 => {
108 self.has_more = true;
110 return Ok(Some(header));
111 }
112 0x91 => {
113 self.has_more = false;
115 return Ok(Some(header));
116 }
117 _ => continue,
119 }
120 }
121
122 self.has_more = false;
124 Ok(None)
125 }
126}
127
128} sync_only! {
131impl<DATA: Read + Seek> Iterator for BootSectionIter<'_, DATA> {
132 type Item = io::Result<BootSectionHeaderEntry>;
133
134 fn next(&mut self) -> Option<Self::Item> {
135 self.next_section().transpose()
136 }
137}
138}