xref: /DragonOS/kernel/src/filesystem/mbr.rs (revision 731bc2b32d7b37298883d7a15b6dca659b436ee4)
1*731bc2b3SLoGin use core::{default::Default, mem::size_of};
2*731bc2b3SLoGin 
3*731bc2b3SLoGin use alloc::{
4*731bc2b3SLoGin     sync::{Arc, Weak},
5*731bc2b3SLoGin     vec::Vec,
6*731bc2b3SLoGin };
7*731bc2b3SLoGin use system_error::SystemError;
8*731bc2b3SLoGin 
9*731bc2b3SLoGin use crate::{
10*731bc2b3SLoGin     driver::base::block::{block_device::BlockDevice, disk_info::Partition, SeekFrom},
11*731bc2b3SLoGin     libs::vec_cursor::VecCursor,
12*731bc2b3SLoGin };
13004e86ffSlogin 
14004e86ffSlogin /// @brief MBR硬盘分区表项的结构
15004e86ffSlogin #[repr(packed)]
16b5b571e0SLoGin #[derive(Debug, Clone, Copy, Default)]
17004e86ffSlogin pub struct MbrDiskPartitionTableEntry {
18004e86ffSlogin     pub flags: u8,                     // 引导标志符,标记此分区为活动分区
19004e86ffSlogin     pub starting_head: u8,             // 起始磁头号
20004e86ffSlogin     pub starting_sector_cylinder: u16, // sector : 低6, cylinder : 高10;   起始扇区号 + 起始柱面号
21004e86ffSlogin     pub part_type: u8,                 // 分区类型ID
22004e86ffSlogin     pub ending_head: u8,               // 结束磁头号
23*731bc2b3SLoGin     pub ending_sector_cylinder: u16, // ending_sector : 低6, ending_cylinder : 高10;  结束扇区号 + 结束柱面号
24004e86ffSlogin     pub starting_lba: u32,           // 起始逻辑扇区
25004e86ffSlogin     pub total_sectors: u32,          // 分区占用的磁盘扇区数
26004e86ffSlogin }
27004e86ffSlogin 
28004e86ffSlogin impl MbrDiskPartitionTableEntry {
29*731bc2b3SLoGin     pub fn starting_sector(&self) -> u32 {
30*731bc2b3SLoGin         return (self.starting_sector_cylinder & ((1 << 6) - 1)).into();
31004e86ffSlogin     }
32004e86ffSlogin     pub fn starting_cylinder(&self) -> u16 {
33004e86ffSlogin         return (self.starting_sector_cylinder >> 6) & ((1 << 10) - 1) as u16;
34004e86ffSlogin     }
35*731bc2b3SLoGin     pub fn ending_sector(&self) -> u32 {
36*731bc2b3SLoGin         self.starting_sector() + self.total_sectors - 1
37004e86ffSlogin     }
38*731bc2b3SLoGin 
39004e86ffSlogin     pub fn ending_cylinder(&self) -> u16 {
40*731bc2b3SLoGin         return (self.ending_sector_cylinder >> 6) & ((1 << 10) - 1) as u16;
41*731bc2b3SLoGin     }
42*731bc2b3SLoGin 
43*731bc2b3SLoGin     pub fn is_valid(&self) -> bool {
44*731bc2b3SLoGin         // 其他更多的可能判断条件
45*731bc2b3SLoGin         self.starting_sector() <= self.ending_sector()
46*731bc2b3SLoGin             && self.starting_cylinder() <= self.ending_cylinder()
47*731bc2b3SLoGin             && self.starting_lba != 0
48*731bc2b3SLoGin             && self.total_sectors != 0
49*731bc2b3SLoGin             && self.part_type != 0
50004e86ffSlogin     }
51004e86ffSlogin }
52004e86ffSlogin 
53004e86ffSlogin /// @brief MBR磁盘分区表结构体
54004e86ffSlogin #[repr(packed)]
55004e86ffSlogin #[derive(Debug, Clone, Copy)]
56004e86ffSlogin pub struct MbrDiskPartionTable {
57004e86ffSlogin     pub reserved: [u8; 446],
58004e86ffSlogin     pub dpte: [MbrDiskPartitionTableEntry; 4], // 磁盘分区表项
59004e86ffSlogin     pub bs_trailsig: u16,
60004e86ffSlogin }
61004e86ffSlogin 
62004e86ffSlogin impl Default for MbrDiskPartionTable {
63004e86ffSlogin     fn default() -> Self {
64004e86ffSlogin         MbrDiskPartionTable {
65004e86ffSlogin             reserved: [0; 446],
66004e86ffSlogin             dpte: [Default::default(); 4],
67004e86ffSlogin             bs_trailsig: Default::default(),
68004e86ffSlogin         }
69004e86ffSlogin     }
70004e86ffSlogin }
71*731bc2b3SLoGin 
72*731bc2b3SLoGin impl MbrDiskPartionTable {
73*731bc2b3SLoGin     /// # 从磁盘读取MBR分区表 - 从磁盘设备中读取并解析MBR分区表
74*731bc2b3SLoGin     ///
75*731bc2b3SLoGin     /// 这个函数从提供的磁盘设备中读取MBR分区表,并将其解析为一个`MbrDiskPartionTable`实例。
76*731bc2b3SLoGin     ///
77*731bc2b3SLoGin     /// ## 参数
78*731bc2b3SLoGin     ///
79*731bc2b3SLoGin     /// - `disk`: Arc<dyn BlockDevice> - 一个磁盘设备的共享引用,用于从磁盘读取数据。
80*731bc2b3SLoGin     ///
81*731bc2b3SLoGin     /// ## 返回值
82*731bc2b3SLoGin     ///
83*731bc2b3SLoGin     /// - `Ok(MbrDiskPartionTable)`: 成功解析的分区表实例。
84*731bc2b3SLoGin     /// - `Err(SystemError)`: 读取磁盘失败或其他系统错误。
85*731bc2b3SLoGin     pub fn from_disk(disk: Arc<dyn BlockDevice>) -> Result<MbrDiskPartionTable, SystemError> {
86*731bc2b3SLoGin         let mut table: MbrDiskPartionTable = Default::default();
87*731bc2b3SLoGin 
88*731bc2b3SLoGin         // 数据缓冲区
89*731bc2b3SLoGin         let mut buf: Vec<u8> = vec![0; size_of::<MbrDiskPartionTable>()];
90*731bc2b3SLoGin         buf.resize(size_of::<MbrDiskPartionTable>(), 0);
91*731bc2b3SLoGin 
92*731bc2b3SLoGin         disk.read_at_sync(0, 1, &mut buf)?;
93*731bc2b3SLoGin 
94*731bc2b3SLoGin         // 创建 Cursor 用于按字节读取
95*731bc2b3SLoGin         let mut cursor = VecCursor::new(buf);
96*731bc2b3SLoGin         cursor.seek(SeekFrom::SeekCurrent(446))?;
97*731bc2b3SLoGin 
98*731bc2b3SLoGin         for i in 0..4 {
99*731bc2b3SLoGin             table.dpte[i].flags = cursor.read_u8()?;
100*731bc2b3SLoGin             table.dpte[i].starting_head = cursor.read_u8()?;
101*731bc2b3SLoGin             table.dpte[i].starting_sector_cylinder = cursor.read_u16()?;
102*731bc2b3SLoGin             table.dpte[i].part_type = cursor.read_u8()?;
103*731bc2b3SLoGin             table.dpte[i].ending_head = cursor.read_u8()?;
104*731bc2b3SLoGin             table.dpte[i].ending_sector_cylinder = cursor.read_u16()?;
105*731bc2b3SLoGin             table.dpte[i].starting_lba = cursor.read_u32()?;
106*731bc2b3SLoGin             table.dpte[i].total_sectors = cursor.read_u32()?;
107*731bc2b3SLoGin 
108*731bc2b3SLoGin             kdebug!("dpte[{i}] = {:?}", table.dpte[i]);
109*731bc2b3SLoGin         }
110*731bc2b3SLoGin         table.bs_trailsig = cursor.read_u16()?;
111*731bc2b3SLoGin         // kdebug!("bs_trailsig = {}", unsafe {
112*731bc2b3SLoGin         //     read_unaligned(addr_of!(table.bs_trailsig))
113*731bc2b3SLoGin         // });
114*731bc2b3SLoGin 
115*731bc2b3SLoGin         if !table.is_valid() {
116*731bc2b3SLoGin             return Err(SystemError::EINVAL);
117*731bc2b3SLoGin         }
118*731bc2b3SLoGin 
119*731bc2b3SLoGin         return Ok(table);
120*731bc2b3SLoGin     }
121*731bc2b3SLoGin 
122*731bc2b3SLoGin     /// # partitions - 获取磁盘的分区信息
123*731bc2b3SLoGin     ///
124*731bc2b3SLoGin     /// 该函数用于获取指定磁盘的分区信息,并将这些分区信息以分区对象的向量形式返回。分区对象包含了分区的类型、起始扇区和总扇区数等信息。
125*731bc2b3SLoGin     ///
126*731bc2b3SLoGin     /// ## 参数
127*731bc2b3SLoGin     ///
128*731bc2b3SLoGin     /// - `disk`: Weak<dyn BlockDevice>: 一个对磁盘设备的弱引用。这个磁盘设备必须实现`BlockDevice` trait。
129*731bc2b3SLoGin     ///
130*731bc2b3SLoGin     /// ## 返回值
131*731bc2b3SLoGin     ///
132*731bc2b3SLoGin     /// 返回一个包含分区信息的`Vec`。每个分区都是一个`Arc<Partition>`,它表示分区的一个强引用。
133*731bc2b3SLoGin     ///
134*731bc2b3SLoGin     pub fn partitions(&self, disk: Weak<dyn BlockDevice>) -> Vec<Arc<Partition>> {
135*731bc2b3SLoGin         let mut partitions: Vec<Arc<Partition>> = Vec::new();
136*731bc2b3SLoGin         for i in 0..4 {
137*731bc2b3SLoGin             if self.dpte[i].is_valid() {
138*731bc2b3SLoGin                 partitions.push(Partition::new(
139*731bc2b3SLoGin                     self.dpte[i].starting_sector() as u64,
140*731bc2b3SLoGin                     self.dpte[i].starting_lba as u64,
141*731bc2b3SLoGin                     self.dpte[i].total_sectors as u64,
142*731bc2b3SLoGin                     disk.clone(),
143*731bc2b3SLoGin                     i as u16,
144*731bc2b3SLoGin                 ));
145*731bc2b3SLoGin             }
146*731bc2b3SLoGin         }
147*731bc2b3SLoGin         return partitions;
148*731bc2b3SLoGin     }
149*731bc2b3SLoGin 
150*731bc2b3SLoGin     pub fn is_valid(&self) -> bool {
151*731bc2b3SLoGin         self.bs_trailsig == 0xAA55
152*731bc2b3SLoGin     }
153*731bc2b3SLoGin }
154