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, 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 { 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 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 { new(partition: Arc<Partition>) -> Result<BiosParameterBlock, SystemError>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的信息是否合法 validate(&self) -> Result<(), SystemError>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 get_volume_id(&self) -> u32377 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