1 #![allow(dead_code)] 2 use alloc::sync::Arc; 3 use log::error; 4 use system_error::SystemError; 5 6 use crate::{ 7 driver::base::block::{block_device::LBA_SIZE, gendisk::GenDisk, SeekFrom}, 8 libs::vec_cursor::VecCursor, 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 { default() -> Self149 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] get_fat_bytes_offset( &self, cluster: Cluster, fat_start_sector: u64, bytes_per_sec: u64, ) -> u64163 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的信息是否合法 validate(&self, _bpb: &BiosParameterBlock) -> Result<(), SystemError>184 fn validate(&self, _bpb: &BiosParameterBlock) -> Result<(), SystemError> { 185 return Ok(()); 186 } 187 } 188 189 impl BiosParameterBlockFAT32 { 190 /// @brief 验证BPB32的信息是否合法 validate(&self, bpb: &BiosParameterBlock) -> Result<(), SystemError>191 fn validate(&self, bpb: &BiosParameterBlock) -> Result<(), SystemError> { 192 if bpb.fat_size_16 != 0 { 193 error!("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 error!("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 error!("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 error!("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 error!("Unknown FAT FS version"); 214 return Err(SystemError::EINVAL); 215 } 216 217 return Ok(()); 218 } 219 } 220 221 impl BiosParameterBlock { new(gendisk: &Arc<GenDisk>) -> Result<BiosParameterBlock, SystemError>222 pub fn new(gendisk: &Arc<GenDisk>) -> Result<BiosParameterBlock, SystemError> { 223 let mut v = vec![0; LBA_SIZE]; 224 // 读取分区的引导扇区 225 gendisk.read_at(&mut v, 0)?; 226 // 获取指针对象 227 let mut cursor = VecCursor::new(v); 228 229 let mut bpb = BiosParameterBlock::default(); 230 231 cursor.read_exact(&mut bpb.jmp_boot)?; 232 cursor.read_exact(&mut bpb.oem_name)?; 233 bpb.bytes_per_sector = cursor.read_u16()?; 234 bpb.sector_per_cluster = cursor.read_u8()?; 235 bpb.rsvd_sec_cnt = cursor.read_u16()?; 236 bpb.num_fats = cursor.read_u8()?; 237 bpb.root_entries_cnt = cursor.read_u16()?; 238 bpb.total_sectors_16 = cursor.read_u16()?; 239 bpb.media = cursor.read_u8()?; 240 bpb.fat_size_16 = cursor.read_u16()?; 241 bpb.sector_per_track = cursor.read_u16()?; 242 bpb.num_heads = cursor.read_u16()?; 243 bpb.hidden_sectors = cursor.read_u32()?; 244 bpb.total_sectors_32 = cursor.read_u32()?; 245 246 let mut bpb32 = BiosParameterBlockFAT32 { 247 fat_size_32: cursor.read_u32()?, 248 ext_flags: cursor.read_u16()?, 249 fs_version: cursor.read_u16()?, 250 root_cluster: cursor.read_u32()?, 251 fs_info: cursor.read_u16()?, 252 backup_boot_sec: cursor.read_u16()?, 253 drive_num: cursor.read_u8()?, 254 reserved1: cursor.read_u8()?, 255 boot_sig: cursor.read_u8()?, 256 volume_id: cursor.read_u32()?, 257 ..Default::default() 258 }; 259 cursor.read_exact(&mut bpb32.reserved0)?; 260 cursor.read_exact(&mut bpb32.volume_label)?; 261 cursor.read_exact(&mut bpb32.filesystem_type)?; 262 263 // 跳过启动代码 264 cursor.seek(SeekFrom::SeekCurrent(420))?; 265 // 读取尾部的启动扇区标志 266 bpb.trail_sig = cursor.read_u16()?; 267 268 // 计算根目录项占用的空间(单位:字节) 269 let root_sectors = ((bpb.root_entries_cnt as u32 * 32) + (bpb.bytes_per_sector as u32 - 1)) 270 / (bpb.bytes_per_sector as u32); 271 272 // 每FAT扇区数 273 let fat_size = if bpb.fat_size_16 != 0 { 274 bpb.fat_size_16 as u32 275 } else { 276 bpb32.fat_size_32 277 }; 278 279 // 当前分区总扇区数 280 let total_sectors = if bpb.total_sectors_16 != 0 { 281 bpb.total_sectors_16 as u32 282 } else { 283 bpb.total_sectors_32 284 }; 285 286 // 数据区扇区数 287 let data_sectors = total_sectors 288 - ((bpb.rsvd_sec_cnt as u32) + (bpb.num_fats as u32) * fat_size + root_sectors); 289 // 总的数据簇数量(向下对齐) 290 let count_clusters = data_sectors / (bpb.sector_per_cluster as u32); 291 292 // 设置FAT类型 293 bpb.fat_type = if count_clusters < FATFileSystem::FAT12_MAX_CLUSTER { 294 FATType::FAT12(BiosParameterBlockLegacy::default()) 295 } else if count_clusters <= FATFileSystem::FAT16_MAX_CLUSTER { 296 FATType::FAT16(BiosParameterBlockLegacy::default()) 297 } else if count_clusters < FATFileSystem::FAT32_MAX_CLUSTER { 298 FATType::FAT32(bpb32) 299 } else { 300 // 都不符合条件,报错 301 return Err(SystemError::EINVAL); 302 }; 303 304 // 验证BPB的信息是否合法 305 bpb.validate()?; 306 307 return Ok(bpb); 308 } 309 310 /// @brief 验证BPB的信息是否合法 validate(&self) -> Result<(), SystemError>311 pub fn validate(&self) -> Result<(), SystemError> { 312 // 校验每扇区字节数是否合法 313 if self.bytes_per_sector.count_ones() != 1 { 314 error!("Invalid bytes per sector(not a power of 2)"); 315 return Err(SystemError::EINVAL); 316 } else if self.bytes_per_sector < 512 { 317 error!("Invalid bytes per sector (value < 512)"); 318 return Err(SystemError::EINVAL); 319 } else if self.bytes_per_sector > 4096 { 320 error!("Invalid bytes per sector (value > 4096)"); 321 return Err(SystemError::EINVAL); 322 } 323 324 if self.rsvd_sec_cnt < 1 { 325 error!("Invalid rsvd_sec_cnt value in BPB"); 326 return Err(SystemError::EINVAL); 327 } 328 329 if self.num_fats == 0 { 330 error!("Invalid fats value in BPB"); 331 return Err(SystemError::EINVAL); 332 } 333 334 if (self.total_sectors_16 == 0) && (self.total_sectors_32 == 0) { 335 error!("Invalid BPB (total_sectors_16 or total_sectors_32 should be non-zero)"); 336 return Err(SystemError::EINVAL); 337 } 338 339 let fat_size = match self.fat_type { 340 FATType::FAT32(bpb32) => { 341 bpb32.validate(self)?; 342 bpb32.fat_size_32 343 } 344 FATType::FAT16(bpb_legacy) | FATType::FAT12(bpb_legacy) => { 345 bpb_legacy.validate(self)?; 346 self.fat_size_16 as u32 347 } 348 }; 349 350 let root_sectors = ((self.root_entries_cnt as u32 * 32) 351 + (self.bytes_per_sector as u32 - 1)) 352 / (self.bytes_per_sector as u32); 353 354 // 当前分区总扇区数 355 let total_sectors = if self.total_sectors_16 != 0 { 356 self.total_sectors_16 as u32 357 } else { 358 self.total_sectors_32 359 }; 360 361 let first_data_sector = 362 (self.rsvd_sec_cnt as u32) + (self.num_fats as u32) * fat_size + root_sectors; 363 364 // 总扇区数应当大于第一个数据扇区的扇区号 365 if total_sectors <= first_data_sector { 366 error!("Total sectors lesser than first data sector"); 367 return Err(SystemError::EINVAL); 368 } 369 370 return Ok(()); 371 } 372 get_volume_id(&self) -> u32373 pub fn get_volume_id(&self) -> u32 { 374 match self.fat_type { 375 FATType::FAT12(f) | FATType::FAT16(f) => { 376 return f.volume_id; 377 } 378 379 FATType::FAT32(f) => { 380 return f.volume_id; 381 } 382 } 383 } 384 } 385