xref: /DragonOS/kernel/src/filesystem/fat/bpb.rs (revision bacd691c9ef0502b5cc618aad50517f9e59df5e0)
1 #![allow(dead_code)]
2 use alloc::{sync::Arc, vec::Vec};
3 
4 use crate::{
5     io::{device::LBA_SIZE, disk_info::Partition, SeekFrom},
6     kerror,
7     libs::vec_cursor::VecCursor, syscall::SystemError,
8 };
9 
10 use super::fs::{Cluster, FATFileSystem};
11 
12 /// 对于所有的FAT文件系统都适用的Bios Parameter Block结构体
13 #[derive(Debug, Clone, Copy, Default)]
14 pub struct BiosParameterBlock {
15     /// 跳转指令
16     pub jmp_boot: [u8; 3],
17 
18     /// 生产厂商名(表明是哪个操作系统格式化了这个卷)
19     pub oem_name: [u8; 8],
20 
21     /// 每扇区字节数
22     pub bytes_per_sector: u16,
23 
24     /// 每簇扇区数
25     pub sector_per_cluster: u8,
26 
27     /// 保留扇区数
28     pub rsvd_sec_cnt: u16,
29 
30     /// FAT表数量
31     pub num_fats: u8,
32 
33     /// 根目录下的32字节目录项数量最大值(只对FAT12、FAT16生效)
34     pub root_entries_cnt: u16,
35 
36     /// 当前分区的总扇区数(只对FAT12、FAT16生效)
37     pub total_sectors_16: u16,
38 
39     /// 介质描述符
40     pub media: u8,
41 
42     /// FAT12/16每FAT扇区数
43     pub fat_size_16: u16,
44 
45     /// 每磁道扇区数
46     pub sector_per_track: u16,
47 
48     /// 磁头数
49     pub num_heads: u16,
50 
51     /// 隐藏扇区数
52     pub hidden_sectors: u32,
53 
54     /// FAT32的总扇区数
55     pub total_sectors_32: u32,
56 
57     /// FAT文件系统类型(以及他们的一些私有信息字段)
58     pub fat_type: FATType,
59 
60     /// 引导扇区结束标志0xAA55
61     pub trail_sig: u16,
62 }
63 
64 #[derive(Debug, Clone, Copy)]
65 pub enum FATType {
66     FAT12(BiosParameterBlockLegacy),
67     FAT16(BiosParameterBlockLegacy),
68     FAT32(BiosParameterBlockFAT32),
69 }
70 
71 /// @brief FAT12/FAT16文件系统特有的BPB信息字段
72 #[derive(Debug, Clone, Copy, Default)]
73 pub struct BiosParameterBlockLegacy {
74     /// int0x13的驱动器号
75     pub drive_num: u8,
76     /// 保留字段
77     pub reserved1: u8,
78     /// 扩展引导标记
79     pub boot_sig: u8,
80     /// 卷号
81     /// BS_VolID
82     pub volume_id: u32,
83     /// 文件系统类型
84     pub filesystem_type: u32,
85 }
86 
87 /// @brief FAT32文件系统特有的BPB信息字段
88 #[derive(Debug, Clone, Copy, Default)]
89 pub struct BiosParameterBlockFAT32 {
90     /// FAT32每FAT扇区数
91     /// BPB_FATSz32
92     pub fat_size_32: u32,
93 
94     /// 扩展标记
95     /// Bits 0-3 -- Zero based number of active FAT(活跃的FAT表的编号)
96     /// Only valid if mirroring iFAT32s disabled
97     /// Bits 4-6 -- 保留
98     /// Bit 7 -- 0表示在运行时,所有的FAT表都互为镜像
99     ///       -- 1表示只使用1个FAT表,具体使用的FAT表的编号需要看Bits 0-3
100     /// Bits 8-15 -- 保留备用
101     /// BPB_ExtFlags
102     pub ext_flags: u16,
103 
104     /// 文件系统版本号。
105     /// 高字节表示主版本号,低字节表示次版本号。
106     /// BPB_FSVer
107     pub fs_version: u16,
108 
109     /// 根目录的簇号
110     /// BPB_RootClus
111     pub root_cluster: u32,
112 
113     /// FsInfo结构体在分区内的偏移量(单位:扇区)
114     pub fs_info: u16,
115 
116     /// 如果这个值非0,那么它表示备份的引导扇区号。
117     /// BPB_BkBootSec
118     pub backup_boot_sec: u16,
119 
120     /// 保留备用
121     /// BPB_Reserved0
122     pub reserved0: [u8; 12],
123 
124     /// int0x13的驱动器号
125     /// BS_DrvNum
126     pub drive_num: u8,
127 
128     pub reserved1: u8,
129 
130     /// 引导标记
131     /// BS_BootSig
132     pub boot_sig: u8,
133 
134     /// 卷号
135     /// BS_VolID
136     pub volume_id: u32,
137 
138     /// 卷标
139     /// BS_VolLab
140     pub volume_label: [u8; 11],
141 
142     /// 文件系统类型
143     /// BS_FilSystype
144     pub filesystem_type: [u8; 8],
145 }
146 
147 impl Default for FATType {
148     fn default() -> Self {
149         return FATType::FAT32(BiosParameterBlockFAT32::default());
150     }
151 }
152 
153 impl FATType {
154     /// @brief 获取指定的簇对应的FAT表项在分区内的字节偏移量
155     ///
156     /// @param cluster 要查询的簇
157     /// @param fat_start_sector FAT表的起始扇区
158     /// @param bytes_per_sec 文件系统每扇区的字节数
159     ///
160     /// @return 指定的簇对应的FAT表项在分区内的字节偏移量
161     #[inline]
162     pub fn get_fat_bytes_offset(
163         &self,
164         cluster: Cluster,
165         fat_start_sector: u64,
166         bytes_per_sec: u64,
167     ) -> u64 {
168         let current_cluster = cluster.cluster_num;
169         // 要查询的簇,在FAT表中的字节偏移量
170         let fat_bytes_offset = match self {
171             FATType::FAT12(_) => current_cluster + (current_cluster / 2),
172             FATType::FAT16(_) => current_cluster * 2,
173             FATType::FAT32(_) => current_cluster * 4,
174         };
175         let fat_sec_number = fat_start_sector + (fat_bytes_offset / bytes_per_sec);
176         let fat_ent_offset = fat_bytes_offset % bytes_per_sec;
177         return fat_sec_number * bytes_per_sec + fat_ent_offset;
178     }
179 }
180 
181 impl BiosParameterBlockLegacy {
182     /// @brief 验证FAT12/16 BPB的信息是否合法
183     fn validate(&self, _bpb: &BiosParameterBlock) -> Result<(), SystemError> {
184         return Ok(());
185     }
186 }
187 
188 impl BiosParameterBlockFAT32 {
189     /// @brief 验证BPB32的信息是否合法
190     fn validate(&self, bpb: &BiosParameterBlock) -> Result<(), SystemError> {
191         if bpb.fat_size_16 != 0 {
192             kerror!("Invalid fat_size_16 value in BPB (should be zero for FAT32)");
193             return Err(SystemError::EINVAL);
194         }
195 
196         if bpb.root_entries_cnt != 0 {
197             kerror!("Invalid root_entries value in BPB (should be zero for FAT32)");
198             return Err(SystemError::EINVAL);
199         }
200 
201         if bpb.total_sectors_16 != 0 {
202             kerror!("Invalid total_sectors_16 value in BPB (should be zero for FAT32)");
203             return Err(SystemError::EINVAL);
204         }
205 
206         if self.fat_size_32 == 0 {
207             kerror!("Invalid fat_size_32 value in BPB (should be non-zero for FAT32)");
208             return Err(SystemError::EINVAL);
209         }
210 
211         if self.fs_version != 0 {
212             kerror!("Unknown FAT FS version");
213             return Err(SystemError::EINVAL);
214         }
215 
216         return Ok(());
217     }
218 }
219 
220 impl BiosParameterBlock {
221     pub fn new(partition: Arc<Partition>) -> Result<BiosParameterBlock, SystemError> {
222         let mut v = Vec::with_capacity(LBA_SIZE);
223         v.resize(LBA_SIZE, 0);
224 
225         // 读取分区的引导扇区
226         partition
227             .disk()
228             .read_at(partition.lba_start as usize, 1, &mut v)?;
229 
230         // 获取指针对象
231         let mut cursor = VecCursor::new(v);
232 
233         let mut bpb = BiosParameterBlock::default();
234 
235         cursor.read_exact(&mut bpb.jmp_boot)?;
236         cursor.read_exact(&mut bpb.oem_name)?;
237         bpb.bytes_per_sector = cursor.read_u16()?;
238         bpb.sector_per_cluster = cursor.read_u8()?;
239         bpb.rsvd_sec_cnt = cursor.read_u16()?;
240         bpb.num_fats = cursor.read_u8()?;
241         bpb.root_entries_cnt = cursor.read_u16()?;
242         bpb.total_sectors_16 = cursor.read_u16()?;
243         bpb.media = cursor.read_u8()?;
244         bpb.fat_size_16 = cursor.read_u16()?;
245         bpb.sector_per_track = cursor.read_u16()?;
246         bpb.num_heads = cursor.read_u16()?;
247         bpb.hidden_sectors = cursor.read_u32()?;
248         bpb.total_sectors_32 = cursor.read_u32()?;
249 
250         let mut bpb32 = BiosParameterBlockFAT32::default();
251         bpb32.fat_size_32 = cursor.read_u32()?;
252         bpb32.ext_flags = cursor.read_u16()?;
253         bpb32.fs_version = cursor.read_u16()?;
254         bpb32.root_cluster = cursor.read_u32()?;
255         bpb32.fs_info = cursor.read_u16()?;
256         bpb32.backup_boot_sec = cursor.read_u16()?;
257 
258         cursor.read_exact(&mut bpb32.reserved0)?;
259         bpb32.drive_num = cursor.read_u8()?;
260         bpb32.reserved1 = cursor.read_u8()?;
261         bpb32.boot_sig = cursor.read_u8()?;
262         bpb32.volume_id = cursor.read_u32()?;
263         cursor.read_exact(&mut bpb32.volume_label)?;
264         cursor.read_exact(&mut bpb32.filesystem_type)?;
265 
266         // 跳过启动代码
267         cursor.seek(SeekFrom::SeekCurrent(420))?;
268         // 读取尾部的启动扇区标志
269         bpb.trail_sig = cursor.read_u16()?;
270 
271         // 计算根目录项占用的空间(单位:字节)
272         let root_sectors = ((bpb.root_entries_cnt as u32 * 32) + (bpb.bytes_per_sector as u32 - 1))
273             / (bpb.bytes_per_sector as u32);
274 
275         // 每FAT扇区数
276         let fat_size = if bpb.fat_size_16 != 0 {
277             bpb.fat_size_16 as u32
278         } else {
279             bpb32.fat_size_32
280         };
281 
282         // 当前分区总扇区数
283         let total_sectors = if bpb.total_sectors_16 != 0 {
284             bpb.total_sectors_16 as u32
285         } else {
286             bpb.total_sectors_32
287         };
288 
289         // 数据区扇区数
290         let data_sectors = total_sectors
291             - ((bpb.rsvd_sec_cnt as u32) + (bpb.num_fats as u32) * fat_size + root_sectors);
292         // 总的数据簇数量(向下对齐)
293         let count_clusters = data_sectors / (bpb.sector_per_cluster as u32);
294 
295         // 设置FAT类型
296         bpb.fat_type = if count_clusters < FATFileSystem::FAT12_MAX_CLUSTER {
297             FATType::FAT12(BiosParameterBlockLegacy::default())
298         } else if count_clusters <= FATFileSystem::FAT16_MAX_CLUSTER {
299             FATType::FAT16(BiosParameterBlockLegacy::default())
300         } else if count_clusters < FATFileSystem::FAT32_MAX_CLUSTER {
301             FATType::FAT32(bpb32)
302         } else {
303             // 都不符合条件,报错
304             return Err(SystemError::EINVAL);
305         };
306 
307         // 验证BPB的信息是否合法
308         bpb.validate()?;
309 
310         return Ok(bpb);
311     }
312 
313     /// @brief 验证BPB的信息是否合法
314     pub fn validate(&self) -> Result<(), SystemError> {
315         // 校验每扇区字节数是否合法
316         if self.bytes_per_sector.count_ones() != 1 {
317             kerror!("Invalid bytes per sector(not a power of 2)");
318             return Err(SystemError::EINVAL);
319         } else if self.bytes_per_sector < 512 {
320             kerror!("Invalid bytes per sector (value < 512)");
321             return Err(SystemError::EINVAL);
322         } else if self.bytes_per_sector > 4096 {
323             kerror!("Invalid bytes per sector (value > 4096)");
324             return Err(SystemError::EINVAL);
325         }
326 
327         if self.rsvd_sec_cnt < 1 {
328             kerror!("Invalid rsvd_sec_cnt value in BPB");
329             return Err(SystemError::EINVAL);
330         }
331 
332         if self.num_fats == 0 {
333             kerror!("Invalid fats value in BPB");
334             return Err(SystemError::EINVAL);
335         }
336 
337         if (self.total_sectors_16 == 0) && (self.total_sectors_32 == 0) {
338             kerror!("Invalid BPB (total_sectors_16 or total_sectors_32 should be non-zero)");
339             return Err(SystemError::EINVAL);
340         }
341 
342         let fat_size = match self.fat_type {
343             FATType::FAT32(bpb32) => {
344                 bpb32.validate(self)?;
345                 bpb32.fat_size_32
346             }
347             FATType::FAT16(bpb_legacy) | FATType::FAT12(bpb_legacy) => {
348                 bpb_legacy.validate(self)?;
349                 self.fat_size_16 as u32
350             }
351         };
352 
353         let root_sectors = ((self.root_entries_cnt as u32 * 32)
354             + (self.bytes_per_sector as u32 - 1))
355             / (self.bytes_per_sector as u32);
356 
357         // 当前分区总扇区数
358         let total_sectors = if self.total_sectors_16 != 0 {
359             self.total_sectors_16 as u32
360         } else {
361             self.total_sectors_32
362         };
363 
364         let first_data_sector =
365             (self.rsvd_sec_cnt as u32) + (self.num_fats as u32) * fat_size + root_sectors;
366 
367         // 总扇区数应当大于第一个数据扇区的扇区号
368         if total_sectors <= first_data_sector {
369             kerror!("Total sectors lesser than first data sector");
370             return Err(SystemError::EINVAL);
371         }
372 
373         return Ok(());
374     }
375 
376     pub fn get_volume_id(&self) -> u32 {
377         match self.fat_type {
378             FATType::FAT12(f) | FATType::FAT16(f) => {
379                 return f.volume_id;
380             }
381 
382             FATType::FAT32(f) => {
383                 return f.volume_id;
384             }
385         }
386     }
387 }
388