xref: /DragonOS/kernel/src/filesystem/mbr.rs (revision 9fa0e95eeed8630a8a69c874090af2f10e8eee02)
1731bc2b3SLoGin use core::{default::Default, mem::size_of};
2731bc2b3SLoGin 
3731bc2b3SLoGin use alloc::{
4731bc2b3SLoGin     sync::{Arc, Weak},
5731bc2b3SLoGin     vec::Vec,
6731bc2b3SLoGin };
72eab6dd7S曾俊 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 {
starting_sector(&self) -> u3230731bc2b3SLoGin     pub fn starting_sector(&self) -> u32 {
31731bc2b3SLoGin         return (self.starting_sector_cylinder & ((1 << 6) - 1)).into();
32004e86ffSlogin     }
starting_cylinder(&self) -> u1633004e86ffSlogin     pub fn starting_cylinder(&self) -> u16 {
34004e86ffSlogin         return (self.starting_sector_cylinder >> 6) & ((1 << 10) - 1) as u16;
35004e86ffSlogin     }
ending_sector(&self) -> u3236731bc2b3SLoGin     pub fn ending_sector(&self) -> u32 {
37731bc2b3SLoGin         self.starting_sector() + self.total_sectors - 1
38004e86ffSlogin     }
39731bc2b3SLoGin 
ending_cylinder(&self) -> u1640004e86ffSlogin     pub fn ending_cylinder(&self) -> u16 {
41731bc2b3SLoGin         return (self.ending_sector_cylinder >> 6) & ((1 << 10) - 1) as u16;
42731bc2b3SLoGin     }
43731bc2b3SLoGin 
is_valid(&self) -> bool44731bc2b3SLoGin     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 {
58bd70d2d1SLoGin     pub _reserved: [u8; 446],
59004e86ffSlogin     pub dpte: [MbrDiskPartitionTableEntry; 4], // 磁盘分区表项
60004e86ffSlogin     pub bs_trailsig: u16,
61004e86ffSlogin }
62004e86ffSlogin 
63004e86ffSlogin impl Default for MbrDiskPartionTable {
default() -> Self64004e86ffSlogin     fn default() -> Self {
65004e86ffSlogin         MbrDiskPartionTable {
66bd70d2d1SLoGin             _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)`: 读取磁盘失败或其他系统错误。
from_disk(disk: Arc<dyn BlockDevice>) -> Result<MbrDiskPartionTable, 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 
1092eab6dd7S曾俊             debug!("dpte[{i}] = {:?}", table.dpte[i]);
110731bc2b3SLoGin         }
111731bc2b3SLoGin         table.bs_trailsig = cursor.read_u16()?;
1122eab6dd7S曾俊         // 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     ///
partitions(&self, disk: Weak<dyn BlockDevice>) -> Vec<Arc<Partition>>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 
151*9fa0e95eSLoGin     /// # partitions_raw - 获取磁盘的分区信息,不包含磁盘设备信息
partitions_raw(&self) -> MbrPartitionIter152*9fa0e95eSLoGin     pub fn partitions_raw(&self) -> MbrPartitionIter {
153*9fa0e95eSLoGin         MbrPartitionIter::new(self)
154*9fa0e95eSLoGin     }
155*9fa0e95eSLoGin 
is_valid(&self) -> bool156731bc2b3SLoGin     pub fn is_valid(&self) -> bool {
157731bc2b3SLoGin         self.bs_trailsig == 0xAA55
158731bc2b3SLoGin     }
159731bc2b3SLoGin }
160*9fa0e95eSLoGin 
161*9fa0e95eSLoGin pub struct MbrPartitionIter<'a> {
162*9fa0e95eSLoGin     table: &'a MbrDiskPartionTable,
163*9fa0e95eSLoGin     index: usize,
164*9fa0e95eSLoGin }
165*9fa0e95eSLoGin 
166*9fa0e95eSLoGin impl<'a> MbrPartitionIter<'a> {
new(table: &'a MbrDiskPartionTable) -> Self167*9fa0e95eSLoGin     fn new(table: &'a MbrDiskPartionTable) -> Self {
168*9fa0e95eSLoGin         MbrPartitionIter { table, index: 0 }
169*9fa0e95eSLoGin     }
170*9fa0e95eSLoGin }
171*9fa0e95eSLoGin 
172*9fa0e95eSLoGin impl<'a> Iterator for MbrPartitionIter<'a> {
173*9fa0e95eSLoGin     type Item = Partition;
174*9fa0e95eSLoGin 
next(&mut self) -> Option<Self::Item>175*9fa0e95eSLoGin     fn next(&mut self) -> Option<Self::Item> {
176*9fa0e95eSLoGin         while self.index < 4 {
177*9fa0e95eSLoGin             let entry = &self.table.dpte[self.index];
178*9fa0e95eSLoGin             let index = self.index;
179*9fa0e95eSLoGin             self.index += 1;
180*9fa0e95eSLoGin             if entry.is_valid() {
181*9fa0e95eSLoGin                 let p = Partition::new_raw(
182*9fa0e95eSLoGin                     self.table.dpte[index].starting_sector() as u64,
183*9fa0e95eSLoGin                     self.table.dpte[index].starting_lba as u64,
184*9fa0e95eSLoGin                     self.table.dpte[index].total_sectors as u64,
185*9fa0e95eSLoGin                     index as u16,
186*9fa0e95eSLoGin                 );
187*9fa0e95eSLoGin                 return Some(p);
188*9fa0e95eSLoGin             }
189*9fa0e95eSLoGin         }
190*9fa0e95eSLoGin         return None;
191*9fa0e95eSLoGin     }
192*9fa0e95eSLoGin }
193