diff --git a/bios/stage-2/src/disk.rs b/bios/stage-2/src/disk.rs index 06a2e8fa..83ee614d 100644 --- a/bios/stage-2/src/disk.rs +++ b/bios/stage-2/src/disk.rs @@ -5,6 +5,9 @@ pub struct DiskAccess { pub disk_number: u16, pub base_offset: u64, pub current_offset: u64, + + /// The offset of the sector read in the last call to read_exact_at. + pub last_read_exact_at_offset: Option, } impl Read for DiskAccess { @@ -19,7 +22,15 @@ impl Read for DiskAccess { let buf = unsafe { &mut TMP_BUF }; assert!(current_sector_offset + len <= buf.buffer.len()); - self.read_exact_into(buf.buffer.len(), buf); + // Don't read the sector if we already read the same sector in the last + // call. + if self + .last_read_exact_at_offset + .is_none_or(|offset| offset != self.current_offset) + { + self.last_read_exact_at_offset = Some(self.current_offset); + self.read_exact_into(buf.buffer.len(), buf); + } &buf.buffer[current_sector_offset..][..len] } diff --git a/bios/stage-2/src/main.rs b/bios/stage-2/src/main.rs index 555b4d55..41520513 100644 --- a/bios/stage-2/src/main.rs +++ b/bios/stage-2/src/main.rs @@ -83,6 +83,7 @@ fn start(disk_number: u16, partition_table_start: *const u8) -> ! { disk_number, base_offset: u64::from(fat_partition.logical_block_address) * 512, current_offset: 0, + last_read_exact_at_offset: None, }; let mut fs = fat::FileSystem::parse(disk.clone()); @@ -198,10 +199,17 @@ fn try_load_file( let file_size = file.file_size().into(); let mut total_offset = 0; - for cluster in fs.file_clusters(&file) { - let cluster = cluster.unwrap(); + let mut file_clusters = fs.file_clusters(&file).map(Result::unwrap).peekable(); + while let Some(cluster) = file_clusters.next() { let cluster_start = cluster.start_offset; - let cluster_end = cluster_start + u64::from(cluster.len_bytes); + let mut cluster_end = cluster_start + u64::from(cluster.len_bytes); + + // Merge with the following clusters if they're contiguous. + while let Some(next_cluster) = + file_clusters.next_if(|next_cluster| next_cluster.start_offset == cluster_end) + { + cluster_end += u64::from(next_cluster.len_bytes); + } let mut offset = 0; loop {