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