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