1 use core::{default::Default, mem::size_of}; 2 3 use alloc::{ 4 sync::{Arc, Weak}, 5 vec::Vec, 6 }; 7 use log::debug; 8 use system_error::SystemError; 9 10 use crate::{ 11 driver::base::block::{block_device::BlockDevice, disk_info::Partition, SeekFrom}, 12 libs::vec_cursor::VecCursor, 13 }; 14 15 /// @brief MBR硬盘分区表项的结构 16 #[repr(packed)] 17 #[derive(Debug, Clone, Copy, Default)] 18 pub struct MbrDiskPartitionTableEntry { 19 pub flags: u8, // 引导标志符,标记此分区为活动分区 20 pub starting_head: u8, // 起始磁头号 21 pub starting_sector_cylinder: u16, // sector : 低6, cylinder : 高10; 起始扇区号 + 起始柱面号 22 pub part_type: u8, // 分区类型ID 23 pub ending_head: u8, // 结束磁头号 24 pub ending_sector_cylinder: u16, // ending_sector : 低6, ending_cylinder : 高10; 结束扇区号 + 结束柱面号 25 pub starting_lba: u32, // 起始逻辑扇区 26 pub total_sectors: u32, // 分区占用的磁盘扇区数 27 } 28 29 impl MbrDiskPartitionTableEntry { 30 pub fn starting_sector(&self) -> u32 { 31 return (self.starting_sector_cylinder & ((1 << 6) - 1)).into(); 32 } 33 pub fn starting_cylinder(&self) -> u16 { 34 return (self.starting_sector_cylinder >> 6) & ((1 << 10) - 1) as u16; 35 } 36 pub fn ending_sector(&self) -> u32 { 37 self.starting_sector() + self.total_sectors - 1 38 } 39 40 pub fn ending_cylinder(&self) -> u16 { 41 return (self.ending_sector_cylinder >> 6) & ((1 << 10) - 1) as u16; 42 } 43 44 pub fn is_valid(&self) -> bool { 45 // 其他更多的可能判断条件 46 self.starting_sector() <= self.ending_sector() 47 && self.starting_cylinder() <= self.ending_cylinder() 48 && self.starting_lba != 0 49 && self.total_sectors != 0 50 && self.part_type != 0 51 } 52 } 53 54 /// @brief MBR磁盘分区表结构体 55 #[repr(packed)] 56 #[derive(Debug, Clone, Copy)] 57 pub struct MbrDiskPartionTable { 58 pub reserved: [u8; 446], 59 pub dpte: [MbrDiskPartitionTableEntry; 4], // 磁盘分区表项 60 pub bs_trailsig: u16, 61 } 62 63 impl Default for MbrDiskPartionTable { 64 fn default() -> Self { 65 MbrDiskPartionTable { 66 reserved: [0; 446], 67 dpte: [Default::default(); 4], 68 bs_trailsig: Default::default(), 69 } 70 } 71 } 72 73 impl MbrDiskPartionTable { 74 /// # 从磁盘读取MBR分区表 - 从磁盘设备中读取并解析MBR分区表 75 /// 76 /// 这个函数从提供的磁盘设备中读取MBR分区表,并将其解析为一个`MbrDiskPartionTable`实例。 77 /// 78 /// ## 参数 79 /// 80 /// - `disk`: Arc<dyn BlockDevice> - 一个磁盘设备的共享引用,用于从磁盘读取数据。 81 /// 82 /// ## 返回值 83 /// 84 /// - `Ok(MbrDiskPartionTable)`: 成功解析的分区表实例。 85 /// - `Err(SystemError)`: 读取磁盘失败或其他系统错误。 86 pub fn from_disk(disk: Arc<dyn BlockDevice>) -> Result<MbrDiskPartionTable, SystemError> { 87 let mut table: MbrDiskPartionTable = Default::default(); 88 89 // 数据缓冲区 90 let mut buf: Vec<u8> = vec![0; size_of::<MbrDiskPartionTable>()]; 91 buf.resize(size_of::<MbrDiskPartionTable>(), 0); 92 93 disk.read_at_sync(0, 1, &mut buf)?; 94 95 // 创建 Cursor 用于按字节读取 96 let mut cursor = VecCursor::new(buf); 97 cursor.seek(SeekFrom::SeekCurrent(446))?; 98 99 for i in 0..4 { 100 table.dpte[i].flags = cursor.read_u8()?; 101 table.dpte[i].starting_head = cursor.read_u8()?; 102 table.dpte[i].starting_sector_cylinder = cursor.read_u16()?; 103 table.dpte[i].part_type = cursor.read_u8()?; 104 table.dpte[i].ending_head = cursor.read_u8()?; 105 table.dpte[i].ending_sector_cylinder = cursor.read_u16()?; 106 table.dpte[i].starting_lba = cursor.read_u32()?; 107 table.dpte[i].total_sectors = cursor.read_u32()?; 108 109 debug!("dpte[{i}] = {:?}", table.dpte[i]); 110 } 111 table.bs_trailsig = cursor.read_u16()?; 112 // debug!("bs_trailsig = {}", unsafe { 113 // read_unaligned(addr_of!(table.bs_trailsig)) 114 // }); 115 116 if !table.is_valid() { 117 return Err(SystemError::EINVAL); 118 } 119 120 return Ok(table); 121 } 122 123 /// # partitions - 获取磁盘的分区信息 124 /// 125 /// 该函数用于获取指定磁盘的分区信息,并将这些分区信息以分区对象的向量形式返回。分区对象包含了分区的类型、起始扇区和总扇区数等信息。 126 /// 127 /// ## 参数 128 /// 129 /// - `disk`: Weak<dyn BlockDevice>: 一个对磁盘设备的弱引用。这个磁盘设备必须实现`BlockDevice` trait。 130 /// 131 /// ## 返回值 132 /// 133 /// 返回一个包含分区信息的`Vec`。每个分区都是一个`Arc<Partition>`,它表示分区的一个强引用。 134 /// 135 pub fn partitions(&self, disk: Weak<dyn BlockDevice>) -> Vec<Arc<Partition>> { 136 let mut partitions: Vec<Arc<Partition>> = Vec::new(); 137 for i in 0..4 { 138 if self.dpte[i].is_valid() { 139 partitions.push(Partition::new( 140 self.dpte[i].starting_sector() as u64, 141 self.dpte[i].starting_lba as u64, 142 self.dpte[i].total_sectors as u64, 143 disk.clone(), 144 i as u16, 145 )); 146 } 147 } 148 return partitions; 149 } 150 151 pub fn is_valid(&self) -> bool { 152 self.bs_trailsig == 0xAA55 153 } 154 } 155