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