修正了FAT32判断逻辑,解决了文件系统为FAT12/16时系统无法正常启动的问题。 (#211)

* fix(fat): fix determination of fat type casue crash if fs is fat12/16

* refactor(fat): split BiosParameterBlock.validate() into BiosParameterBlockFAT32.validate() and BiosParameterBlockLegacy.validate()

* 调整“最大允许的簇号”的常量放置的位置。

---------

Co-authored-by: longjin <longjin@RinGoTek.cn>
This commit is contained in:
WaferJay 2023-03-27 09:32:43 +08:00 committed by GitHub
parent 45b8371173
commit 2286eda652
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 68 additions and 53 deletions

View File

@ -8,7 +8,7 @@ use crate::{
libs::vec_cursor::VecCursor, libs::vec_cursor::VecCursor,
}; };
use super::fs::Cluster; use super::fs::{Cluster, FATFileSystem};
/// 对于所有的FAT文件系统都适用的Bios Parameter Block结构体 /// 对于所有的FAT文件系统都适用的Bios Parameter Block结构体
#[derive(Debug, Clone, Copy, Default)] #[derive(Debug, Clone, Copy, Default)]
@ -179,6 +179,45 @@ impl FATType {
} }
} }
impl BiosParameterBlockLegacy {
/// @brief 验证FAT12/16 BPB的信息是否合法
fn validate(&self, _bpb: &BiosParameterBlock) -> Result<(), i32> {
return Ok(());
}
}
impl BiosParameterBlockFAT32 {
/// @brief 验证BPB32的信息是否合法
fn validate(&self, bpb: &BiosParameterBlock) -> Result<(), i32> {
if bpb.fat_size_16 != 0 {
kerror!("Invalid fat_size_16 value in BPB (should be zero for FAT32)");
return Err(-(EINVAL as i32));
}
if bpb.root_entries_cnt != 0 {
kerror!("Invalid root_entries value in BPB (should be zero for FAT32)");
return Err(-(EINVAL as i32));
}
if bpb.total_sectors_16 != 0 {
kerror!("Invalid total_sectors_16 value in BPB (should be zero for FAT32)");
return Err(-(EINVAL as i32));
}
if self.fat_size_32 == 0 {
kerror!("Invalid fat_size_32 value in BPB (should be non-zero for FAT32)");
return Err(-(EINVAL as i32));
}
if self.fs_version != 0 {
kerror!("Unknown FAT FS version");
return Err(-(EINVAL as i32));
}
return Ok(());
}
}
impl BiosParameterBlock { impl BiosParameterBlock {
pub fn new(partition: Arc<Partition>) -> Result<BiosParameterBlock, i32> { pub fn new(partition: Arc<Partition>) -> Result<BiosParameterBlock, i32> {
let mut v = Vec::with_capacity(LBA_SIZE); let mut v = Vec::with_capacity(LBA_SIZE);
@ -230,9 +269,6 @@ impl BiosParameterBlock {
// 读取尾部的启动扇区标志 // 读取尾部的启动扇区标志
bpb.trail_sig = cursor.read_u16()?; bpb.trail_sig = cursor.read_u16()?;
// 验证BPB32的信息是否合法
bpb.validate(&bpb32)?;
// 计算根目录项占用的空间(单位:字节) // 计算根目录项占用的空间(单位:字节)
let root_sectors = ((bpb.root_entries_cnt as u32 * 32) + (bpb.bytes_per_sector as u32 - 1)) let root_sectors = ((bpb.root_entries_cnt as u32 * 32) + (bpb.bytes_per_sector as u32 - 1))
/ (bpb.bytes_per_sector as u32); / (bpb.bytes_per_sector as u32);
@ -258,19 +294,25 @@ impl BiosParameterBlock {
let count_clusters = data_sectors / (bpb.sector_per_cluster as u32); let count_clusters = data_sectors / (bpb.sector_per_cluster as u32);
// 设置FAT类型 // 设置FAT类型
bpb.fat_type = if count_clusters < 4085 { bpb.fat_type = if count_clusters < FATFileSystem::FAT12_MAX_CLUSTER {
FATType::FAT12(BiosParameterBlockLegacy::default()) FATType::FAT12(BiosParameterBlockLegacy::default())
} else if count_clusters < 65525 { } else if count_clusters <= FATFileSystem::FAT16_MAX_CLUSTER {
FATType::FAT16(BiosParameterBlockLegacy::default()) FATType::FAT16(BiosParameterBlockLegacy::default())
} else { } else if count_clusters < FATFileSystem::FAT32_MAX_CLUSTER {
FATType::FAT32(bpb32) FATType::FAT32(bpb32)
} else {
// 都不符合条件,报错
return Err(-(EINVAL as i32));
}; };
// 验证BPB的信息是否合法
bpb.validate()?;
return Ok(bpb); return Ok(bpb);
} }
/// @brief 验证BPB32的信息是否合法 /// @brief 验证BPB的信息是否合法
pub fn validate(&self, bpb32: &BiosParameterBlockFAT32) -> Result<(), i32> { pub fn validate(&self) -> Result<(), i32> {
// 校验每扇区字节数是否合法 // 校验每扇区字节数是否合法
if self.bytes_per_sector.count_ones() != 1 { if self.bytes_per_sector.count_ones() != 1 {
kerror!("Invalid bytes per sector(not a power of 2)"); kerror!("Invalid bytes per sector(not a power of 2)");
@ -283,8 +325,6 @@ impl BiosParameterBlock {
return Err(-(EINVAL as i32)); return Err(-(EINVAL as i32));
} }
let is_fat32 = self.is_fat32();
if self.rsvd_sec_cnt < 1 { if self.rsvd_sec_cnt < 1 {
kerror!("Invalid rsvd_sec_cnt value in BPB"); kerror!("Invalid rsvd_sec_cnt value in BPB");
return Err(-(EINVAL as i32)); return Err(-(EINVAL as i32));
@ -295,42 +335,26 @@ impl BiosParameterBlock {
return Err(-(EINVAL as i32)); return Err(-(EINVAL as i32));
} }
if is_fat32 && self.root_entries_cnt != 0 {
kerror!("Invalid root_entries value in BPB (should be zero for FAT32)");
return Err(-(EINVAL as i32));
}
if is_fat32 && self.total_sectors_16 != 0 {
kerror!("Invalid total_sectors_16 value in BPB (should be zero for FAT32)");
return Err(-(EINVAL as i32));
}
if (self.total_sectors_16 == 0) && (self.total_sectors_32 == 0) { if (self.total_sectors_16 == 0) && (self.total_sectors_32 == 0) {
kerror!("Invalid BPB (total_sectors_16 or total_sectors_32 should be non-zero)"); kerror!("Invalid BPB (total_sectors_16 or total_sectors_32 should be non-zero)");
return Err(-(EINVAL as i32)); return Err(-(EINVAL as i32));
} }
if is_fat32 && bpb32.fat_size_32 == 0 { let fat_size = match self.fat_type {
kerror!("Invalid fat_size_32 value in BPB (should be non-zero for FAT32)"); FATType::FAT32(bpb32) => {
return Err(-(EINVAL as i32)); bpb32.validate(self)?;
bpb32.fat_size_32
} }
FATType::FAT16(bpb_legacy) | FATType::FAT12(bpb_legacy) => {
if bpb32.fs_version != 0 { bpb_legacy.validate(self)?;
kerror!("Unknown FAT FS version"); self.fat_size_16 as u32
return Err(-(EINVAL as i32));
} }
};
let root_sectors = ((self.root_entries_cnt as u32 * 32) let root_sectors = ((self.root_entries_cnt as u32 * 32)
+ (self.bytes_per_sector as u32 - 1)) + (self.bytes_per_sector as u32 - 1))
/ (self.bytes_per_sector as u32); / (self.bytes_per_sector as u32);
// 每FAT扇区数
let fat_size = if self.fat_size_16 != 0 {
self.fat_size_16 as u32
} else {
bpb32.fat_size_32
};
// 当前分区总扇区数 // 当前分区总扇区数
let total_sectors = if self.total_sectors_16 != 0 { let total_sectors = if self.total_sectors_16 != 0 {
self.total_sectors_16 as u32 self.total_sectors_16 as u32
@ -341,31 +365,15 @@ impl BiosParameterBlock {
let first_data_sector = let first_data_sector =
(self.rsvd_sec_cnt as u32) + (self.num_fats as u32) * fat_size + root_sectors; (self.rsvd_sec_cnt as u32) + (self.num_fats as u32) * fat_size + root_sectors;
// 数据区扇区数
let data_sectors = total_sectors - first_data_sector;
// 总的数据簇数量(向下对齐)
let count_clusters = data_sectors / (self.sector_per_cluster as u32);
// 总扇区数应当大于第一个数据扇区的扇区号 // 总扇区数应当大于第一个数据扇区的扇区号
if total_sectors <= first_data_sector { if total_sectors <= first_data_sector {
kerror!("Total sectors lesser than first data sector"); kerror!("Total sectors lesser than first data sector");
return Err(-(EINVAL as i32)); return Err(-(EINVAL as i32));
} }
// 检查文件系统类型与总的数据簇数量的关系是否合法
if (is_fat32 && (count_clusters < 65525)) || ((!is_fat32) && (count_clusters >= 65525)) {
kerror!("FAT determination using tot_sec_16 and count_cluster differs");
return Err(-(EINVAL as i32));
}
return Ok(()); return Ok(());
} }
/// @brief 判断当前是否为fat32的bpb
fn is_fat32(&self) -> bool {
// fat32的bpb这个字段是0
return self.total_sectors_16 == 0;
}
pub fn get_volume_id(&self) -> u32 { pub fn get_volume_id(&self) -> u32 {
match self.fat_type { match self.fat_type {
FATType::FAT12(f) | FATType::FAT16(f) => { FATType::FAT12(f) | FATType::FAT16(f) => {

View File

@ -244,6 +244,13 @@ impl FileSystem for FATFileSystem {
} }
impl FATFileSystem { impl FATFileSystem {
/// FAT12允许的最大簇号
pub const FAT12_MAX_CLUSTER: u32 = 0xFF5;
/// FAT16允许的最大簇号
pub const FAT16_MAX_CLUSTER: u32 = 0xFFF5;
/// FAT32允许的最大簇号
pub const FAT32_MAX_CLUSTER: u32 = 0x0FFFFFF7;
pub fn new(partition: Arc<Partition>) -> Result<Arc<FATFileSystem>, i32> { pub fn new(partition: Arc<Partition>) -> Result<Arc<FATFileSystem>, i32> {
let bpb = BiosParameterBlock::new(partition.clone())?; let bpb = BiosParameterBlock::new(partition.clone())?;