xref: /DragonOS/kernel/src/filesystem/mbr.rs (revision dd8e74ef0d7f91a141bd217736bef4fe7dc6df3d)
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