1 #![allow(dead_code)] 2 use alloc::{sync::Arc, vec::Vec}; 3 4 use crate::{ 5 include::bindings::bindings::EINVAL, 6 io::{device::LBA_SIZE, disk_info::Partition, SeekFrom}, 7 kerror, 8 libs::vec_cursor::VecCursor, 9 }; 10 11 use super::fs::Cluster; 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 BiosParameterBlock { new(partition: Arc<Partition>) -> Result<BiosParameterBlock, i32>183 pub fn new(partition: Arc<Partition>) -> Result<BiosParameterBlock, i32> { 184 let mut v = Vec::with_capacity(LBA_SIZE); 185 v.resize(LBA_SIZE, 0); 186 187 // 读取分区的引导扇区 188 partition 189 .disk() 190 .read_at(partition.lba_start as usize, 1, &mut v)?; 191 192 // 获取指针对象 193 let mut cursor = VecCursor::new(v); 194 195 let mut bpb = BiosParameterBlock::default(); 196 197 cursor.read_exact(&mut bpb.jmp_boot)?; 198 cursor.read_exact(&mut bpb.oem_name)?; 199 bpb.bytes_per_sector = cursor.read_u16()?; 200 bpb.sector_per_cluster = cursor.read_u8()?; 201 bpb.rsvd_sec_cnt = cursor.read_u16()?; 202 bpb.num_fats = cursor.read_u8()?; 203 bpb.root_entries_cnt = cursor.read_u16()?; 204 bpb.total_sectors_16 = cursor.read_u16()?; 205 bpb.media = cursor.read_u8()?; 206 bpb.fat_size_16 = cursor.read_u16()?; 207 bpb.sector_per_track = cursor.read_u16()?; 208 bpb.num_heads = cursor.read_u16()?; 209 bpb.hidden_sectors = cursor.read_u32()?; 210 bpb.total_sectors_32 = cursor.read_u32()?; 211 212 let mut bpb32 = BiosParameterBlockFAT32::default(); 213 bpb32.fat_size_32 = cursor.read_u32()?; 214 bpb32.ext_flags = cursor.read_u16()?; 215 bpb32.fs_version = cursor.read_u16()?; 216 bpb32.root_cluster = cursor.read_u32()?; 217 bpb32.fs_info = cursor.read_u16()?; 218 bpb32.backup_boot_sec = cursor.read_u16()?; 219 220 cursor.read_exact(&mut bpb32.reserved0)?; 221 bpb32.drive_num = cursor.read_u8()?; 222 bpb32.reserved1 = cursor.read_u8()?; 223 bpb32.boot_sig = cursor.read_u8()?; 224 bpb32.volume_id = cursor.read_u32()?; 225 cursor.read_exact(&mut bpb32.volume_label)?; 226 cursor.read_exact(&mut bpb32.filesystem_type)?; 227 228 // 跳过启动代码 229 cursor.seek(SeekFrom::SeekCurrent(420))?; 230 // 读取尾部的启动扇区标志 231 bpb.trail_sig = cursor.read_u16()?; 232 233 // 验证BPB32的信息是否合法 234 bpb.validate(&bpb32)?; 235 236 // 计算根目录项占用的空间(单位:字节) 237 let root_sectors = ((bpb.root_entries_cnt as u32 * 32) + (bpb.bytes_per_sector as u32 - 1)) 238 / (bpb.bytes_per_sector as u32); 239 240 // 每FAT扇区数 241 let fat_size = if bpb.fat_size_16 != 0 { 242 bpb.fat_size_16 as u32 243 } else { 244 bpb32.fat_size_32 245 }; 246 247 // 当前分区总扇区数 248 let total_sectors = if bpb.total_sectors_16 != 0 { 249 bpb.total_sectors_16 as u32 250 } else { 251 bpb.total_sectors_32 252 }; 253 254 // 数据区扇区数 255 let data_sectors = total_sectors 256 - ((bpb.rsvd_sec_cnt as u32) + (bpb.num_fats as u32) * fat_size + root_sectors); 257 // 总的数据簇数量(向下对齐) 258 let count_clusters = data_sectors / (bpb.sector_per_cluster as u32); 259 260 // 设置FAT类型 261 bpb.fat_type = if count_clusters < 4085 { 262 FATType::FAT12(BiosParameterBlockLegacy::default()) 263 } else if count_clusters < 65525 { 264 FATType::FAT16(BiosParameterBlockLegacy::default()) 265 } else { 266 FATType::FAT32(bpb32) 267 }; 268 269 return Ok(bpb); 270 } 271 272 /// @brief 验证BPB32的信息是否合法 validate(&self, bpb32: &BiosParameterBlockFAT32) -> Result<(), i32>273 pub fn validate(&self, bpb32: &BiosParameterBlockFAT32) -> Result<(), i32> { 274 // 校验每扇区字节数是否合法 275 if self.bytes_per_sector.count_ones() != 1 { 276 kerror!("Invalid bytes per sector(not a power of 2)"); 277 return Err(-(EINVAL as i32)); 278 } else if self.bytes_per_sector < 512 { 279 kerror!("Invalid bytes per sector (value < 512)"); 280 return Err(-(EINVAL as i32)); 281 } else if self.bytes_per_sector > 4096 { 282 kerror!("Invalid bytes per sector (value > 4096)"); 283 return Err(-(EINVAL as i32)); 284 } 285 286 let is_fat32 = self.is_fat32(); 287 288 if self.rsvd_sec_cnt < 1 { 289 kerror!("Invalid rsvd_sec_cnt value in BPB"); 290 return Err(-(EINVAL as i32)); 291 } 292 293 if self.num_fats == 0 { 294 kerror!("Invalid fats value in BPB"); 295 return Err(-(EINVAL as i32)); 296 } 297 298 if is_fat32 && self.root_entries_cnt != 0 { 299 kerror!("Invalid root_entries value in BPB (should be zero for FAT32)"); 300 return Err(-(EINVAL as i32)); 301 } 302 303 if is_fat32 && self.total_sectors_16 != 0 { 304 kerror!("Invalid total_sectors_16 value in BPB (should be zero for FAT32)"); 305 return Err(-(EINVAL as i32)); 306 } 307 308 if (self.total_sectors_16 == 0) && (self.total_sectors_32 == 0) { 309 kerror!("Invalid BPB (total_sectors_16 or total_sectors_32 should be non-zero)"); 310 return Err(-(EINVAL as i32)); 311 } 312 313 if is_fat32 && bpb32.fat_size_32 == 0 { 314 kerror!("Invalid fat_size_32 value in BPB (should be non-zero for FAT32)"); 315 return Err(-(EINVAL as i32)); 316 } 317 318 if bpb32.fs_version != 0 { 319 kerror!("Unknown FAT FS version"); 320 return Err(-(EINVAL as i32)); 321 } 322 323 let root_sectors = ((self.root_entries_cnt as u32 * 32) 324 + (self.bytes_per_sector as u32 - 1)) 325 / (self.bytes_per_sector as u32); 326 327 // 每FAT扇区数 328 let fat_size = if self.fat_size_16 != 0 { 329 self.fat_size_16 as u32 330 } else { 331 bpb32.fat_size_32 332 }; 333 334 // 当前分区总扇区数 335 let total_sectors = if self.total_sectors_16 != 0 { 336 self.total_sectors_16 as u32 337 } else { 338 self.total_sectors_32 339 }; 340 341 let first_data_sector = 342 (self.rsvd_sec_cnt as u32) + (self.num_fats as u32) * fat_size + root_sectors; 343 344 // 数据区扇区数 345 let data_sectors = total_sectors - first_data_sector; 346 // 总的数据簇数量(向下对齐) 347 let count_clusters = data_sectors / (self.sector_per_cluster as u32); 348 349 // 总扇区数应当大于第一个数据扇区的扇区号 350 if total_sectors <= first_data_sector { 351 kerror!("Total sectors lesser than first data sector"); 352 return Err(-(EINVAL as i32)); 353 } 354 355 // 检查文件系统类型与总的数据簇数量的关系是否合法 356 if (is_fat32 && (count_clusters < 65525)) || ((!is_fat32) && (count_clusters >= 65525)) { 357 kerror!("FAT determination using tot_sec_16 and count_cluster differs"); 358 return Err(-(EINVAL as i32)); 359 } 360 return Ok(()); 361 } 362 363 /// @brief 判断当前是否为fat32的bpb is_fat32(&self) -> bool364 fn is_fat32(&self) -> bool { 365 // fat32的bpb,这个字段是0 366 return self.total_sectors_16 == 0; 367 } 368 get_volume_id(&self) -> u32369 pub fn get_volume_id(&self) -> u32 { 370 match self.fat_type { 371 FATType::FAT12(f) | FATType::FAT16(f) => { 372 return f.volume_id; 373 } 374 375 FATType::FAT32(f) => { 376 return f.volume_id; 377 } 378 } 379 } 380 } 381