1 /** 2 * @file fat32.h 3 * @author fslongjin (longjin@RinGoTek.cn) 4 * @brief fat32文件系统 5 * @version 0.1 6 * @date 2022-04-19 7 * 8 * @copyright Copyright (c) 2022 9 * 10 */ 11 12 #pragma once 13 14 #include <filesystem/MBR.h> 15 #include <filesystem/vfs/VFS.h> 16 17 #define FAT32_MAX_PARTITION_NUM 128 // 系统支持的最大的fat32分区数量 18 19 #define FAT32_DELETED_FLAG 0xe5 // 如果短目录项的name[0]为这个值,那么意味着这个短目录项是空闲的 20 21 /** 22 * @brief fat32文件系统引导扇区结构体 23 * 24 */ 25 struct fat32_BootSector_t 26 { 27 uint8_t BS_jmpBoot[3]; // 跳转指令 28 uint8_t BS_OEMName[8]; // 生产厂商名 29 uint16_t BPB_BytesPerSec; // 每扇区字节数 30 uint8_t BPB_SecPerClus; // 每簇扇区数 31 uint16_t BPB_RsvdSecCnt; // 保留扇区数 32 uint8_t BPB_NumFATs; // FAT表数量 33 uint16_t BPB_RootEntCnt; // 根目录文件数最大值 34 uint16_t BPB_TotSec16; // 16位扇区总数 35 uint8_t BPB_Media; // 介质描述符 36 uint16_t BPB_FATSz16; // FAT12/16每FAT扇区数 37 uint16_t BPB_SecPerTrk; // 每磁道扇区数 38 uint16_t BPB_NumHeads; // 磁头数 39 uint32_t BPB_HiddSec; // 隐藏扇区数 40 uint32_t BPB_TotSec32; // 32位扇区总数 41 42 uint32_t BPB_FATSz32; // FAT32每FAT扇区数 43 uint16_t BPB_ExtFlags; // 扩展标志 44 uint16_t BPB_FSVer; // 文件系统版本号 45 uint32_t BPB_RootClus; // 根目录起始簇号 46 uint16_t BPB_FSInfo; // FS info结构体的扇区号 47 uint16_t BPB_BkBootSec; // 引导扇区的备份扇区号 48 uint8_t BPB_Reserved0[12]; 49 50 uint8_t BS_DrvNum; // int0x13的驱动器号 51 uint8_t BS_Reserved1; 52 uint8_t BS_BootSig; // 扩展引导标记 53 uint32_t BS_VolID; // 卷序列号 54 uint8_t BS_VolLab[11]; // 卷标 55 uint8_t BS_FilSysType[8]; // 文件系统类型 56 57 uint8_t BootCode[420]; // 引导代码、数据 58 59 uint16_t BS_TrailSig; // 结束标志0xAA55 60 } __attribute__((packed)); 61 62 /** 63 * @brief fat32文件系统的FSInfo扇区结构体 64 * 65 */ 66 struct fat32_FSInfo_t 67 { 68 uint32_t FSI_LeadSig; // FS info扇区标志符 数值为0x41615252 69 uint8_t FSI_Reserved1[480]; // 保留使用,全部置为0 70 uint32_t FSI_StrucSig; // 另一个标志符,数值为0x61417272 71 uint32_t FSI_Free_Count; // 上一次记录的空闲簇数量,这是一个参考值 72 uint32_t FSI_Nxt_Free; // 空闲簇的起始搜索位置,这是为驱动程序提供的参考值 73 uint8_t FSI_Reserved2[12]; // 保留使用,全部置为0 74 uint32_t FSI_TrailSig; // 结束标志,数值为0xaa550000 75 } __attribute__((packed)); 76 77 #define ATTR_READ_ONLY (1 << 0) 78 #define ATTR_HIDDEN (1 << 1) 79 #define ATTR_SYSTEM (1 << 2) 80 #define ATTR_VOLUME_ID (1 << 3) 81 #define ATTR_DIRECTORY (1 << 4) 82 #define ATTR_ARCHIVE (1 << 5) 83 #define ATTR_LONG_NAME (ATTR_READ_ONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_VOLUME_ID) 84 85 /** 86 * @brief fat32文件系统短目录项,大小为32bytes 87 * 88 */ 89 struct fat32_Directory_t 90 { 91 unsigned char DIR_Name[11]; 92 unsigned char DIR_Attr; // 目录项属性 93 unsigned char DIR_NTRes; // EXT|BASE => 8(BASE).3(EXT) 94 // BASE:LowerCase(8),UpperCase(0) 95 // EXT:LowerCase(16),UpperCase(0) 96 unsigned char DIR_CrtTimeTenth; // 文件创建的毫秒级时间戳 97 unsigned short DIR_CrtTime; // 文件创建时间 98 unsigned short DIR_CrtDate; // 文件创建日期 99 unsigned short DIR_LastAccDate; // 文件的最后访问日期 100 unsigned short DIR_FstClusHI; // 起始簇号(高16bit) 101 unsigned short DIR_WrtTime; // 最后写入时间 102 unsigned short DIR_WrtDate; // 最后写入日期 103 unsigned short DIR_FstClusLO; // 起始簇号(低16bit) 104 unsigned int DIR_FileSize; // 文件大小 105 } __attribute__((packed)); 106 107 #define LOWERCASE_BASE (8) 108 #define LOWERCASE_EXT (16) 109 110 /** 111 * @brief fat32文件系统长目录项,大小为32bytes 112 * 113 */ 114 struct fat32_LongDirectory_t 115 { 116 unsigned char LDIR_Ord; // 长目录项的序号 117 unsigned short LDIR_Name1[5]; // 长文件名的第1-5个字符,每个字符占2bytes 118 unsigned char LDIR_Attr; // 目录项属性必须为ATTR_LONG_NAME 119 unsigned char LDIR_Type; // 如果为0,则说明这是长目录项的子项 120 unsigned char LDIR_Chksum; // 短文件名的校验和 121 unsigned short LDIR_Name2[6]; // 长文件名的第6-11个字符,每个字符占2bytes 122 unsigned short LDIR_FstClusLO; // 必须为0 123 unsigned short LDIR_Name3[2]; // 长文件名的12-13个字符,每个字符占2bytes 124 } __attribute__((packed)); 125 126 /** 127 * @brief fat32文件系统的超级块信息结构体 128 * 129 */ 130 struct fat32_partition_info_t 131 { 132 uint16_t partition_id; // 全局fat32分区id 133 // todo: 增加mutex,使得对fat32文件系统的访问是互斥的 134 135 struct fat32_BootSector_t bootsector; 136 struct fat32_FSInfo_t fsinfo; 137 uint64_t fsinfo_sector_addr_infat; 138 uint64_t bootsector_bak_sector_addr_infat; 139 140 uint64_t starting_sector; 141 uint64_t sector_count; 142 143 uint64_t sec_per_clus; // 每簇扇区数 144 uint64_t bytes_per_sec; // 每扇区字节数 145 uint64_t bytes_per_clus; // 每簇字节数 146 147 uint64_t first_data_sector; // 数据区起始扇区号 148 uint64_t FAT1_base_sector; // FAT1表的起始簇号 149 uint64_t FAT2_base_sector; // FAT2表的起始簇号 150 uint64_t sec_per_FAT; // 每FAT表扇区数 151 uint64_t NumFATs; // FAT表数 152 }; 153 154 typedef struct fat32_partition_info_t fat32_sb_info_t; 155 156 struct fat32_inode_info_t 157 { 158 uint32_t first_clus; // 文件的起始簇号 159 uint64_t dEntry_location_clus; // fat entry的起始簇号 dEntry struct in cluster (0 is root, 1 is invalid) 160 uint64_t dEntry_location_clus_offset; // fat entry在起始簇中的偏移量(是第几个entry) dEntry struct offset in cluster 161 162 uint16_t create_date; 163 uint16_t create_time; 164 uint16_t write_time; 165 uint16_t write_date; 166 }; 167 168 typedef struct fat32_inode_info_t fat32_inode_info_t; 169 170 /** 171 * @brief FAT32目录项插槽信息 172 * 一个插槽指的是 一个长目录项/短目录项 173 */ 174 struct fat32_slot_info 175 { 176 off_t i_pos; // on-disk position of directory entry(扇区号) 177 off_t slot_off; // offset for slot or (de) start 178 int num_slots; // number of slots +1(de) in filename 179 struct fat32_Directory_t * de; 180 181 // todo: 加入block io层后,在这里引入buffer_head 182 void *buffer; // 记得释放这个buffer!!! 183 }; 184 185 /** 186 * @brief 注册指定磁盘上的指定分区的fat32文件系统 187 * 188 * @param blk_dev 块设备结构体 189 * @param part_num 磁盘分区编号 190 * 191 * @return struct vfs_super_block_t * 文件系统的超级块 192 */ 193 struct vfs_superblock_t *fat32_register_partition(struct block_device *blk_dev, uint8_t part_num); 194 195 /** 196 * @brief 创建fat32文件系统的超级块 197 * 198 * @param blk 块设备结构体 199 * @return struct vfs_superblock_t* 创建好的超级块 200 */ 201 struct vfs_superblock_t *fat32_read_superblock(struct block_device *blk); 202 203 /** 204 * @brief 创建新的文件 205 * @param parent_inode 父目录的inode结构体 206 * @param dest_dEntry 新文件的dentry 207 * @param mode 创建模式 208 */ 209 long fat32_create(struct vfs_index_node_t *parent_inode, struct vfs_dir_entry_t *dest_dEntry, int mode); 210 211 void fat32_init(); 212 213 /** 214 * @brief 读取文件夹(在指定目录中找出有效目录项) 215 * 216 * @param file_ptr 文件结构体指针 217 * @param dirent 返回的dirent 218 * @param filler 填充dirent的函数 219 * @return int64_t 220 */ 221 int64_t fat32_readdir(struct vfs_file_t *file_ptr, void *dirent, vfs_filldir_t filler);