fat32.rs 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. use core::{ops::ControlFlow, sync::atomic::Ordering};
  2. use alloc::{
  3. collections::btree_map::BTreeMap,
  4. sync::{Arc, Weak},
  5. vec::Vec,
  6. };
  7. use bindings::EIO;
  8. use dir::Dirs as _;
  9. use file::ClusterRead;
  10. use crate::{
  11. io::{Buffer, ByteBuffer, UninitBuffer},
  12. kernel::{
  13. block::{make_device, BlockDevice, BlockDeviceRequest},
  14. constants::{S_IFDIR, S_IFREG},
  15. mem::paging::Page,
  16. vfs::{
  17. dentry::Dentry,
  18. inode::{define_struct_inode, Ino, Inode, InodeData},
  19. mount::{register_filesystem, Mount, MountCreator},
  20. vfs::Vfs,
  21. DevId,
  22. },
  23. },
  24. prelude::*,
  25. KResult,
  26. };
  27. mod dir;
  28. mod file;
  29. type ClusterNo = u32;
  30. #[derive(Clone, Copy)]
  31. #[repr(C, packed)]
  32. struct Bootsector {
  33. jmp: [u8; 3],
  34. oem: [u8; 8],
  35. bytes_per_sector: u16,
  36. sectors_per_cluster: u8,
  37. reserved_sectors: u16,
  38. fat_copies: u8,
  39. root_entries: u16, // should be 0 for FAT32
  40. _total_sectors: u16, // outdated
  41. media: u8,
  42. _sectors_per_fat: u16, // outdated
  43. sectors_per_track: u16,
  44. heads: u16,
  45. hidden_sectors: u32,
  46. total_sectors: u32,
  47. sectors_per_fat: u32,
  48. flags: u16,
  49. fat_version: u16,
  50. root_cluster: ClusterNo,
  51. fsinfo_sector: u16,
  52. backup_bootsector: u16,
  53. _reserved: [u8; 12],
  54. drive_number: u8,
  55. _reserved2: u8,
  56. ext_sig: u8,
  57. serial: u32,
  58. volume_label: [u8; 11],
  59. fs_type: [u8; 8],
  60. bootcode: [u8; 420],
  61. mbr_signature: u16,
  62. }
  63. impl_any!(FatFs);
  64. /// # Lock order
  65. /// 2. FatTable
  66. /// 3. Inodes
  67. ///
  68. struct FatFs {
  69. sectors_per_cluster: u8,
  70. rootdir_cluster: ClusterNo,
  71. data_start: u64,
  72. volume_label: [u8; 11],
  73. device: Arc<BlockDevice>,
  74. fat: RwSemaphore<Vec<ClusterNo>>,
  75. weak: Weak<FatFs>,
  76. icache: BTreeMap<Ino, FatInode>,
  77. }
  78. impl Vfs for FatFs {
  79. fn io_blksize(&self) -> usize {
  80. 4096
  81. }
  82. fn fs_devid(&self) -> DevId {
  83. self.device.devid()
  84. }
  85. fn is_read_only(&self) -> bool {
  86. true
  87. }
  88. }
  89. impl FatFs {
  90. fn read_cluster(&self, cluster: ClusterNo, buf: &Page) -> KResult<()> {
  91. let cluster = cluster - 2;
  92. let rq = BlockDeviceRequest {
  93. sector: self.data_start as u64 + cluster as u64 * self.sectors_per_cluster as u64,
  94. count: self.sectors_per_cluster as u64,
  95. buffer: core::slice::from_ref(buf),
  96. };
  97. self.device.read_raw(rq)?;
  98. Ok(())
  99. }
  100. fn get_or_alloc_inode(&self, ino: Ino, is_directory: bool, size: u32) -> Arc<dyn Inode> {
  101. self.icache
  102. .get(&ino)
  103. .cloned()
  104. .map(FatInode::unwrap)
  105. .unwrap_or_else(|| {
  106. if is_directory {
  107. DirInode::new(ino, self.weak.clone(), size)
  108. } else {
  109. FileInode::new(ino, self.weak.clone(), size)
  110. }
  111. })
  112. }
  113. }
  114. impl FatFs {
  115. pub fn create(device: DevId) -> KResult<(Arc<Self>, Arc<dyn Inode>)> {
  116. let device = BlockDevice::get(device)?;
  117. let mut fatfs_arc = Arc::new_cyclic(|weak: &Weak<FatFs>| Self {
  118. device,
  119. sectors_per_cluster: 0,
  120. rootdir_cluster: 0,
  121. data_start: 0,
  122. fat: RwSemaphore::new(Vec::new()),
  123. weak: weak.clone(),
  124. icache: BTreeMap::new(),
  125. volume_label: [0; 11],
  126. });
  127. let fatfs = unsafe { Arc::get_mut_unchecked(&mut fatfs_arc) };
  128. let mut info: UninitBuffer<Bootsector> = UninitBuffer::new();
  129. fatfs.device.read_some(0, &mut info)?.ok_or(EIO)?;
  130. let info = info.assume_filled_ref()?;
  131. fatfs.sectors_per_cluster = info.sectors_per_cluster;
  132. fatfs.rootdir_cluster = info.root_cluster;
  133. fatfs.data_start =
  134. info.reserved_sectors as u64 + info.fat_copies as u64 * info.sectors_per_fat as u64;
  135. let fat = fatfs.fat.get_mut();
  136. fat.resize(
  137. 512 * info.sectors_per_fat as usize / core::mem::size_of::<ClusterNo>(),
  138. 0,
  139. );
  140. let mut buffer = ByteBuffer::from(fat.as_mut_slice());
  141. fatfs
  142. .device
  143. .read_some(info.reserved_sectors as usize * 512, &mut buffer)?
  144. .ok_or(EIO)?;
  145. info.volume_label
  146. .iter()
  147. .take_while(|&&c| c != ' ' as u8)
  148. .take(11)
  149. .enumerate()
  150. .for_each(|(idx, c)| fatfs.volume_label[idx] = *c);
  151. let root_dir_cluster_count = ClusterIterator::new(fat, fatfs.rootdir_cluster).count();
  152. let root_dir_size = root_dir_cluster_count as u32 * info.sectors_per_cluster as u32 * 512;
  153. let root_inode = DirInode::new(info.root_cluster as Ino, fatfs.weak.clone(), root_dir_size);
  154. Ok((fatfs_arc, root_inode))
  155. }
  156. }
  157. struct ClusterIterator<'fat> {
  158. fat: &'fat [ClusterNo],
  159. cur: ClusterNo,
  160. }
  161. impl<'fat> ClusterIterator<'fat> {
  162. fn new(fat: &'fat [ClusterNo], start: ClusterNo) -> Self {
  163. Self { fat, cur: start }
  164. }
  165. }
  166. impl<'fat> Iterator for ClusterIterator<'fat> {
  167. type Item = ClusterNo;
  168. fn next(&mut self) -> Option<Self::Item> {
  169. const EOC: ClusterNo = 0x0FFFFFF8;
  170. let next = self.cur;
  171. if next >= EOC {
  172. None
  173. } else {
  174. self.cur = self.fat[next as usize];
  175. Some(next)
  176. }
  177. }
  178. }
  179. #[allow(dead_code)]
  180. #[derive(Clone)]
  181. enum FatInode {
  182. File(Arc<FileInode>),
  183. Dir(Arc<DirInode>),
  184. }
  185. impl FatInode {
  186. fn unwrap(self) -> Arc<dyn Inode> {
  187. match self {
  188. FatInode::File(inode) => inode,
  189. FatInode::Dir(inode) => inode,
  190. }
  191. }
  192. }
  193. define_struct_inode! {
  194. struct FileInode;
  195. }
  196. impl FileInode {
  197. fn new(ino: Ino, weak: Weak<FatFs>, size: u32) -> Arc<Self> {
  198. let inode = Arc::new(Self {
  199. idata: InodeData::new(ino, weak),
  200. });
  201. // Safety: We are initializing the inode
  202. inode.nlink.store(1, Ordering::Relaxed);
  203. inode.mode.store(S_IFREG | 0o777, Ordering::Relaxed);
  204. inode.size.store(size as u64, Ordering::Relaxed);
  205. inode
  206. }
  207. }
  208. impl Inode for FileInode {
  209. fn read(&self, buffer: &mut dyn Buffer, offset: usize) -> KResult<usize> {
  210. let vfs = self.vfs.upgrade().ok_or(EIO)?;
  211. let vfs = vfs.as_any().downcast_ref::<FatFs>().unwrap();
  212. let fat = vfs.fat.lock_shared();
  213. if self.size.load(Ordering::Relaxed) as usize == 0 {
  214. return Ok(0);
  215. }
  216. let iter = ClusterIterator::new(fat.as_ref(), self.ino as ClusterNo).read(vfs, offset);
  217. for data in iter {
  218. if buffer.fill(data?)?.should_stop() {
  219. break;
  220. }
  221. }
  222. Ok(buffer.wrote())
  223. }
  224. }
  225. define_struct_inode! {
  226. struct DirInode;
  227. }
  228. impl DirInode {
  229. fn new(ino: Ino, weak: Weak<FatFs>, size: u32) -> Arc<Self> {
  230. let inode = Arc::new(Self {
  231. idata: InodeData::new(ino, weak),
  232. });
  233. // Safety: We are initializing the inode
  234. inode.nlink.store(2, Ordering::Relaxed);
  235. inode.mode.store(S_IFDIR | 0o777, Ordering::Relaxed);
  236. inode.size.store(size as u64, Ordering::Relaxed);
  237. inode
  238. }
  239. }
  240. impl Inode for DirInode {
  241. fn lookup(&self, dentry: &Arc<Dentry>) -> KResult<Option<Arc<dyn Inode>>> {
  242. let vfs = self.vfs.upgrade().ok_or(EIO)?;
  243. let vfs = vfs.as_any().downcast_ref::<FatFs>().unwrap();
  244. let fat = vfs.fat.lock_shared();
  245. let mut entries = ClusterIterator::new(fat.as_ref(), self.ino as ClusterNo)
  246. .read(vfs, 0)
  247. .dirs();
  248. let entry = entries.find(|entry| {
  249. entry
  250. .as_ref()
  251. .map(|entry| &entry.filename == dentry.name())
  252. .unwrap_or(true)
  253. });
  254. match entry {
  255. None => Ok(None),
  256. Some(Err(err)) => Err(err),
  257. Some(Ok(entry)) => Ok(Some(vfs.get_or_alloc_inode(
  258. entry.cluster as Ino,
  259. entry.is_directory,
  260. entry.size,
  261. ))),
  262. }
  263. }
  264. fn do_readdir(
  265. &self,
  266. offset: usize,
  267. callback: &mut dyn FnMut(&[u8], Ino) -> KResult<ControlFlow<(), ()>>,
  268. ) -> KResult<usize> {
  269. let vfs = self.vfs.upgrade().ok_or(EIO)?;
  270. let vfs = vfs.as_any().downcast_ref::<FatFs>().unwrap();
  271. let fat = vfs.fat.lock_shared();
  272. let cluster_iter = ClusterIterator::new(fat.as_ref(), self.ino as ClusterNo)
  273. .read(vfs, offset)
  274. .dirs();
  275. let mut nread = 0usize;
  276. for entry in cluster_iter {
  277. let entry = entry?;
  278. vfs.get_or_alloc_inode(entry.cluster as Ino, entry.is_directory, entry.size);
  279. if callback(&entry.filename, entry.cluster as Ino)?.is_break() {
  280. break;
  281. }
  282. nread += entry.entry_offset as usize;
  283. }
  284. Ok(nread)
  285. }
  286. }
  287. struct FatMountCreator;
  288. impl MountCreator for FatMountCreator {
  289. fn create_mount(&self, _source: &str, _flags: u64, mp: &Arc<Dentry>) -> KResult<Mount> {
  290. let (fatfs, root_inode) = FatFs::create(make_device(8, 1))?;
  291. Mount::new(mp, fatfs, root_inode)
  292. }
  293. }
  294. pub fn init() {
  295. register_filesystem("fat32", Arc::new(FatMountCreator)).unwrap();
  296. }