bpb.rs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. #![allow(dead_code)]
  2. use alloc::sync::Arc;
  3. use log::error;
  4. use system_error::SystemError;
  5. use crate::{
  6. driver::base::block::{block_device::LBA_SIZE, gendisk::GenDisk, SeekFrom},
  7. libs::vec_cursor::VecCursor,
  8. };
  9. use super::fs::{Cluster, FATFileSystem};
  10. /// 对于所有的FAT文件系统都适用的Bios Parameter Block结构体
  11. #[derive(Debug, Clone, Copy, Default)]
  12. pub struct BiosParameterBlock {
  13. /// 跳转指令
  14. pub jmp_boot: [u8; 3],
  15. /// 生产厂商名(表明是哪个操作系统格式化了这个卷)
  16. pub oem_name: [u8; 8],
  17. /// 每扇区字节数
  18. pub bytes_per_sector: u16,
  19. /// 每簇扇区数
  20. pub sector_per_cluster: u8,
  21. /// 保留扇区数
  22. pub rsvd_sec_cnt: u16,
  23. /// FAT表数量
  24. pub num_fats: u8,
  25. /// 根目录下的32字节目录项数量最大值(只对FAT12、FAT16生效)
  26. pub root_entries_cnt: u16,
  27. /// 当前分区的总扇区数(只对FAT12、FAT16生效)
  28. pub total_sectors_16: u16,
  29. /// 介质描述符
  30. pub media: u8,
  31. /// FAT12/16每FAT扇区数
  32. pub fat_size_16: u16,
  33. /// 每磁道扇区数
  34. pub sector_per_track: u16,
  35. /// 磁头数
  36. pub num_heads: u16,
  37. /// 隐藏扇区数
  38. pub hidden_sectors: u32,
  39. /// FAT32的总扇区数
  40. pub total_sectors_32: u32,
  41. /// FAT文件系统类型(以及他们的一些私有信息字段)
  42. pub fat_type: FATType,
  43. /// 引导扇区结束标志0xAA55
  44. pub trail_sig: u16,
  45. }
  46. #[derive(Debug, Clone, Copy)]
  47. pub enum FATType {
  48. FAT12(BiosParameterBlockLegacy),
  49. FAT16(BiosParameterBlockLegacy),
  50. FAT32(BiosParameterBlockFAT32),
  51. }
  52. /// @brief FAT12/FAT16文件系统特有的BPB信息字段
  53. #[derive(Debug, Clone, Copy, Default)]
  54. pub struct BiosParameterBlockLegacy {
  55. /// int0x13的驱动器号
  56. pub drive_num: u8,
  57. /// 保留字段
  58. pub reserved1: u8,
  59. /// 扩展引导标记
  60. pub boot_sig: u8,
  61. /// 卷号
  62. /// BS_VolID
  63. pub volume_id: u32,
  64. /// 文件系统类型
  65. pub filesystem_type: u32,
  66. }
  67. /// @brief FAT32文件系统特有的BPB信息字段
  68. #[derive(Debug, Clone, Copy, Default)]
  69. pub struct BiosParameterBlockFAT32 {
  70. /// FAT32每FAT扇区数
  71. /// BPB_FATSz32
  72. pub fat_size_32: u32,
  73. /// 扩展标记
  74. /// Bits 0-3 -- Zero based number of active FAT(活跃的FAT表的编号)
  75. /// Only valid if mirroring iFAT32s disabled
  76. /// Bits 4-6 -- 保留
  77. /// Bit 7 -- 0表示在运行时,所有的FAT表都互为镜像
  78. /// -- 1表示只使用1个FAT表,具体使用的FAT表的编号需要看Bits 0-3
  79. /// Bits 8-15 -- 保留备用
  80. /// BPB_ExtFlags
  81. pub ext_flags: u16,
  82. /// 文件系统版本号。
  83. /// 高字节表示主版本号,低字节表示次版本号。
  84. /// BPB_FSVer
  85. pub fs_version: u16,
  86. /// 根目录的簇号
  87. /// BPB_RootClus
  88. pub root_cluster: u32,
  89. /// FsInfo结构体在分区内的偏移量(单位:扇区)
  90. pub fs_info: u16,
  91. /// 如果这个值非0,那么它表示备份的引导扇区号。
  92. /// BPB_BkBootSec
  93. pub backup_boot_sec: u16,
  94. /// 保留备用
  95. /// BPB_Reserved0
  96. pub reserved0: [u8; 12],
  97. /// int0x13的驱动器号
  98. /// BS_DrvNum
  99. pub drive_num: u8,
  100. pub reserved1: u8,
  101. /// 引导标记
  102. /// BS_BootSig
  103. pub boot_sig: u8,
  104. /// 卷号
  105. /// BS_VolID
  106. pub volume_id: u32,
  107. /// 卷标
  108. /// BS_VolLab
  109. pub volume_label: [u8; 11],
  110. /// 文件系统类型
  111. /// BS_FilSystype
  112. pub filesystem_type: [u8; 8],
  113. }
  114. impl Default for FATType {
  115. fn default() -> Self {
  116. return FATType::FAT32(BiosParameterBlockFAT32::default());
  117. }
  118. }
  119. impl FATType {
  120. /// @brief 获取指定的簇对应的FAT表项在分区内的字节偏移量
  121. ///
  122. /// @param cluster 要查询的簇
  123. /// @param fat_start_sector FAT表的起始扇区
  124. /// @param bytes_per_sec 文件系统每扇区的字节数
  125. ///
  126. /// @return 指定的簇对应的FAT表项在分区内的字节偏移量
  127. #[inline]
  128. pub fn get_fat_bytes_offset(
  129. &self,
  130. cluster: Cluster,
  131. fat_start_sector: u64,
  132. bytes_per_sec: u64,
  133. ) -> u64 {
  134. let current_cluster = cluster.cluster_num;
  135. // 要查询的簇,在FAT表中的字节偏移量
  136. let fat_bytes_offset = match self {
  137. FATType::FAT12(_) => current_cluster + (current_cluster / 2),
  138. FATType::FAT16(_) => current_cluster * 2,
  139. FATType::FAT32(_) => current_cluster * 4,
  140. };
  141. let fat_sec_number = fat_start_sector + (fat_bytes_offset / bytes_per_sec);
  142. let fat_ent_offset = fat_bytes_offset % bytes_per_sec;
  143. return fat_sec_number * bytes_per_sec + fat_ent_offset;
  144. }
  145. }
  146. impl BiosParameterBlockLegacy {
  147. /// @brief 验证FAT12/16 BPB的信息是否合法
  148. fn validate(&self, _bpb: &BiosParameterBlock) -> Result<(), SystemError> {
  149. return Ok(());
  150. }
  151. }
  152. impl BiosParameterBlockFAT32 {
  153. /// @brief 验证BPB32的信息是否合法
  154. fn validate(&self, bpb: &BiosParameterBlock) -> Result<(), SystemError> {
  155. if bpb.fat_size_16 != 0 {
  156. error!("Invalid fat_size_16 value in BPB (should be zero for FAT32)");
  157. return Err(SystemError::EINVAL);
  158. }
  159. if bpb.root_entries_cnt != 0 {
  160. error!("Invalid root_entries value in BPB (should be zero for FAT32)");
  161. return Err(SystemError::EINVAL);
  162. }
  163. if bpb.total_sectors_16 != 0 {
  164. error!("Invalid total_sectors_16 value in BPB (should be zero for FAT32)");
  165. return Err(SystemError::EINVAL);
  166. }
  167. if self.fat_size_32 == 0 {
  168. error!("Invalid fat_size_32 value in BPB (should be non-zero for FAT32)");
  169. return Err(SystemError::EINVAL);
  170. }
  171. if self.fs_version != 0 {
  172. error!("Unknown FAT FS version");
  173. return Err(SystemError::EINVAL);
  174. }
  175. return Ok(());
  176. }
  177. }
  178. impl BiosParameterBlock {
  179. pub fn new(gendisk: &Arc<GenDisk>) -> Result<BiosParameterBlock, SystemError> {
  180. let mut v = vec![0; LBA_SIZE];
  181. // 读取分区的引导扇区
  182. gendisk.read_at(&mut v, 0)?;
  183. // 获取指针对象
  184. let mut cursor = VecCursor::new(v);
  185. let mut bpb = BiosParameterBlock::default();
  186. cursor.read_exact(&mut bpb.jmp_boot)?;
  187. cursor.read_exact(&mut bpb.oem_name)?;
  188. bpb.bytes_per_sector = cursor.read_u16()?;
  189. bpb.sector_per_cluster = cursor.read_u8()?;
  190. bpb.rsvd_sec_cnt = cursor.read_u16()?;
  191. bpb.num_fats = cursor.read_u8()?;
  192. bpb.root_entries_cnt = cursor.read_u16()?;
  193. bpb.total_sectors_16 = cursor.read_u16()?;
  194. bpb.media = cursor.read_u8()?;
  195. bpb.fat_size_16 = cursor.read_u16()?;
  196. bpb.sector_per_track = cursor.read_u16()?;
  197. bpb.num_heads = cursor.read_u16()?;
  198. bpb.hidden_sectors = cursor.read_u32()?;
  199. bpb.total_sectors_32 = cursor.read_u32()?;
  200. let mut bpb32 = BiosParameterBlockFAT32 {
  201. fat_size_32: cursor.read_u32()?,
  202. ext_flags: cursor.read_u16()?,
  203. fs_version: cursor.read_u16()?,
  204. root_cluster: cursor.read_u32()?,
  205. fs_info: cursor.read_u16()?,
  206. backup_boot_sec: cursor.read_u16()?,
  207. drive_num: cursor.read_u8()?,
  208. reserved1: cursor.read_u8()?,
  209. boot_sig: cursor.read_u8()?,
  210. volume_id: cursor.read_u32()?,
  211. ..Default::default()
  212. };
  213. cursor.read_exact(&mut bpb32.reserved0)?;
  214. cursor.read_exact(&mut bpb32.volume_label)?;
  215. cursor.read_exact(&mut bpb32.filesystem_type)?;
  216. // 跳过启动代码
  217. cursor.seek(SeekFrom::SeekCurrent(420))?;
  218. // 读取尾部的启动扇区标志
  219. bpb.trail_sig = cursor.read_u16()?;
  220. // 计算根目录项占用的空间(单位:字节)
  221. let root_sectors = (bpb.root_entries_cnt as u32 * 32).div_ceil(bpb.bytes_per_sector as u32);
  222. // 每FAT扇区数
  223. let fat_size = if bpb.fat_size_16 != 0 {
  224. bpb.fat_size_16 as u32
  225. } else {
  226. bpb32.fat_size_32
  227. };
  228. // 当前分区总扇区数
  229. let total_sectors = if bpb.total_sectors_16 != 0 {
  230. bpb.total_sectors_16 as u32
  231. } else {
  232. bpb.total_sectors_32
  233. };
  234. // 数据区扇区数
  235. let data_sectors = total_sectors
  236. - ((bpb.rsvd_sec_cnt as u32) + (bpb.num_fats as u32) * fat_size + root_sectors);
  237. // 总的数据簇数量(向下对齐)
  238. let count_clusters = data_sectors / (bpb.sector_per_cluster as u32);
  239. // 设置FAT类型
  240. bpb.fat_type = if count_clusters < FATFileSystem::FAT12_MAX_CLUSTER {
  241. FATType::FAT12(BiosParameterBlockLegacy::default())
  242. } else if count_clusters <= FATFileSystem::FAT16_MAX_CLUSTER {
  243. FATType::FAT16(BiosParameterBlockLegacy::default())
  244. } else if count_clusters < FATFileSystem::FAT32_MAX_CLUSTER {
  245. FATType::FAT32(bpb32)
  246. } else {
  247. // 都不符合条件,报错
  248. return Err(SystemError::EINVAL);
  249. };
  250. // 验证BPB的信息是否合法
  251. bpb.validate()?;
  252. return Ok(bpb);
  253. }
  254. /// @brief 验证BPB的信息是否合法
  255. pub fn validate(&self) -> Result<(), SystemError> {
  256. // 校验每扇区字节数是否合法
  257. if self.bytes_per_sector.count_ones() != 1 {
  258. error!("Invalid bytes per sector(not a power of 2)");
  259. return Err(SystemError::EINVAL);
  260. } else if self.bytes_per_sector < 512 {
  261. error!("Invalid bytes per sector (value < 512)");
  262. return Err(SystemError::EINVAL);
  263. } else if self.bytes_per_sector > 4096 {
  264. error!("Invalid bytes per sector (value > 4096)");
  265. return Err(SystemError::EINVAL);
  266. }
  267. if self.rsvd_sec_cnt < 1 {
  268. error!("Invalid rsvd_sec_cnt value in BPB");
  269. return Err(SystemError::EINVAL);
  270. }
  271. if self.num_fats == 0 {
  272. error!("Invalid fats value in BPB");
  273. return Err(SystemError::EINVAL);
  274. }
  275. if (self.total_sectors_16 == 0) && (self.total_sectors_32 == 0) {
  276. error!("Invalid BPB (total_sectors_16 or total_sectors_32 should be non-zero)");
  277. return Err(SystemError::EINVAL);
  278. }
  279. let fat_size = match self.fat_type {
  280. FATType::FAT32(bpb32) => {
  281. bpb32.validate(self)?;
  282. bpb32.fat_size_32
  283. }
  284. FATType::FAT16(bpb_legacy) | FATType::FAT12(bpb_legacy) => {
  285. bpb_legacy.validate(self)?;
  286. self.fat_size_16 as u32
  287. }
  288. };
  289. let root_sectors =
  290. (self.root_entries_cnt as u32 * 32).div_ceil(self.bytes_per_sector as u32);
  291. // 当前分区总扇区数
  292. let total_sectors = if self.total_sectors_16 != 0 {
  293. self.total_sectors_16 as u32
  294. } else {
  295. self.total_sectors_32
  296. };
  297. let first_data_sector =
  298. (self.rsvd_sec_cnt as u32) + (self.num_fats as u32) * fat_size + root_sectors;
  299. // 总扇区数应当大于第一个数据扇区的扇区号
  300. if total_sectors <= first_data_sector {
  301. error!("Total sectors lesser than first data sector");
  302. return Err(SystemError::EINVAL);
  303. }
  304. return Ok(());
  305. }
  306. pub fn get_volume_id(&self) -> u32 {
  307. match self.fat_type {
  308. FATType::FAT12(f) | FATType::FAT16(f) => {
  309. return f.volume_id;
  310. }
  311. FATType::FAT32(f) => {
  312. return f.volume_id;
  313. }
  314. }
  315. }
  316. }