1731bc2b3SLoGin use core::{default::Default, mem::size_of}; 2731bc2b3SLoGin 3731bc2b3SLoGin use alloc::{ 4731bc2b3SLoGin sync::{Arc, Weak}, 5731bc2b3SLoGin vec::Vec, 6731bc2b3SLoGin }; 7*2eab6dd7S曾俊 use log::debug; 8731bc2b3SLoGin use system_error::SystemError; 9731bc2b3SLoGin 10731bc2b3SLoGin use crate::{ 11731bc2b3SLoGin driver::base::block::{block_device::BlockDevice, disk_info::Partition, SeekFrom}, 12731bc2b3SLoGin libs::vec_cursor::VecCursor, 13731bc2b3SLoGin }; 14004e86ffSlogin 15004e86ffSlogin /// @brief MBR硬盘分区表项的结构 16004e86ffSlogin #[repr(packed)] 17b5b571e0SLoGin #[derive(Debug, Clone, Copy, Default)] 18004e86ffSlogin pub struct MbrDiskPartitionTableEntry { 19004e86ffSlogin pub flags: u8, // 引导标志符,标记此分区为活动分区 20004e86ffSlogin pub starting_head: u8, // 起始磁头号 21004e86ffSlogin pub starting_sector_cylinder: u16, // sector : 低6, cylinder : 高10; 起始扇区号 + 起始柱面号 22004e86ffSlogin pub part_type: u8, // 分区类型ID 23004e86ffSlogin pub ending_head: u8, // 结束磁头号 24731bc2b3SLoGin pub ending_sector_cylinder: u16, // ending_sector : 低6, ending_cylinder : 高10; 结束扇区号 + 结束柱面号 25004e86ffSlogin pub starting_lba: u32, // 起始逻辑扇区 26004e86ffSlogin pub total_sectors: u32, // 分区占用的磁盘扇区数 27004e86ffSlogin } 28004e86ffSlogin 29004e86ffSlogin impl MbrDiskPartitionTableEntry { 30731bc2b3SLoGin pub fn starting_sector(&self) -> u32 { 31731bc2b3SLoGin return (self.starting_sector_cylinder & ((1 << 6) - 1)).into(); 32004e86ffSlogin } 33004e86ffSlogin pub fn starting_cylinder(&self) -> u16 { 34004e86ffSlogin return (self.starting_sector_cylinder >> 6) & ((1 << 10) - 1) as u16; 35004e86ffSlogin } 36731bc2b3SLoGin pub fn ending_sector(&self) -> u32 { 37731bc2b3SLoGin self.starting_sector() + self.total_sectors - 1 38004e86ffSlogin } 39731bc2b3SLoGin 40004e86ffSlogin pub fn ending_cylinder(&self) -> u16 { 41731bc2b3SLoGin return (self.ending_sector_cylinder >> 6) & ((1 << 10) - 1) as u16; 42731bc2b3SLoGin } 43731bc2b3SLoGin 44731bc2b3SLoGin pub fn is_valid(&self) -> bool { 45731bc2b3SLoGin // 其他更多的可能判断条件 46731bc2b3SLoGin self.starting_sector() <= self.ending_sector() 47731bc2b3SLoGin && self.starting_cylinder() <= self.ending_cylinder() 48731bc2b3SLoGin && self.starting_lba != 0 49731bc2b3SLoGin && self.total_sectors != 0 50731bc2b3SLoGin && self.part_type != 0 51004e86ffSlogin } 52004e86ffSlogin } 53004e86ffSlogin 54004e86ffSlogin /// @brief MBR磁盘分区表结构体 55004e86ffSlogin #[repr(packed)] 56004e86ffSlogin #[derive(Debug, Clone, Copy)] 57004e86ffSlogin pub struct MbrDiskPartionTable { 58004e86ffSlogin pub reserved: [u8; 446], 59004e86ffSlogin pub dpte: [MbrDiskPartitionTableEntry; 4], // 磁盘分区表项 60004e86ffSlogin pub bs_trailsig: u16, 61004e86ffSlogin } 62004e86ffSlogin 63004e86ffSlogin impl Default for MbrDiskPartionTable { 64004e86ffSlogin fn default() -> Self { 65004e86ffSlogin MbrDiskPartionTable { 66004e86ffSlogin reserved: [0; 446], 67004e86ffSlogin dpte: [Default::default(); 4], 68004e86ffSlogin bs_trailsig: Default::default(), 69004e86ffSlogin } 70004e86ffSlogin } 71004e86ffSlogin } 72731bc2b3SLoGin 73731bc2b3SLoGin impl MbrDiskPartionTable { 74731bc2b3SLoGin /// # 从磁盘读取MBR分区表 - 从磁盘设备中读取并解析MBR分区表 75731bc2b3SLoGin /// 76731bc2b3SLoGin /// 这个函数从提供的磁盘设备中读取MBR分区表,并将其解析为一个`MbrDiskPartionTable`实例。 77731bc2b3SLoGin /// 78731bc2b3SLoGin /// ## 参数 79731bc2b3SLoGin /// 80731bc2b3SLoGin /// - `disk`: Arc<dyn BlockDevice> - 一个磁盘设备的共享引用,用于从磁盘读取数据。 81731bc2b3SLoGin /// 82731bc2b3SLoGin /// ## 返回值 83731bc2b3SLoGin /// 84731bc2b3SLoGin /// - `Ok(MbrDiskPartionTable)`: 成功解析的分区表实例。 85731bc2b3SLoGin /// - `Err(SystemError)`: 读取磁盘失败或其他系统错误。 86731bc2b3SLoGin pub fn from_disk(disk: Arc<dyn BlockDevice>) -> Result<MbrDiskPartionTable, SystemError> { 87731bc2b3SLoGin let mut table: MbrDiskPartionTable = Default::default(); 88731bc2b3SLoGin 89731bc2b3SLoGin // 数据缓冲区 90731bc2b3SLoGin let mut buf: Vec<u8> = vec![0; size_of::<MbrDiskPartionTable>()]; 91731bc2b3SLoGin buf.resize(size_of::<MbrDiskPartionTable>(), 0); 92731bc2b3SLoGin 93731bc2b3SLoGin disk.read_at_sync(0, 1, &mut buf)?; 94731bc2b3SLoGin 95731bc2b3SLoGin // 创建 Cursor 用于按字节读取 96731bc2b3SLoGin let mut cursor = VecCursor::new(buf); 97731bc2b3SLoGin cursor.seek(SeekFrom::SeekCurrent(446))?; 98731bc2b3SLoGin 99731bc2b3SLoGin for i in 0..4 { 100731bc2b3SLoGin table.dpte[i].flags = cursor.read_u8()?; 101731bc2b3SLoGin table.dpte[i].starting_head = cursor.read_u8()?; 102731bc2b3SLoGin table.dpte[i].starting_sector_cylinder = cursor.read_u16()?; 103731bc2b3SLoGin table.dpte[i].part_type = cursor.read_u8()?; 104731bc2b3SLoGin table.dpte[i].ending_head = cursor.read_u8()?; 105731bc2b3SLoGin table.dpte[i].ending_sector_cylinder = cursor.read_u16()?; 106731bc2b3SLoGin table.dpte[i].starting_lba = cursor.read_u32()?; 107731bc2b3SLoGin table.dpte[i].total_sectors = cursor.read_u32()?; 108731bc2b3SLoGin 109*2eab6dd7S曾俊 debug!("dpte[{i}] = {:?}", table.dpte[i]); 110731bc2b3SLoGin } 111731bc2b3SLoGin table.bs_trailsig = cursor.read_u16()?; 112*2eab6dd7S曾俊 // debug!("bs_trailsig = {}", unsafe { 113731bc2b3SLoGin // read_unaligned(addr_of!(table.bs_trailsig)) 114731bc2b3SLoGin // }); 115731bc2b3SLoGin 116731bc2b3SLoGin if !table.is_valid() { 117731bc2b3SLoGin return Err(SystemError::EINVAL); 118731bc2b3SLoGin } 119731bc2b3SLoGin 120731bc2b3SLoGin return Ok(table); 121731bc2b3SLoGin } 122731bc2b3SLoGin 123731bc2b3SLoGin /// # partitions - 获取磁盘的分区信息 124731bc2b3SLoGin /// 125731bc2b3SLoGin /// 该函数用于获取指定磁盘的分区信息,并将这些分区信息以分区对象的向量形式返回。分区对象包含了分区的类型、起始扇区和总扇区数等信息。 126731bc2b3SLoGin /// 127731bc2b3SLoGin /// ## 参数 128731bc2b3SLoGin /// 129731bc2b3SLoGin /// - `disk`: Weak<dyn BlockDevice>: 一个对磁盘设备的弱引用。这个磁盘设备必须实现`BlockDevice` trait。 130731bc2b3SLoGin /// 131731bc2b3SLoGin /// ## 返回值 132731bc2b3SLoGin /// 133731bc2b3SLoGin /// 返回一个包含分区信息的`Vec`。每个分区都是一个`Arc<Partition>`,它表示分区的一个强引用。 134731bc2b3SLoGin /// 135731bc2b3SLoGin pub fn partitions(&self, disk: Weak<dyn BlockDevice>) -> Vec<Arc<Partition>> { 136731bc2b3SLoGin let mut partitions: Vec<Arc<Partition>> = Vec::new(); 137731bc2b3SLoGin for i in 0..4 { 138731bc2b3SLoGin if self.dpte[i].is_valid() { 139731bc2b3SLoGin partitions.push(Partition::new( 140731bc2b3SLoGin self.dpte[i].starting_sector() as u64, 141731bc2b3SLoGin self.dpte[i].starting_lba as u64, 142731bc2b3SLoGin self.dpte[i].total_sectors as u64, 143731bc2b3SLoGin disk.clone(), 144731bc2b3SLoGin i as u16, 145731bc2b3SLoGin )); 146731bc2b3SLoGin } 147731bc2b3SLoGin } 148731bc2b3SLoGin return partitions; 149731bc2b3SLoGin } 150731bc2b3SLoGin 151731bc2b3SLoGin pub fn is_valid(&self) -> bool { 152731bc2b3SLoGin self.bs_trailsig == 0xAA55 153731bc2b3SLoGin } 154731bc2b3SLoGin } 155