//! Physical paired-GPT reads, bounded streaming validation, and mount refusal. use super::*; use os_partitions_gpt::{Error as PartitionError, MountState, StreamError}; pub fn run(boot: &BootData, allocator: &mut memory::FrameAllocator) -> Result<(), &'static str> { let before = allocator.remaining_pages(); let mut primary = [0u8; 512]; let mut backup = [0u8; 512]; let mut disk = virtio_ro_turkfs::RoDisk::open( boot, allocator, "TURKOS/OS/K1530-GET")?; if disk.capacity() != 2048 { return Err("k1530-disk-capacity"); } disk.read(1, &mut primary)?; disk.read(2047, &mut backup)?; disk.close(allocator)?; if allocator.remaining_pages() != before { return Err("k1530-header-DMA-leak"); } let layout = os_partitions_gpt::inspect_headers(&primary, &backup, 2048) .map_err(|_| "k1530-valid-GPT-headers")?; if layout.primary_array_lba != 2 || layout.backup_array_lba != 2015 || layout.first_usable != 34 || layout.last_usable != 2014 { return Err("k1530-GPT-layout"); } let mut mounts = MountState::new(); let mut active: Option = None; let mut batch = 0usize; let mut reads = 0usize; let result = mounts.mount_stream(&primary, &backup, 2048, |lba, destination| { if batch == 4 { active.take().ok_or("k1530-reader-missing")?.close(allocator)?; batch = 0; } if active.is_none() { active = Some(virtio_ro_turkfs::RoDisk::open( boot, allocator, "TURKOS/OS/K1530-GET")?); } active.as_mut().ok_or("k1530-reader-open")?.read(lba, destination)?; batch += 1; reads += 1; Ok::<(), &'static str>(()) }); if let Some(disk) = active.take() { disk.close(allocator)?; } let table = result.map_err(|_| "k1530-valid-GPT-arrays")?; if reads != 64 || table.count != 2 || table.entries[0].map(|p| (p.first_lba, p.last_lba)) != Some((34, 100)) || table.entries[1].map(|p| (p.first_lba, p.last_lba)) != Some((101, 2014)) { return Err("k1530-GPT-partitions"); } if allocator.remaining_pages() != before { return Err("k1530-array-DMA-leak"); } let healthy = mounts; let mut corrupt_crc = primary; corrupt_crc[56] ^= 1; let mut forbidden_reads = 0usize; let refused = mounts.mount_stream(&corrupt_crc, &backup, 2048, |_lba, _sector| { forbidden_reads += 1; Ok::<(), ()>(()) }); if refused != Err(StreamError::Parse(PartitionError::BadHeaderCrc)) || forbidden_reads != 0 || mounts != healthy { return Err("k1530-bad-CRC-mounted"); } let mut oversized = primary; oversized[80..84].copy_from_slice(&4096u32.to_le_bytes()); oversized[16..20].fill(0); let crc = os_partitions_gpt::crc32(&oversized[..92]); oversized[16..20].copy_from_slice(&crc.to_le_bytes()); let refused = mounts.mount_stream(&oversized, &backup, 2048, |_lba, _sector| { forbidden_reads += 1; Ok::<(), ()>(()) }); if refused != Err(StreamError::Parse(PartitionError::UnsupportedLayout)) || forbidden_reads != 0 || mounts != healthy { return Err("k1530-oversized-mounted"); } let mut empty = MountState::new(); let refused = empty.mount_stream(&corrupt_crc, &backup, 2048, |_lba, _sector| { forbidden_reads += 1; Ok::<(), ()>(()) }); if refused != Err(StreamError::Parse(PartitionError::BadHeaderCrc)) || forbidden_reads != 0 || empty.table.is_some() || empty.generation != 0 { return Err("k1530-corrupt-disk-mounted"); } write_line("TURKOS/OS/K1530-GPT: PHYSICAL=READ HEADERS=2 ARRAYS=64 ENTRIES=2 FIRST=34:100 SECOND=101:2014 CRC=REJECTED OVERSIZED=REJECTED MOUNT=UNCHANGED FRAMES=RETURNED"); Ok(()) }