1 #include "fat32.h"
2 #include "fat_ent.h"
3 #include "internal.h"
4 #include <common/errno.h>
5 #include <common/kprint.h>
6 #include <common/spinlock.h>
7 #include <common/stdio.h>
8 #include <common/string.h>
9 #include <driver/disk/ahci/ahci.h>
10 #include <filesystem/MBR.h>
11 #include <mm/slab.h>
12 
13 struct vfs_super_block_operations_t fat32_sb_ops;
14 struct vfs_dir_entry_operations_t fat32_dEntry_ops;
15 struct vfs_file_operations_t fat32_file_ops;
16 struct vfs_inode_operations_t fat32_inode_ops;
17 extern struct blk_gendisk ahci_gendisk0;
18 
19 static unsigned int vfat_striptail_len(unsigned int len, const char *name);
20 static int vfat_find(struct vfs_index_node_t *dir, const char *name, struct fat32_slot_info *slot_info);
21 static int __fat32_search_long_short(struct vfs_index_node_t *parent_inode, const char *name, int name_len,
22                                      struct fat32_slot_info *sinfo);
23 static int fat32_detach_inode(struct vfs_index_node_t *inode);
24 
25 /**
26  * @brief 注册指定磁盘上的指定分区的fat32文件系统
27  *
28  * @param blk_dev 块设备结构体
29  * @param part_num 磁盘分区编号
30  *
31  * @return struct vfs_super_block_t * 文件系统的超级块
32  */
fat32_register_partition(struct block_device * blk_dev,uint8_t part_num)33 struct vfs_superblock_t *fat32_register_partition(struct block_device *blk_dev, uint8_t part_num)
34 {
35     // 挂载文件系统到vfs
36     return vfs_mount_fs("/", "FAT32", blk_dev);
37 }
38 
39 /**
40  * @brief 计算短目录项文件名的校验和
41  *
42  * @param name 短目录项文件名字符串(长度为11)
43  * @return uint8_t 校验和
44  */
fat32_ChkSum(uint8_t * name)45 static uint8_t fat32_ChkSum(uint8_t *name)
46 {
47     uint8_t chksum = 0;
48     for (uint8_t i = 0; i < 11; ++i)
49     {
50         chksum = ((chksum & 1) ? 0x80 : 0) + (chksum >> 1) + *name;
51         ++name;
52     }
53     return chksum;
54 }
55 
__fat32_search_long_short(struct vfs_index_node_t * parent_inode,const char * name,int name_len,struct fat32_slot_info * sinfo)56 static int __fat32_search_long_short(struct vfs_index_node_t *parent_inode, const char *name, int name_len,
57                                      struct fat32_slot_info *sinfo)
58 {
59     struct fat32_inode_info_t *finode = (struct fat32_inode_info_t *)parent_inode->private_inode_info;
60     fat32_sb_info_t *fsbi = (fat32_sb_info_t *)parent_inode->sb->private_sb_info;
61     struct block_device *blk = parent_inode->sb->blk_device;
62 
63     uint8_t *buf = kzalloc(fsbi->bytes_per_clus, 0);
64 
65     // 计算父目录项的起始簇号
66     uint32_t cluster = finode->first_clus;
67 
68     struct fat32_Directory_t *tmp_dEntry = NULL;
69     int cnt_long_dir = 0; // 最终结果中,长目录项的数量
70 
71     while (true)
72     {
73 
74         // 计算父目录项的起始LBA扇区号
75         uint64_t sector = __fat32_calculate_LBA(fsbi->first_data_sector, fsbi->sec_per_clus, cluster);
76         // kdebug("fat32_part_info[part_id].bootsector.BPB_SecPerClus=%d",fat32_part_info[part_id].bootsector.BPB_SecPerClus);
77         // kdebug("sector=%d",sector);
78 
79         // 读取父目录项的起始簇数据
80         blk->bd_disk->fops->transfer(blk->bd_disk, AHCI_CMD_READ_DMA_EXT, sector, fsbi->sec_per_clus, (uint64_t)buf);
81 
82         tmp_dEntry = (struct fat32_Directory_t *)buf;
83 
84         // 查找每个文件的短目录项
85         for (int i = 0; i < fsbi->bytes_per_clus; i += 32, ++tmp_dEntry)
86         {
87             // 跳过长目录项
88             if (tmp_dEntry->DIR_Attr == ATTR_LONG_NAME)
89                 continue;
90 
91             // 跳过无效目录项、空闲目录项
92             if (tmp_dEntry->DIR_Name[0] == 0xe5 || tmp_dEntry->DIR_Name[0] == 0x00 || tmp_dEntry->DIR_Name[0] == 0x05)
93                 continue;
94             // kdebug("short name [%d] %s\n 33333==[%#02x]", i / 32, tmp_dEntry->DIR_Name, tmp_dEntry->DIR_Name[3]);
95             // 找到长目录项,位于短目录项之前
96             struct fat32_LongDirectory_t *tmp_ldEntry = (struct fat32_LongDirectory_t *)tmp_dEntry - 1;
97             cnt_long_dir = 0;
98             int js = 0;
99             // 遍历每个长目录项
100             while (tmp_ldEntry->LDIR_Attr == ATTR_LONG_NAME && tmp_ldEntry->LDIR_Ord != 0xe5)
101             {
102                 // 比较name1
103                 for (int x = 0; x < 5; ++x)
104                 {
105                     if (js >= name_len && (tmp_ldEntry->LDIR_Name1[x] == 0xffff))
106                         continue;
107                     else if (js > name_len ||
108                              tmp_ldEntry->LDIR_Name1[x] != (uint16_t)(name[js++])) // 文件名不匹配,检索下一个短目录项
109                         goto continue_cmp_fail;
110                 }
111 
112                 // 比较name2
113                 for (int x = 0; x < 6; ++x)
114                 {
115                     if (js >= name_len && (tmp_ldEntry->LDIR_Name2[x] == 0xffff))
116                         continue;
117                     else if (js > name_len ||
118                              tmp_ldEntry->LDIR_Name2[x] != (uint16_t)(name[js++])) // 文件名不匹配,检索下一个短目录项
119                         goto continue_cmp_fail;
120                 }
121 
122                 // 比较name3
123                 for (int x = 0; x < 2; ++x)
124                 {
125                     if (js >= name_len && (tmp_ldEntry->LDIR_Name3[x] == 0xffff))
126                         continue;
127                     else if (js > name_len ||
128                              tmp_ldEntry->LDIR_Name3[x] != (uint16_t)(name[js++])) // 文件名不匹配,检索下一个短目录项
129                         goto continue_cmp_fail;
130                 }
131 
132                 if (js >= name_len) // 找到需要的目录项,返回
133                 {
134                     // kdebug("found target long name.");
135                     cnt_long_dir = tmp_dEntry - (struct fat32_Directory_t *)tmp_ldEntry;
136                     goto success;
137                 }
138 
139                 --tmp_ldEntry; // 检索下一个长目录项
140             }
141 
142             // 不存在长目录项,匹配短目录项的基础名
143             js = 0;
144             for (int x = 0; x < 8; ++x)
145             {
146                 // kdebug("no long name, comparing short name");
147                 // kdebug("value = %#02x", tmp_dEntry->DIR_Name[x]);
148                 switch (tmp_dEntry->DIR_Name[x])
149                 {
150                 case ' ':
151                     if (!(tmp_dEntry->DIR_Attr & ATTR_DIRECTORY)) // 不是文件夹(是文件)
152                     {
153                         if (name[js] == '.')
154                             continue;
155                         else if (tmp_dEntry->DIR_Name[x] == name[js])
156                         {
157                             ++js;
158                             break;
159                         }
160                         else
161                             goto continue_cmp_fail;
162                     }
163                     else // 是文件夹
164                     {
165                         if (js < name_len && tmp_dEntry->DIR_Name[x] == name[js]) // 当前位正确匹配
166                         {
167                             ++js;
168                             break; // 进行下一位的匹配
169                         }
170                         else if (js == name_len)
171                             continue;
172                         else
173                             goto continue_cmp_fail;
174                     }
175                     break;
176 
177                 // 当前位是字母
178                 case 'A' ... 'Z':
179                 case 'a' ... 'z':
180                     if (tmp_dEntry->DIR_NTRes & LOWERCASE_BASE) // 为兼容windows系统,检测DIR_NTRes字段
181                     {
182                         if (js < name_len && (tmp_dEntry->DIR_Name[x] + 32 == name[js]))
183                         {
184                             ++js;
185                             break;
186                         }
187                         else
188                             goto continue_cmp_fail;
189                     }
190                     else
191                     {
192                         if (js < name_len && tmp_dEntry->DIR_Name[x] == name[js])
193                         {
194                             ++js;
195                             break;
196                         }
197                         else
198                             goto continue_cmp_fail;
199                     }
200                     break;
201                 case '0' ... '9':
202                     if (js < name_len && tmp_dEntry->DIR_Name[x] == name[js])
203                     {
204                         ++js;
205                         break;
206                     }
207                     else
208                         goto continue_cmp_fail;
209 
210                     break;
211                 default:
212                     // ++js;
213                     goto continue_cmp_fail;
214                     break;
215                 }
216             }
217             if (js > name_len)
218             {
219                 // kdebug("js > namelen");
220                 goto continue_cmp_fail;
221             }
222             // 若短目录项为文件,则匹配扩展名
223             if (!(tmp_dEntry->DIR_Attr & ATTR_DIRECTORY))
224             {
225                 ++js;
226                 for (int x = 8; x < 11; ++x)
227                 {
228                     switch (tmp_dEntry->DIR_Name[x])
229                     {
230                         // 当前位是字母
231                     case 'A' ... 'Z':
232                     case 'a' ... 'z':
233                         if (tmp_dEntry->DIR_NTRes & LOWERCASE_EXT) // 为兼容windows系统,检测DIR_NTRes字段
234                         {
235                             if ((tmp_dEntry->DIR_Name[x] + 32 == name[js]))
236                             {
237                                 ++js;
238                                 break;
239                             }
240                             else
241                                 goto continue_cmp_fail;
242                         }
243                         else
244                         {
245                             if (tmp_dEntry->DIR_Name[x] == name[js])
246                             {
247                                 ++js;
248                                 break;
249                             }
250                             else
251                                 goto continue_cmp_fail;
252                         }
253                         break;
254                     case '0' ... '9':
255                     case ' ':
256                         if (tmp_dEntry->DIR_Name[x] == name[js])
257                         {
258                             ++js;
259                             break;
260                         }
261                         else
262                             goto continue_cmp_fail;
263 
264                         break;
265 
266                     default:
267                         goto continue_cmp_fail;
268                         break;
269                     }
270                 }
271             }
272             if (js > name_len)
273             {
274                 // kdebug("js > namelen");
275                 goto continue_cmp_fail;
276             }
277             cnt_long_dir = 0;
278             goto success;
279         continue_cmp_fail:;
280         }
281 
282         // 当前簇没有发现目标文件名,寻找下一个簇
283         cluster = fat32_read_FAT_entry(blk, fsbi, cluster);
284 
285         if (cluster >= 0x0ffffff7) // 寻找完父目录的所有簇,都没有找到目标文件名
286         {
287             kfree(buf);
288             return -ENOENT;
289         }
290     }
291     if (unlikely(tmp_dEntry == NULL))
292     {
293         BUG_ON(1);
294         kfree(buf);
295         return -ENOENT;
296     }
297 success:;
298 
299     // 填充sinfo
300     sinfo->buffer = buf;
301     sinfo->de = tmp_dEntry;
302     sinfo->i_pos = __fat32_calculate_LBA(fsbi->first_data_sector, fsbi->sec_per_clus, cluster);
303     sinfo->num_slots = cnt_long_dir + 1;
304     sinfo->slot_off = tmp_dEntry - (struct fat32_Directory_t *)buf;
305     // kdebug("successfully found:%s", name);
306     return 0;
307 }
308 
309 /**
310  * @brief 在父目录中寻找指定的目录项
311  *
312  * @param parent_inode 父目录项的inode
313  * @param dest_dentry 搜索目标目录项
314  * @return struct vfs_dir_entry_t* 目标目录项
315  */
fat32_lookup(struct vfs_index_node_t * parent_inode,struct vfs_dir_entry_t * dest_dentry)316 struct vfs_dir_entry_t *fat32_lookup(struct vfs_index_node_t *parent_inode, struct vfs_dir_entry_t *dest_dentry)
317 {
318     int errcode = 0;
319     fat32_sb_info_t *fsbi = (fat32_sb_info_t *)parent_inode->sb->private_sb_info;
320     struct fat32_inode_info_t *finode = NULL;
321 
322     struct fat32_slot_info sinfo = {0};
323     errcode = vfat_find(parent_inode, dest_dentry->name, &sinfo);
324 
325     if (unlikely(errcode != 0))
326         return NULL;
327 
328 find_lookup_success:; // 找到目标dentry
329     struct vfs_index_node_t *p = vfs_alloc_inode();
330 
331     p->file_size = sinfo.de->DIR_FileSize;
332     // 计算文件占用的扇区数, 由于最小存储单位是簇,因此需要按照簇的大小来对齐扇区
333     p->blocks = (p->file_size + fsbi->bytes_per_clus - 1) / fsbi->bytes_per_sec;
334     p->attribute = (sinfo.de->DIR_Attr & ATTR_DIRECTORY) ? VFS_IF_DIR : VFS_IF_FILE;
335     p->sb = parent_inode->sb;
336     p->file_ops = &fat32_file_ops;
337     p->inode_ops = &fat32_inode_ops;
338 
339     // 为inode的与文件系统相关的信息结构体分配空间
340     p->private_inode_info = (void *)kzalloc(sizeof(fat32_inode_info_t), 0);
341     finode = (fat32_inode_info_t *)p->private_inode_info;
342 
343     finode->first_clus = ((sinfo.de->DIR_FstClusHI << 16) | sinfo.de->DIR_FstClusLO) & 0x0fffffff;
344     finode->dEntry_location_clus = __fat32_LBA_to_cluster(fsbi->first_data_sector, fsbi->sec_per_clus, sinfo.i_pos);
345     finode->dEntry_location_clus_offset = sinfo.slot_off; // 计算dentry的偏移量
346     // kdebug("finode->dEntry_location_clus=%#018lx", finode->dEntry_location_clus);
347     // kdebug("finode->dEntry_location_clus_offset=%#018lx", finode->dEntry_location_clus_offset);
348     finode->create_date = sinfo.de->DIR_CrtDate;
349     finode->create_time = sinfo.de->DIR_CrtTime;
350     finode->write_date = sinfo.de->DIR_WrtDate;
351     finode->write_time = sinfo.de->DIR_WrtTime;
352 
353     // 暂时使用fat32的高4bit来标志设备文件
354     // todo: 引入devfs后删除这段代码
355     if ((sinfo.de->DIR_FstClusHI >> 12) && (p->attribute & VFS_IF_FILE))
356         p->attribute |= VFS_IF_DEVICE;
357 
358     dest_dentry->dir_inode = p;
359     dest_dentry->dir_ops = &fat32_dEntry_ops;
360     list_init(&dest_dentry->child_node_list);
361     list_init(&dest_dentry->subdirs_list);
362 
363     kfree(sinfo.buffer);
364     return dest_dentry;
365 }
366 
367 /**
368  * @brief 创建fat32文件系统的超级块
369  *
370  * @param blk 块设备结构体
371  * @return struct vfs_superblock_t* 创建好的超级块
372  */
fat32_read_superblock(struct block_device * blk)373 struct vfs_superblock_t *fat32_read_superblock(struct block_device *blk)
374 {
375     // 读取文件系统的boot扇区
376     uint8_t buf[512] = {0};
377     blk->bd_disk->fops->transfer(blk->bd_disk, AHCI_CMD_READ_DMA_EXT, blk->bd_start_LBA, 1, (uint64_t)&buf);
378 
379     // 分配超级块的空间
380     struct vfs_superblock_t *sb_ptr = (struct vfs_superblock_t *)kzalloc(sizeof(struct vfs_superblock_t), 0);
381     blk->bd_superblock = sb_ptr;
382     sb_ptr->sb_ops = &fat32_sb_ops;
383     sb_ptr->dir_ops = &fat32_dEntry_ops;
384     sb_ptr->private_sb_info = kzalloc(sizeof(fat32_sb_info_t), 0);
385     sb_ptr->blk_device = blk;
386 
387     struct fat32_BootSector_t *fbs = (struct fat32_BootSector_t *)buf;
388 
389     fat32_sb_info_t *fsbi = (fat32_sb_info_t *)(sb_ptr->private_sb_info);
390 
391     fsbi->starting_sector = blk->bd_start_LBA;
392     fsbi->sector_count = blk->bd_sectors_num;
393     fsbi->sec_per_clus = fbs->BPB_SecPerClus;
394     fsbi->bytes_per_clus = fbs->BPB_SecPerClus * fbs->BPB_BytesPerSec;
395     fsbi->bytes_per_sec = fbs->BPB_BytesPerSec;
396     fsbi->first_data_sector = blk->bd_start_LBA + fbs->BPB_RsvdSecCnt + fbs->BPB_FATSz32 * fbs->BPB_NumFATs;
397     fsbi->FAT1_base_sector = blk->bd_start_LBA + fbs->BPB_RsvdSecCnt;
398     fsbi->FAT2_base_sector = fsbi->FAT1_base_sector + fbs->BPB_FATSz32;
399     fsbi->sec_per_FAT = fbs->BPB_FATSz32;
400     fsbi->NumFATs = fbs->BPB_NumFATs;
401     fsbi->fsinfo_sector_addr_infat = fbs->BPB_FSInfo;
402     fsbi->bootsector_bak_sector_addr_infat = fbs->BPB_BkBootSec;
403 
404     printk_color(ORANGE, BLACK,
405                  "FAT32 Boot Sector\n\tBPB_FSInfo:%#018lx\n\tBPB_BkBootSec:%#018lx\n\tBPB_TotSec32:%#018lx\n",
406                  fbs->BPB_FSInfo, fbs->BPB_BkBootSec, fbs->BPB_TotSec32);
407 
408     // fsinfo扇区的信息
409     memset(&fsbi->fsinfo, 0, sizeof(struct fat32_FSInfo_t));
410     blk->bd_disk->fops->transfer(blk->bd_disk, AHCI_CMD_READ_DMA_EXT,
411                                  blk->bd_start_LBA + fsbi->fsinfo_sector_addr_infat, 1, (uint64_t)&fsbi->fsinfo);
412 
413     printk_color(BLUE, BLACK, "FAT32 FSInfo\n\tFSI_LeadSig:%#018lx\n\tFSI_StrucSig:%#018lx\n\tFSI_Free_Count:%#018lx\n",
414                  fsbi->fsinfo.FSI_LeadSig, fsbi->fsinfo.FSI_StrucSig, fsbi->fsinfo.FSI_Free_Count);
415 
416     // 初始化超级块的dir entry
417     sb_ptr->root = vfs_alloc_dentry(2);
418 
419     sb_ptr->root->parent = sb_ptr->root;
420     sb_ptr->root->dir_ops = &fat32_dEntry_ops;
421     // 分配2个字节的name
422     sb_ptr->root->name[0] = '/';
423     sb_ptr->root->name_length = 1;
424 
425     // 为root目录项分配index node
426     sb_ptr->root->dir_inode = vfs_alloc_inode();
427     sb_ptr->root->dir_inode->inode_ops = &fat32_inode_ops;
428     sb_ptr->root->dir_inode->file_ops = &fat32_file_ops;
429     sb_ptr->root->dir_inode->file_size = 0;
430     // 计算文件占用的扇区数, 由于最小存储单位是簇,因此需要按照簇的大小来对齐扇区
431     sb_ptr->root->dir_inode->blocks =
432         (sb_ptr->root->dir_inode->file_size + fsbi->bytes_per_clus - 1) / fsbi->bytes_per_sec;
433     sb_ptr->root->dir_inode->attribute = VFS_IF_DIR;
434     sb_ptr->root->dir_inode->sb = sb_ptr; // 反向绑定对应的超级块
435 
436     // 初始化inode信息
437     sb_ptr->root->dir_inode->private_inode_info = kmalloc(sizeof(struct fat32_inode_info_t), 0);
438     memset(sb_ptr->root->dir_inode->private_inode_info, 0, sizeof(struct fat32_inode_info_t));
439     struct fat32_inode_info_t *finode = (struct fat32_inode_info_t *)sb_ptr->root->dir_inode->private_inode_info;
440 
441     finode->first_clus = fbs->BPB_RootClus;
442     finode->dEntry_location_clus = 0;
443     finode->dEntry_location_clus_offset = 0;
444     finode->create_time = 0;
445     finode->create_date = 0;
446     finode->write_date = 0;
447     finode->write_time;
448 
449     return sb_ptr;
450 }
451 
452 /**
453  * @brief todo: 写入superblock
454  *
455  * @param sb
456  */
fat32_write_superblock(struct vfs_superblock_t * sb)457 void fat32_write_superblock(struct vfs_superblock_t *sb)
458 {
459 }
460 
461 /**
462  * @brief 释放superblock的内存空间
463  *
464  * @param sb 要被释放的superblock
465  */
fat32_put_superblock(struct vfs_superblock_t * sb)466 void fat32_put_superblock(struct vfs_superblock_t *sb)
467 {
468     kfree(sb->private_sb_info);
469     kfree(sb->root->dir_inode->private_inode_info);
470     kfree(sb->root->dir_inode);
471     kfree(sb->root);
472     kfree(sb);
473 }
474 
475 /**
476  * @brief 写入inode到硬盘上
477  *
478  * @param inode
479  */
fat32_write_inode(struct vfs_index_node_t * inode)480 void fat32_write_inode(struct vfs_index_node_t *inode)
481 {
482     fat32_inode_info_t *finode = inode->private_inode_info;
483 
484     if (finode->dEntry_location_clus == 0)
485     {
486         kerror("FAT32 error: Attempt to write the root inode");
487         return;
488     }
489 
490     fat32_sb_info_t *fsbi = (fat32_sb_info_t *)inode->sb->private_sb_info;
491 
492     // 计算目标inode对应数据区的LBA地址
493     uint64_t fLBA = fsbi->first_data_sector + (finode->dEntry_location_clus - 2) * fsbi->sec_per_clus;
494 
495     struct fat32_Directory_t *buf = (struct fat32_Directory_t *)kmalloc(fsbi->bytes_per_clus, 0);
496     memset(buf, 0, fsbi->bytes_per_clus);
497 
498     inode->sb->blk_device->bd_disk->fops->transfer(inode->sb->blk_device->bd_disk, AHCI_CMD_READ_DMA_EXT, fLBA,
499                                                    fsbi->sec_per_clus, (uint64_t)buf);
500     // 计算目标dEntry所在的位置
501     struct fat32_Directory_t *fdEntry = buf + finode->dEntry_location_clus_offset;
502 
503     // 写入fat32文件系统的dir_entry
504     fdEntry->DIR_FileSize = inode->file_size;
505     fdEntry->DIR_FstClusLO = finode->first_clus & 0xffff;
506     fdEntry->DIR_FstClusHI = (finode->first_clus >> 16) | (fdEntry->DIR_FstClusHI & 0xf000);
507 
508     // 将dir entry写回磁盘
509     inode->sb->blk_device->bd_disk->fops->transfer(inode->sb->blk_device->bd_disk, AHCI_CMD_WRITE_DMA_EXT, fLBA,
510                                                    fsbi->sec_per_clus, (uint64_t)buf);
511     kfree(buf);
512 }
513 
514 struct vfs_super_block_operations_t fat32_sb_ops = {
515     .write_superblock = fat32_write_superblock,
516     .put_superblock = fat32_put_superblock,
517     .write_inode = fat32_write_inode,
518 };
519 
520 // todo: compare
fat32_compare(struct vfs_dir_entry_t * parent_dEntry,char * source_filename,char * dest_filename)521 long fat32_compare(struct vfs_dir_entry_t *parent_dEntry, char *source_filename, char *dest_filename)
522 {
523     return 0;
524 }
525 // todo: hash
fat32_hash(struct vfs_dir_entry_t * dEntry,char * filename)526 long fat32_hash(struct vfs_dir_entry_t *dEntry, char *filename)
527 {
528     return 0;
529 }
530 // todo: release
fat32_release(struct vfs_dir_entry_t * dEntry)531 long fat32_release(struct vfs_dir_entry_t *dEntry)
532 {
533     return 0;
534 }
535 // todo: iput
fat32_iput(struct vfs_dir_entry_t * dEntry,struct vfs_index_node_t * inode)536 long fat32_iput(struct vfs_dir_entry_t *dEntry, struct vfs_index_node_t *inode)
537 {
538     return 0;
539 }
540 
541 /**
542  * @brief fat32文件系统对于dEntry的操作
543  *
544  */
545 struct vfs_dir_entry_operations_t fat32_dEntry_ops = {
546     .compare = fat32_compare,
547     .hash = fat32_hash,
548     .release = fat32_release,
549     .iput = fat32_iput,
550 };
551 
552 // todo: open
fat32_open(struct vfs_index_node_t * inode,struct vfs_file_t * file_ptr)553 long fat32_open(struct vfs_index_node_t *inode, struct vfs_file_t *file_ptr)
554 {
555     return 0;
556 }
557 
558 // todo: close
fat32_close(struct vfs_index_node_t * inode,struct vfs_file_t * file_ptr)559 long fat32_close(struct vfs_index_node_t *inode, struct vfs_file_t *file_ptr)
560 {
561     return 0;
562 }
563 
564 /**
565  * @brief 从fat32文件系统读取数据
566  *
567  * @param file_ptr 文件描述符
568  * @param buf 输出缓冲区
569  * @param count 要读取的字节数
570  * @param position 文件指针位置
571  * @return long 执行成功:传输的字节数量    执行失败:错误码(小于0)
572  */
fat32_read(struct vfs_file_t * file_ptr,char * buf,int64_t count,long * position)573 long fat32_read(struct vfs_file_t *file_ptr, char *buf, int64_t count, long *position)
574 {
575 
576     struct fat32_inode_info_t *finode = (struct fat32_inode_info_t *)(file_ptr->dEntry->dir_inode->private_inode_info);
577     fat32_sb_info_t *fsbi = (fat32_sb_info_t *)(file_ptr->dEntry->dir_inode->sb->private_sb_info);
578     struct block_device *blk = file_ptr->dEntry->dir_inode->sb->blk_device;
579 
580     // First cluster num of the file
581     uint64_t cluster = finode->first_clus;
582     // kdebug("fsbi->bytes_per_clus=%d fsbi->sec_per_clus=%d finode->first_clus=%d cluster=%d", fsbi->bytes_per_clus,
583     // fsbi->sec_per_clus, finode->first_clus, cluster);
584 
585     // kdebug("fsbi->bytes_per_clus=%d", fsbi->bytes_per_clus);
586 
587     // clus offset in file
588     uint64_t clus_offset_in_file = (*position) / fsbi->bytes_per_clus;
589     // bytes offset in clus
590     uint64_t bytes_offset = (*position) % fsbi->bytes_per_clus;
591 
592     if (!cluster)
593         return -EFAULT;
594 
595     // find the actual cluster on disk of the specified position
596     for (int i = 0; i < clus_offset_in_file; ++i)
597         cluster = fat32_read_FAT_entry(blk, fsbi, cluster);
598 
599     // 如果需要读取的数据边界大于文件大小
600     if (*position + count > file_ptr->dEntry->dir_inode->file_size)
601         count = file_ptr->dEntry->dir_inode->file_size - *position;
602 
603     // 剩余还需要传输的字节数量
604     int64_t bytes_remain = count;
605 
606     // alloc buffer memory space for ahci transfer
607     void *tmp_buffer = kmalloc(fsbi->bytes_per_clus, 0);
608 
609     int64_t retval = 0;
610     do
611     {
612 
613         memset(tmp_buffer, 0, fsbi->bytes_per_clus);
614         uint64_t sector = fsbi->first_data_sector + (cluster - 2) * fsbi->sec_per_clus;
615 
616         // 读取一个簇的数据
617         int errno = blk->bd_disk->fops->transfer(blk->bd_disk, AHCI_CMD_READ_DMA_EXT, sector, fsbi->sec_per_clus,
618                                                  (uint64_t)tmp_buffer);
619         if (errno != AHCI_SUCCESS)
620         {
621             kerror("FAT32 FS(read) error!");
622             retval = -EIO;
623             break;
624         }
625 
626         int64_t step_trans_len = 0; // 当前循环传输的字节数
627         if (bytes_remain > (fsbi->bytes_per_clus - bytes_offset))
628             step_trans_len = (fsbi->bytes_per_clus - bytes_offset);
629         else
630             step_trans_len = bytes_remain;
631 
632         if (((uint64_t)buf) < USER_MAX_LINEAR_ADDR)
633             copy_to_user(buf, tmp_buffer + bytes_offset, step_trans_len);
634         else
635             memcpy(buf, tmp_buffer + bytes_offset, step_trans_len);
636 
637         bytes_remain -= step_trans_len;
638         buf += step_trans_len;
639         bytes_offset -= bytes_offset;
640 
641         *position += step_trans_len; // 更新文件指针
642 
643         cluster = fat32_read_FAT_entry(blk, fsbi, cluster);
644     } while (bytes_remain && (cluster < 0x0ffffff8) && cluster != 0);
645 
646     kfree(tmp_buffer);
647 
648     if (!bytes_remain)
649         retval = count;
650 
651     return retval;
652 }
653 
654 /**
655  * @brief 向fat32文件系统写入数据
656  *
657  * @param file_ptr 文件描述符
658  * @param buf 输入写入的字节数
659  * @param position 文件指针位置
660  * @return long 执行成功:传输的字节数量    执行失败:错误码(小于0)
661  */
fat32_write(struct vfs_file_t * file_ptr,char * buf,int64_t count,long * position)662 long fat32_write(struct vfs_file_t *file_ptr, char *buf, int64_t count, long *position)
663 {
664     struct fat32_inode_info_t *finode = (struct fat32_inode_info_t *)file_ptr->dEntry->dir_inode->private_inode_info;
665     fat32_sb_info_t *fsbi = (fat32_sb_info_t *)(file_ptr->dEntry->dir_inode->sb->private_sb_info);
666     struct block_device *blk = file_ptr->dEntry->dir_inode->sb->blk_device;
667 
668     // First cluster num of the file
669     uint32_t cluster = finode->first_clus;
670     int64_t flags = 0;
671 
672     // clus offset in file
673     uint64_t clus_offset_in_file = (*position) / fsbi->bytes_per_clus;
674     // bytes offset in clus
675     uint64_t bytes_offset = (*position) % fsbi->bytes_per_clus;
676 
677     if (!cluster) // 起始簇号为0,说明是空文件
678     {
679         // 分配空闲簇
680         if (fat32_alloc_clusters(file_ptr->dEntry->dir_inode, &cluster, 1) != 0)
681             return -ENOSPC;
682     }
683     else
684     {
685         // 跳转到position所在的簇
686         for (uint64_t i = 0; i < clus_offset_in_file; ++i)
687             cluster = fat32_read_FAT_entry(blk, fsbi, cluster);
688     }
689     // kdebug("cluster(start)=%d", cluster);
690     //  没有可用的磁盘空间
691     if (!cluster)
692         return -ENOSPC;
693 
694     int64_t bytes_remain = count;
695 
696     if (count < 0) // 要写入的字节数小于0
697         return -EINVAL;
698 
699     uint64_t sector;
700     int64_t retval = 0;
701 
702     void *tmp_buffer = kmalloc(fsbi->bytes_per_clus, 0);
703     do
704     {
705         memset(tmp_buffer, 0, fsbi->bytes_per_clus);
706         sector = fsbi->first_data_sector + (cluster - 2) * fsbi->sec_per_clus; // 计算对应的扇区
707         if (!flags)                                                            // 当前簇已分配
708         {
709             // kdebug("read existed sec=%ld", sector);
710             //  读取一个簇的数据
711             int errno = blk->bd_disk->fops->transfer(blk->bd_disk, AHCI_CMD_READ_DMA_EXT, sector, fsbi->sec_per_clus,
712                                                      (uint64_t)tmp_buffer);
713             if (errno != 0)
714             {
715                 // kerror("FAT32 FS(write)  read disk error!");
716                 retval = -EIO;
717                 break;
718             }
719         }
720 
721         int64_t step_trans_len = 0; // 当前循环传输的字节数
722         if (bytes_remain > (fsbi->bytes_per_clus - bytes_offset))
723             step_trans_len = (fsbi->bytes_per_clus - bytes_offset);
724         else
725             step_trans_len = bytes_remain;
726 
727         // kdebug("step_trans_len=%d, bytes_offset=%d", step_trans_len, bytes_offset);
728         if (((uint64_t)buf) < USER_MAX_LINEAR_ADDR)
729             copy_from_user(tmp_buffer + bytes_offset, buf, step_trans_len);
730         else
731             memcpy(tmp_buffer + bytes_offset, buf, step_trans_len);
732 
733         // 写入数据到对应的簇
734         int errno = blk->bd_disk->fops->transfer(blk->bd_disk, AHCI_CMD_WRITE_DMA_EXT, sector, fsbi->sec_per_clus,
735                                                  (uint64_t)tmp_buffer);
736         if (errno != AHCI_SUCCESS)
737         {
738             kerror("FAT32 FS(write)  write disk error!");
739             retval = -EIO;
740             break;
741         }
742 
743         bytes_remain -= step_trans_len;
744         buf += step_trans_len;
745         bytes_offset -= bytes_offset;
746 
747         *position += step_trans_len; // 更新文件指针
748         // kdebug("step_trans_len=%d", step_trans_len);
749 
750         int next_clus = 0;
751         if (bytes_remain)
752             next_clus = fat32_read_FAT_entry(blk, fsbi, cluster);
753         else
754             break;
755         if (next_clus >= 0x0ffffff8) // 已经到达了最后一个簇,需要分配新簇
756         {
757             if (fat32_alloc_clusters(file_ptr->dEntry->dir_inode, &next_clus, 1) != 0)
758             {
759                 // 没有空闲簇
760                 kfree(tmp_buffer);
761                 return -ENOSPC;
762             }
763 
764             cluster = next_clus; // 切换当前簇
765             flags = 1;           // 标记当前簇是新分配的簇
766         }
767 
768     } while (bytes_remain);
769 
770     // 文件大小有增长
771     if (*position > (file_ptr->dEntry->dir_inode->file_size))
772     {
773         file_ptr->dEntry->dir_inode->file_size = *position;
774         file_ptr->dEntry->dir_inode->sb->sb_ops->write_inode(file_ptr->dEntry->dir_inode);
775         // kdebug("new file size=%ld", *position);
776     }
777 
778     kfree(tmp_buffer);
779     if (!bytes_remain)
780         retval = count;
781     // kdebug("retval=%lld", retval);
782     return retval;
783 }
784 
785 /**
786  * @brief 调整文件的当前访问位置
787  *
788  * @param file_ptr vfs文件指针
789  * @param offset 调整的偏移量
790  * @param whence 调整方法
791  * @return long 更新后的指针位置
792  */
fat32_lseek(struct vfs_file_t * file_ptr,long offset,long whence)793 long fat32_lseek(struct vfs_file_t *file_ptr, long offset, long whence)
794 {
795     struct vfs_index_node_t *inode = file_ptr->dEntry->dir_inode;
796 
797     long pos = 0;
798     switch (whence)
799     {
800     case SEEK_SET: // 相对于文件头
801         pos = offset;
802         break;
803     case SEEK_CUR: // 相对于当前位置
804         pos = file_ptr->position + offset;
805         break;
806     case SEEK_END: // 相对于文件末尾
807         pos = file_ptr->dEntry->dir_inode->file_size + offset;
808         break;
809 
810     default:
811         return -EINVAL;
812         break;
813     }
814 
815     if (pos < 0 || pos > file_ptr->dEntry->dir_inode->file_size)
816         return -EOVERFLOW;
817     file_ptr->position = pos;
818 
819     // kdebug("fat32 lseek -> position=%d", file_ptr->position);
820     return pos;
821 }
822 // todo: ioctl
fat32_ioctl(struct vfs_index_node_t * inode,struct vfs_file_t * file_ptr,uint64_t cmd,uint64_t arg)823 long fat32_ioctl(struct vfs_index_node_t *inode, struct vfs_file_t *file_ptr, uint64_t cmd, uint64_t arg)
824 {
825     return 0;
826 }
827 
828 /**
829  * @brief fat32文件系统,关于文件的操作
830  *
831  */
832 struct vfs_file_operations_t fat32_file_ops = {
833     .open = fat32_open,
834     .close = fat32_close,
835     .read = fat32_read,
836     .write = fat32_write,
837     .lseek = fat32_lseek,
838     .ioctl = fat32_ioctl,
839     .readdir = fat32_readdir,
840 };
841 
842 /**
843  * @brief 创建新的文件
844  * @param parent_inode 父目录的inode结构体
845  * @param dest_dEntry 新文件的dentry
846  * @param mode 创建模式
847  */
fat32_create(struct vfs_index_node_t * parent_inode,struct vfs_dir_entry_t * dest_dEntry,int mode)848 long fat32_create(struct vfs_index_node_t *parent_inode, struct vfs_dir_entry_t *dest_dEntry, int mode)
849 {
850     // 文件系统超级块信息
851     fat32_sb_info_t *fsbi = (fat32_sb_info_t *)parent_inode->sb->private_sb_info;
852     // 父目录项的inode的私有信息
853     struct fat32_inode_info_t *parent_inode_info = (struct fat32_inode_info_t *)parent_inode->private_inode_info;
854 
855     int64_t retval = 0;
856 
857     // ======== 检验名称的合法性
858     retval = fat32_check_name_available(dest_dEntry->name, dest_dEntry->name_length, 0);
859 
860     if (retval != 0)
861         return retval;
862 
863     if (dest_dEntry->dir_inode != NULL)
864         return -EEXIST;
865 
866     struct vfs_index_node_t *inode = vfs_alloc_inode();
867     dest_dEntry->dir_inode = inode;
868     dest_dEntry->dir_ops = &fat32_dEntry_ops;
869 
870     struct fat32_inode_info_t *finode = (struct fat32_inode_info_t *)kzalloc(sizeof(struct fat32_inode_info_t), 0);
871     inode->attribute = VFS_IF_FILE;
872     inode->file_ops = &fat32_file_ops;
873     inode->file_size = 0;
874     inode->sb = parent_inode->sb;
875     inode->inode_ops = &fat32_inode_ops;
876     inode->private_inode_info = (void *)finode;
877     inode->blocks = fsbi->sec_per_clus;
878 
879     struct block_device *blk = inode->sb->blk_device;
880 
881     // 计算总共需要多少个目录项
882     uint32_t cnt_longname = (dest_dEntry->name_length + 25) / 26;
883     // 默认都是创建长目录项来存储
884     if (cnt_longname == 0)
885         cnt_longname = 1;
886 
887     // 空闲dentry所在的扇区号
888     uint32_t tmp_dentry_sector = 0;
889     // 空闲dentry所在的缓冲区的基地址
890     uint64_t tmp_dentry_clus_buf_addr = 0;
891     uint64_t tmp_parent_dentry_clus = 0;
892     // 寻找空闲目录项
893     struct fat32_Directory_t *empty_fat32_dentry = fat32_find_empty_dentry(
894         parent_inode, cnt_longname + 1, 0, &tmp_dentry_sector, &tmp_parent_dentry_clus, &tmp_dentry_clus_buf_addr);
895     // kdebug("found empty dentry, cnt_longname=%ld", cnt_longname);
896 
897     finode->first_clus = 0;
898     finode->dEntry_location_clus = tmp_parent_dentry_clus;
899     finode->dEntry_location_clus_offset = empty_fat32_dentry - (struct fat32_Directory_t *)tmp_dentry_clus_buf_addr;
900 
901     // ====== 为新的文件分配一个簇 =======
902     uint32_t new_dir_clus;
903     if (fat32_alloc_clusters(inode, &new_dir_clus, 1) != 0)
904     {
905         retval = -ENOSPC;
906         goto fail;
907     }
908     // kdebug("new dir clus=%ld", new_dir_clus);
909     // kdebug("dest_dEntry->name=%s", dest_dEntry->name);
910 
911     // ====== 填写短目录项
912     fat32_fill_shortname(dest_dEntry, empty_fat32_dentry, new_dir_clus);
913     // kdebug("dest_dEntry->name=%s",dest_dEntry->name);
914 
915     // 计算校验和
916     uint8_t short_dentry_ChkSum = fat32_ChkSum(empty_fat32_dentry->DIR_Name);
917 
918     // kdebug("dest_dEntry->name=%s", dest_dEntry->name);
919     // ======== 填写长目录项
920     fat32_fill_longname(dest_dEntry, (struct fat32_LongDirectory_t *)(empty_fat32_dentry - 1), short_dentry_ChkSum,
921                         cnt_longname);
922 
923     // ====== 将目录项写回磁盘
924     // kdebug("tmp_dentry_sector=%ld", tmp_dentry_sector);
925     blk->bd_disk->fops->transfer(blk->bd_disk, AHCI_CMD_WRITE_DMA_EXT, tmp_dentry_sector, fsbi->sec_per_clus,
926                                  tmp_dentry_clus_buf_addr);
927 
928     // 注意:parent字段需要在调用函数的地方进行设置
929 
930     // 释放在find empty dentry中动态申请的缓冲区
931     kfree((void *)tmp_dentry_clus_buf_addr);
932     return 0;
933 fail:;
934     // 释放在find empty dentry中动态申请的缓冲区
935     kfree((void *)tmp_dentry_clus_buf_addr);
936     dest_dEntry->dir_inode = NULL;
937     dest_dEntry->dir_ops = NULL;
938     kfree(finode);
939     kfree(inode);
940     return retval;
941 }
942 
943 /**
944  * @brief 创建文件夹
945  * @param inode 父目录的inode
946  * @param dEntry 新的文件夹的dentry
947  * @param mode 创建文件夹的mode
948  * @return long 错误码
949  */
fat32_mkdir(struct vfs_index_node_t * parent_inode,struct vfs_dir_entry_t * dEntry,int mode)950 int64_t fat32_mkdir(struct vfs_index_node_t *parent_inode, struct vfs_dir_entry_t *dEntry, int mode)
951 {
952     int64_t retval = 0;
953 
954     // 文件系统超级块信息
955     fat32_sb_info_t *fsbi = (fat32_sb_info_t *)parent_inode->sb->private_sb_info;
956     // 父目录项的inode私有信息
957     struct fat32_inode_info_t *parent_inode_info = (struct fat32_inode_info_t *)parent_inode->private_inode_info;
958     // ======== 检验名称的合法性
959     retval = fat32_check_name_available(dEntry->name, dEntry->name_length, 0);
960     if (retval != 0)
961         return retval;
962     // ====== 找一块连续的区域放置新的目录项 =====
963 
964     // 计算总共需要多少个目录项
965     uint32_t cnt_longname = (dEntry->name_length + 25) / 26;
966     // 默认都是创建长目录项来存储
967     if (cnt_longname == 0)
968         cnt_longname = 1;
969 
970     // 空闲dentry所在的扇区号
971     uint32_t tmp_dentry_sector = 0;
972     // 空闲dentry所在的缓冲区的基地址
973     uint64_t tmp_dentry_clus_buf_addr = 0;
974     uint64_t tmp_parent_dentry_clus = 0;
975     // 寻找空闲目录项
976     struct fat32_Directory_t *empty_fat32_dentry = fat32_find_empty_dentry(
977         parent_inode, cnt_longname + 1, 0, &tmp_dentry_sector, &tmp_parent_dentry_clus, &tmp_dentry_clus_buf_addr);
978 
979     // ====== 初始化inode =======
980     struct vfs_index_node_t *inode = vfs_alloc_inode();
981     inode->attribute = VFS_IF_DIR;
982     inode->blocks = fsbi->sec_per_clus;
983     inode->file_ops = &fat32_file_ops;
984     inode->file_size = 0;
985     inode->inode_ops = &fat32_inode_ops;
986     inode->sb = parent_inode->sb;
987 
988     struct block_device *blk = inode->sb->blk_device;
989 
990     // ===== 初始化inode的文件系统私有信息 ====
991 
992     inode->private_inode_info = (fat32_inode_info_t *)kmalloc(sizeof(fat32_inode_info_t), 0);
993     memset(inode->private_inode_info, 0, sizeof(fat32_inode_info_t));
994     fat32_inode_info_t *p = (fat32_inode_info_t *)inode->private_inode_info;
995     p->first_clus = 0;
996     p->dEntry_location_clus = tmp_parent_dentry_clus;
997     p->dEntry_location_clus_offset = empty_fat32_dentry - (struct fat32_Directory_t *)tmp_dentry_clus_buf_addr;
998     // kdebug(" p->dEntry_location_clus_offset=%d", p->dEntry_location_clus_offset);
999     // todo: 填写完全fat32_inode_info的信息
1000 
1001     // 初始化dentry信息
1002     dEntry->dir_ops = &fat32_dEntry_ops;
1003     dEntry->dir_inode = inode;
1004 
1005     // ====== 为新的文件夹分配一个簇 =======
1006     uint32_t new_dir_clus;
1007     if (fat32_alloc_clusters(inode, &new_dir_clus, 1) != 0)
1008     {
1009         retval = -ENOSPC;
1010         goto fail;
1011     }
1012 
1013     // kdebug("new dir clus=%ld", new_dir_clus);
1014 
1015     // ====== 填写短目录项
1016     fat32_fill_shortname(dEntry, empty_fat32_dentry, new_dir_clus);
1017 
1018     // 计算校验和
1019     uint8_t short_dentry_ChkSum = fat32_ChkSum(empty_fat32_dentry->DIR_Name);
1020 
1021     // ======== 填写长目录项
1022     fat32_fill_longname(dEntry, (struct fat32_LongDirectory_t *)(empty_fat32_dentry - 1), short_dentry_ChkSum,
1023                         cnt_longname);
1024 
1025     // ====== 将目录项写回磁盘
1026     // kdebug("tmp_dentry_sector=%ld", tmp_dentry_sector);
1027     blk->bd_disk->fops->transfer(blk->bd_disk, AHCI_CMD_WRITE_DMA_EXT, tmp_dentry_sector, fsbi->sec_per_clus,
1028                                  tmp_dentry_clus_buf_addr);
1029     // ====== 初始化新的文件夹的目录项 =====
1030     {
1031         // kdebug("to create dot and dot dot.");
1032         void *buf = kmalloc(fsbi->bytes_per_clus, 0);
1033         struct fat32_Directory_t *new_dir_dentries = (struct fat32_Directory_t *)buf;
1034         memset((void *)new_dir_dentries, 0, fsbi->bytes_per_clus);
1035 
1036         // 新增 . 目录项
1037         new_dir_dentries->DIR_Attr = ATTR_DIRECTORY;
1038         new_dir_dentries->DIR_FileSize = 0;
1039         new_dir_dentries->DIR_Name[0] = '.';
1040         for (int i = 1; i < 11; ++i)
1041             new_dir_dentries->DIR_Name[i] = 0x20;
1042 
1043         new_dir_dentries->DIR_FstClusHI = empty_fat32_dentry->DIR_FstClusHI;
1044         new_dir_dentries->DIR_FstClusLO = empty_fat32_dentry->DIR_FstClusLO;
1045 
1046         // 新增 .. 目录项
1047         ++new_dir_dentries;
1048         new_dir_dentries->DIR_Attr = ATTR_DIRECTORY;
1049         new_dir_dentries->DIR_FileSize = 0;
1050         new_dir_dentries->DIR_Name[0] = '.';
1051         new_dir_dentries->DIR_Name[1] = '.';
1052         for (int i = 2; i < 11; ++i)
1053             new_dir_dentries->DIR_Name[i] = 0x20;
1054         new_dir_dentries->DIR_FstClusHI = (unsigned short)(parent_inode_info->first_clus >> 16) & 0x0fff;
1055         new_dir_dentries->DIR_FstClusLO = (unsigned short)(parent_inode_info->first_clus) & 0xffff;
1056 
1057         // 写入磁盘
1058 
1059         uint64_t sector = fsbi->first_data_sector + (new_dir_clus - 2) * fsbi->sec_per_clus;
1060         // kdebug("add dot and dot dot: sector=%ld", sector);
1061         blk->bd_disk->fops->transfer(blk->bd_disk, AHCI_CMD_WRITE_DMA_EXT, sector, fsbi->sec_per_clus, (uint64_t)buf);
1062     }
1063 
1064     // 注意:parent字段需要在调用函数的地方进行设置
1065     // 注意:需要将当前dentry加入父目录的subdirs_list
1066 
1067     // 释放在find empty dentry中动态申请的缓冲区
1068     kfree((void *)tmp_dentry_clus_buf_addr);
1069 
1070     return 0;
1071 fail:;
1072     // 释放在find empty dentry中动态申请的缓冲区
1073     kfree((void *)tmp_dentry_clus_buf_addr);
1074     return retval;
1075 }
1076 
1077 // todo: rmdir
fat32_rmdir(struct vfs_index_node_t * inode,struct vfs_dir_entry_t * dEntry)1078 int64_t fat32_rmdir(struct vfs_index_node_t *inode, struct vfs_dir_entry_t *dEntry)
1079 {
1080     return 0;
1081 }
1082 
1083 // todo: rename
fat32_rename(struct vfs_index_node_t * old_inode,struct vfs_dir_entry_t * old_dEntry,struct vfs_index_node_t * new_inode,struct vfs_dir_entry_t * new_dEntry)1084 int64_t fat32_rename(struct vfs_index_node_t *old_inode, struct vfs_dir_entry_t *old_dEntry,
1085                      struct vfs_index_node_t *new_inode, struct vfs_dir_entry_t *new_dEntry)
1086 {
1087     return 0;
1088 }
1089 
1090 // todo: getAttr
fat32_getAttr(struct vfs_dir_entry_t * dEntry,uint64_t * attr)1091 int64_t fat32_getAttr(struct vfs_dir_entry_t *dEntry, uint64_t *attr)
1092 {
1093     return 0;
1094 }
1095 
1096 // todo: setAttr
fat32_setAttr(struct vfs_dir_entry_t * dEntry,uint64_t * attr)1097 int64_t fat32_setAttr(struct vfs_dir_entry_t *dEntry, uint64_t *attr)
1098 {
1099     return 0;
1100 }
1101 
1102 /**
1103  * @brief 从fat32中卸载inode
1104  *
1105  * @param inode 要被卸载的inode
1106  * @return int 错误码
1107  */
fat32_detach_inode(struct vfs_index_node_t * inode)1108 static int fat32_detach_inode(struct vfs_index_node_t *inode)
1109 {
1110     // todo: 当引入哈希表管理inode之后,这个函数负责将inode从哈希表中删除
1111     // 参考Linux的fat_detach
1112     return 0;
1113 }
1114 
1115 /**
1116  * @brief 取消inode和dentry之间的链接关系(删除文件)
1117  *
1118  * @param inode 要被取消关联关系的目录项的【父目录项】
1119  * @param dentry 要被取消关联关系的子目录项
1120  */
fat32_unlink(struct vfs_index_node_t * dir,struct vfs_dir_entry_t * dentry)1121 int64_t fat32_unlink(struct vfs_index_node_t *dir, struct vfs_dir_entry_t *dentry)
1122 {
1123     int retval = 0;
1124     struct vfs_superblock_t *sb = dir->sb;
1125     struct vfs_index_node_t *inode_to_remove = dentry->dir_inode;
1126     fat32_sb_info_t *fsbi = (fat32_sb_info_t *)sb->private_sb_info;
1127     struct fat32_slot_info sinfo = {0};
1128     // todo: 对fat32的超级块加锁
1129 
1130     retval = vfat_find(dir, dentry->name, &sinfo);
1131 
1132     if (unlikely(retval != 0))
1133         goto out;
1134 
1135     // 从fat表删除目录项
1136     retval = fat32_remove_entries(dir, &sinfo);
1137     if (unlikely(retval != 0))
1138         goto out;
1139     retval = fat32_detach_inode(dentry->dir_inode);
1140     if (unlikely(retval != 0))
1141         goto out;
1142 out:;
1143     if (sinfo.buffer != NULL)
1144         kfree(sinfo.buffer);
1145     // todo: 对fat32的超级块放锁
1146     return retval;
1147 }
1148 
1149 /**
1150  * @brief 读取文件夹(在指定目录中找出有效目录项)
1151  *
1152  * @param file_ptr 文件结构体指针
1153  * @param dirent 返回的dirent
1154  * @param filler 填充dirent的函数
1155  * @return uint64_t dirent的总大小
1156  */
fat32_readdir(struct vfs_file_t * file_ptr,void * dirent,vfs_filldir_t filler)1157 int64_t fat32_readdir(struct vfs_file_t *file_ptr, void *dirent, vfs_filldir_t filler)
1158 {
1159     struct fat32_inode_info_t *finode = (struct fat32_inode_info_t *)file_ptr->dEntry->dir_inode->private_inode_info;
1160     fat32_sb_info_t *fsbi = (fat32_sb_info_t *)file_ptr->dEntry->dir_inode->sb->private_sb_info;
1161     struct block_device *blk = file_ptr->dEntry->dir_inode->sb->blk_device;
1162 
1163     unsigned char *buf = (unsigned char *)kzalloc(fsbi->bytes_per_clus, 0);
1164     uint32_t cluster = finode->first_clus;
1165 
1166     // 当前文件指针所在位置的簇号(文件内偏移量)
1167     int clus_num = file_ptr->position / fsbi->bytes_per_clus;
1168 
1169     // 循环读取fat entry,直到读取到文件当前位置的所在簇号
1170     for (int i = 0; i < clus_num; ++i)
1171     {
1172         cluster = fat32_read_FAT_entry(blk, fsbi, cluster);
1173         if (cluster > 0x0ffffff7) // 文件结尾
1174         {
1175             kerror("file position out of range! (cluster not exists)");
1176             return NULL;
1177         }
1178     }
1179 
1180     uint64_t dentry_type = 0; // 传递给filler的dentry类型数据
1181 
1182     char *dir_name = NULL;
1183     int name_len = 0;
1184     // ==== 此时已经将文件夹的目录项起始簇的簇号读取到cluster变量中 ===
1185     while (cluster <= 0x0ffffff7) // cluster在循环末尾更新(如果当前簇已经没有短目录项的话)
1186     {
1187         // 计算文件夹当前位置所在簇的起始扇区号
1188         uint64_t sector = fsbi->first_data_sector + (cluster - 2) * fsbi->sec_per_clus;
1189         // 读取文件夹目录项当前位置起始扇区的数据
1190 
1191         if (AHCI_SUCCESS != blk->bd_disk->fops->transfer(blk->bd_disk, AHCI_CMD_READ_DMA_EXT, sector,
1192                                                          fsbi->sec_per_clus, (uint64_t)buf))
1193         {
1194             // 读取失败
1195             kerror("Failed to read the file's first sector.");
1196             kfree(buf);
1197             return NULL;
1198         }
1199 
1200         struct fat32_Directory_t *dentry = NULL;
1201         struct fat32_LongDirectory_t *long_dentry = NULL;
1202 
1203         // 找到当前短目录项
1204         dentry = (struct fat32_Directory_t *)(buf + file_ptr->position % fsbi->bytes_per_clus);
1205 
1206         name_len = 0;
1207         // 逐个查找短目录项
1208         for (int i = file_ptr->position % fsbi->bytes_per_clus; i < fsbi->bytes_per_clus;
1209              i += 32, file_ptr->position += 32, ++dentry)
1210         {
1211             // 若是长目录项则跳过
1212             if (dentry->DIR_Attr == ATTR_LONG_NAME)
1213                 continue;
1214             // 跳过无效表项、空闲表项
1215             if (dentry->DIR_Name[0] == 0xe5 || dentry->DIR_Name[0] == 0x00 || dentry->DIR_Name[0] == 0x05)
1216                 continue;
1217 
1218             // 找到短目录项
1219             // 该短目录项对应的第一个长目录项
1220             long_dentry = (struct fat32_LongDirectory_t *)(dentry - 1);
1221 
1222             // 如果长目录项有效,则读取长目录项
1223             if (long_dentry->LDIR_Attr == ATTR_LONG_NAME && long_dentry->LDIR_Ord != 0xe5 &&
1224                 long_dentry->LDIR_Ord != 0x00 && long_dentry->LDIR_Ord != 0x05)
1225             {
1226                 int count_long_dentry = 0;
1227                 // 统计长目录项的个数
1228                 while (long_dentry->LDIR_Attr == ATTR_LONG_NAME && long_dentry->LDIR_Ord != 0xe5 &&
1229                        long_dentry->LDIR_Ord != 0x00 && long_dentry->LDIR_Ord != 0x05)
1230                 {
1231                     ++count_long_dentry;
1232                     if (long_dentry->LDIR_Ord & 0x40) // 最后一个长目录项
1233                         break;
1234                     --long_dentry;
1235                 }
1236                 // 为目录名分配空间
1237                 dir_name = (char *)kmalloc(count_long_dentry * 26 + 1, 0);
1238                 memset(dir_name, 0, count_long_dentry * 26 + 1);
1239 
1240                 // 重新将长目录项指针指向第一个长目录项
1241                 long_dentry = (struct fat32_LongDirectory_t *)(dentry - 1);
1242                 name_len = 0;
1243                 // 逐个存储文件名
1244                 for (int j = 0; j < count_long_dentry; ++j, --long_dentry)
1245                 {
1246                     // 存储name1
1247                     for (int k = 0; k < 5; ++k)
1248                     {
1249                         if (long_dentry->LDIR_Name1[k] != 0xffff && long_dentry->LDIR_Name1[k] != 0x0000)
1250                             dir_name[name_len++] = (char)long_dentry->LDIR_Name1[k];
1251                     }
1252 
1253                     // 存储name2
1254                     for (int k = 0; k < 6; ++k)
1255                     {
1256                         if (long_dentry->LDIR_Name2[k] != 0xffff && long_dentry->LDIR_Name2[k] != 0x0000)
1257                             dir_name[name_len++] = (char)long_dentry->LDIR_Name2[k];
1258                     }
1259 
1260                     // 存储name3
1261                     for (int k = 0; k < 2; ++k)
1262                     {
1263                         if (long_dentry->LDIR_Name3[k] != 0xffff && long_dentry->LDIR_Name3[k] != 0x0000)
1264                             dir_name[name_len++] = (char)long_dentry->LDIR_Name3[k];
1265                     }
1266                 }
1267 
1268                 // 读取目录项成功,返回
1269                 dentry_type = dentry->DIR_Attr;
1270                 goto find_dir_success;
1271             }
1272             else // 不存在长目录项
1273             {
1274                 dir_name = (char *)kmalloc(15, 0);
1275                 memset(dir_name, 0, 15);
1276 
1277                 name_len = 0;
1278                 int total_len = 0;
1279                 // 读取基础名
1280                 for (int j = 0; j < 8; ++j, ++total_len)
1281                 {
1282                     if (dentry->DIR_Name[j] == ' ')
1283                         break;
1284 
1285                     if (dentry->DIR_NTRes & LOWERCASE_BASE) // 如果标记了文件名小写,则转换为小写字符
1286                         dir_name[name_len++] = dentry->DIR_Name[j] + 32;
1287                     else
1288                         dir_name[name_len++] = dentry->DIR_Name[j];
1289                 }
1290 
1291                 // 如果当前短目录项为文件夹,则直接返回,不需要读取扩展名
1292                 if (dentry->DIR_Attr & ATTR_DIRECTORY)
1293                 {
1294                     dentry_type = dentry->DIR_Attr;
1295                     goto find_dir_success;
1296                 }
1297 
1298                 // 是文件,增加  .
1299                 dir_name[name_len++] = '.';
1300 
1301                 // 读取扩展名
1302                 // 读取基础名
1303                 for (int j = 0; j < 3; ++j, ++total_len)
1304                 {
1305                     if (dentry->DIR_Name[j] == ' ')
1306                         break;
1307 
1308                     if (dentry->DIR_NTRes & LOWERCASE_BASE) // 如果标记了文件名小写,则转换为小写字符
1309                         dir_name[name_len++] = dentry->DIR_Name[j] + 32;
1310                     else
1311                         dir_name[name_len++] = dentry->DIR_Name[j];
1312                 }
1313 
1314                 if (total_len == 8) // 没有扩展名
1315                     dir_name[--name_len] = '\0';
1316 
1317                 dentry_type = dentry->DIR_Attr;
1318                 goto find_dir_success;
1319             }
1320         }
1321 
1322         // 当前簇不存在目录项
1323         cluster = fat32_read_FAT_entry(blk, fsbi, cluster);
1324     }
1325 
1326     kfree(buf);
1327     // 在上面的循环中读取到目录项结尾了,仍没有找到
1328     return NULL;
1329 
1330 find_dir_success:;
1331     // 将文件夹位置坐标加32(即指向下一个目录项)
1332     file_ptr->position += 32;
1333     // todo: 计算ino_t
1334     if (dentry_type & ATTR_DIRECTORY)
1335         dentry_type = VFS_IF_DIR;
1336     else
1337         dentry_type = VFS_IF_FILE;
1338 
1339     return filler(dirent, 0, dir_name, name_len, dentry_type, 0);
1340 }
1341 
1342 struct vfs_inode_operations_t fat32_inode_ops = {
1343     .create = fat32_create,
1344     .mkdir = fat32_mkdir,
1345     .rmdir = fat32_rmdir,
1346     .lookup = fat32_lookup,
1347     .rename = fat32_rename,
1348     .getAttr = fat32_getAttr,
1349     .setAttr = fat32_setAttr,
1350     .unlink = fat32_unlink,
1351 
1352 };
1353 
1354 /**
1355  * @brief 给定字符串长度,计算去除字符串尾部的'.'后,剩余部分的长度
1356  *
1357  * @param len 字符串长度(不包括\0)
1358  * @param name 名称字符串
1359  * @return unsigned int 去除'.'后的
1360  */
vfat_striptail_len(unsigned int len,const char * name)1361 static unsigned int vfat_striptail_len(unsigned int len, const char *name)
1362 {
1363     while (len && name[len - 1] == '.')
1364         --len;
1365     return len;
1366 }
1367 
1368 /**
1369  * @brief 在指定inode的长目录项中搜索目标子目录项
1370  *
1371  * @param dir 父目录项inode
1372  * @param name 要查找的子目录项的名称
1373  * @param len 子目录项名称长度
1374  * @param slot_info 返回的对应的子目录项的短目录项。
1375  * @return int 错误码
1376  */
fat_search_long(struct vfs_index_node_t * dir,const char * name,int len,struct fat32_slot_info * slot_info)1377 static int fat_search_long(struct vfs_index_node_t *dir, const char *name, int len, struct fat32_slot_info *slot_info)
1378 {
1379     int retval = 0;
1380     retval = __fat32_search_long_short(dir, name, len, slot_info);
1381     return retval;
1382 }
1383 /**
1384  * @brief 在fat32中,根据父inode,寻找给定名称的子inode
1385  *
1386  * @param dir 父目录项的inode
1387  * @param name 子目录项名称
1388  * @param slot_info 找到的slot的信息
1389  * @return int 错误码
1390  */
vfat_find(struct vfs_index_node_t * dir,const char * name,struct fat32_slot_info * slot_info)1391 static int vfat_find(struct vfs_index_node_t *dir, const char *name, struct fat32_slot_info *slot_info)
1392 {
1393     uint32_t len = vfat_striptail_len(strnlen(name, PAGE_4K_SIZE - 1), name);
1394 
1395     if (len == 0)
1396         return -ENOENT;
1397 
1398     return fat_search_long(dir, name, len, slot_info);
1399 }
1400 
1401 struct vfs_filesystem_type_t fat32_fs_type = {
1402     .name = "FAT32",
1403     .fs_flags = 0,
1404     .read_superblock = fat32_read_superblock,
1405     .next = NULL,
1406 };
fat32_init()1407 void fat32_init()
1408 {
1409 
1410     kinfo("Initializing FAT32...");
1411 
1412     // 在VFS中注册fat32文件系统
1413     vfs_register_filesystem(&fat32_fs_type);
1414 
1415     // 挂载根文件系统
1416     fat32_register_partition(ahci_gendisk0.partition + 0, 0);
1417     kinfo("FAT32 initialized.");
1418 }