use super::super::boot::{BaseBootCatalog, BootSectionHeaderEntry};
use super::super::io::{self, Read, Seek, SeekFrom};
use super::super::io::{IsoCursor, LogicalSector};
use super::IsoImage;
use bytemuck::Zeroable;
use hadris_common::types::endian::Endian;
use spin::Mutex;
#[derive(Debug, Clone)]
pub struct BootInfo {
pub(crate) catalog: BaseBootCatalog,
pub(crate) catalog_ptr: LogicalSector,
}
impl BootInfo {
sync_only! {
pub fn sections<'a, R: Read + Seek>(
&'a self,
image: &'a IsoImage<R>,
) -> BootSectionIter<'a, R> {
let catalog_byte_offset = (self.catalog_ptr.0 as u64) * 2048 + 64;
BootSectionIter {
data: &image.data,
current_seek: catalog_byte_offset,
has_more: true,
}
}
}
pub fn default_entry(&self) -> Option<BootEntryInfo> {
let entry = &self.catalog.default_entry;
if !entry.is_valid() {
return None;
}
Some(BootEntryInfo {
bootable: entry.boot_indicator == 0x88,
meadia_type: entry.boot_media_type,
load_segment: entry.load_segment.get(),
sector_count: entry.sector_count.get(),
load_rba: entry.load_rba.get(),
})
}
}
#[derive(Debug, Clone)]
pub struct BootEntryInfo {
pub bootable: bool,
pub meadia_type: u8,
pub load_segment: u16,
pub sector_count: u16,
pub load_rba: u32,
}
sync_only! {
pub struct BootSectionIter<'data, DATA: Read + Seek> {
data: &'data Mutex<IsoCursor<DATA>>,
current_seek: u64,
has_more: bool,
}
impl<DATA: Read + Seek> Iterator for BootSectionIter<'_, DATA> {
type Item = io::Result<BootSectionHeaderEntry>;
fn next(&mut self) -> Option<Self::Item> {
let mut data = self.data.lock();
if !self.has_more {
return None;
}
use super::super::io::try_io_result_option as try_io;
try_io!(data.seek(SeekFrom::Start(self.current_seek)));
let mut header = BootSectionHeaderEntry::zeroed();
const MAX_ENTRIES_PER_SECTOR: usize = 64; for _ in 0..MAX_ENTRIES_PER_SECTOR {
try_io!(data.read_exact(bytemuck::bytes_of_mut(&mut header)));
self.current_seek += 32;
match header.header_type {
0x00 => {
self.has_more = false;
return None;
}
0x90 => {
self.has_more = true;
return Some(Ok(header));
}
0x91 => {
self.has_more = false;
return Some(Ok(header));
}
_ => continue,
}
}
self.has_more = false;
None
}
}
}