Forked from 10183_BOOT / OSKernel2024-10183_BOOT
Source project has a limited visibility.
fat.c 37.00 KiB
#include "include/types.h"
#include "include/fat32.h"
#include "include/string.h"
#include "include/buf.h"
#include "include/riscv.h"
#include "include/defs.h"
#include "include/param.h"
#include "include/fs.h"
#include "include/spinlock.h"
#include "include/sleeplock.h"
#include "include/file.h"
#include "include/stat.h"
#include "include/proc.h"
#include "include/FileSystem.h"
#include <assert.h>
// 待办:assert.h 包含进来了却报错: undefined reference to `__assert_func'
// 解决这个之后吧注释掉的assert写回来
// struct superblock fat;
extern DirentCache direntCache;
extern FileSystem rootFileSystem;
 * Read the Boot Parameter Block.
 * @return  0       if success
 *          -1      if fail
// fs's read, name, mount_point should be inited
int fat32_init(FileSystem *fs) {
    // printf("[FAT32 init]fat init begin\n");
    struct buf *b = fs->read(fs, 0);
    if (b == 0) {
        panic("");
    // 82 是啥?
    if (strncmp((char const*)(b->data + 82), "FAT32", 5)) {
        panic("not FAT32 volume");
        return -1;
    memmove(&fs->superBlock.bpb.byts_per_sec, b->data + 11, 2);  
    fs->superBlock.bpb.sec_per_clus = *(b->data + 13);
    fs->superBlock.bpb.rsvd_sec_cnt = *(uint16*)(b->data + 14);
    fs->superBlock.bpb.fat_cnt = *(b->data + 16);
    fs->superBlock.bpb.hidd_sec = *(uint32*)(b->data + 28);
    fs->superBlock.bpb.tot_sec = *(uint32*)(b->data + 32);
    fs->superBlock.bpb.fat_sz = *(uint32*)(b->data + 36);
    fs->superBlock.bpb.root_clus = *(uint32*)(b->data + 44); // 44 根目录的第一个 clus 编号 通常为2
    fs->superBlock.first_data_sec = fs->superBlock.bpb.rsvd_sec_cnt + fs->superBlock.bpb.fat_cnt * fs->superBlock.bpb.fat_sz;
    fs->superBlock.data_sec_cnt = fs->superBlock.bpb.tot_sec - fs->superBlock.first_data_sec;
    fs->superBlock.data_clus_cnt = fs->superBlock.data_sec_cnt / fs->superBlock.bpb.sec_per_clus;
    fs->superBlock.byts_per_clus = fs->superBlock.bpb.sec_per_clus * fs->superBlock.bpb.byts_per_sec;
    brelse(b);
    // printf("[FAT32 init]read fat s\n");
#ifdef DEBUG
    printf("[FAT32 init]byts_per_sec: %d\n", fat.bpb.byts_per_sec);
    printf("[FAT32 init]root_clus: %d\n", fat.bpb.root_clus);
    printf("[FAT32 init]sec_per_clus: %d\n", fat.bpb.sec_per_clus);
    printf("[FAT32 init]fat_cnt: %d\n", fat.bpb.fat_cnt);
    printf("[FAT32 init]fat_sz: %d\n", fat.bpb.fat_sz);
    printf("[FAT32 init]first_data_sec: %d\n", fat.first_data_sec);
#endif
    // make sure that byts_per_sec has the same value with BSIZE
    if (BSIZE != fs->superBlock.bpb.byts_per_sec)
        panic("byts_per_sec != BSIZE");
    memset(&fs->root, 0, sizeof(fs->root));
    initsleeplock(&fs->root.lock, "entry");
    fs->root.attribute = (ATTR_DIRECTORY | ATTR_SYSTEM);
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
fs->root.first_clus = fs->root.cur_clus = fs->superBlock.bpb.root_clus; fs->root.valid = 1; fs->root.filename[0]='/'; fs->root.fileSystem = fs; fs->root.ref = 1; // printf("[FAT32 init]fat init end\n"); return 0; } // TODO ,当从 FAT32 卷的 FAT 条目加载值时,需要用 0x0FFFFFFF 屏蔽前 4 位。此外,当将值存储到 FAT 条目中时,需要保留 FAT 条目中的前 4 位。 /** * Read the FAT table content corresponded to the given cluster number. * @param cluster the number of cluster which you want to read its content * in FAT table */ // return的是fat[i],即该簇所在文件的下一个簇的编号 static uint32 read_fat(FileSystem *fs, uint32 cluster){ if (cluster >= FAT32_EOC) { return cluster; } if (cluster > FAT_CLUSTER_MAX) { // because cluster number starts at 2, not 0 return 0; } u32 fat_sec = ThisFATEntSecNum(cluster); struct buf* buf = fs->read(fs,fat_sec); u32 next_clus = *(u32*)(buf->data + ThisFATEntOffset(cluster)); brelse(buf); return next_clus; } /** * Write the FAT region content corresponded to the given cluster number. * @param cluster the number of cluster to write its content in FAT table * @param content the content which should be the next cluster number of * FAT end of chain flag * 把一个构造好的 32 位的目录项写进fat */ static int write_fat(FileSystem *fs, uint32 cluster, uint32 content) { if (cluster > fs->superBlock.data_clus_cnt + 1) { return -1; } uint32 fat_sec = ThisFATEntSecNum(cluster); struct buf* b = fs->read(fs, fat_sec); uint off = ThisFATEntOffset(cluster); *(uint32*)(b->data + off) = content; bwrite(b); brelse(b); return 0; } // 清空cluster 号对应的cluster数据块 static void zero_clus(FileSystem *fs, uint32 cluster) { uint32 sec = FirstSectorofCluster(cluster); struct buf* b; for (int i = 0; i < fs->superBlock.bpb.sec_per_clus; i++) { b = fs->read(fs, sec++); memset(b->data, 0, BSIZE); bwrite(b); brelse(b); } } // 分配设备 dev 上新的簇,并将该簇内容清空 // 读 FAT 表,找到空闲项并将其设为末尾簇 // 返回 cluster 的 number static u32 alloc_clus(FileSystem *fs, uint8 dev) {
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
// should we keep a free cluster list? instead of searching fat every time. struct buf* b; u32 sec = fs->superBlock.bpb.rsvd_sec_cnt; // i 是用来遍历一个 fat 表里面所有的sector // j 是用来遍历一个 sector 里面所有的 32 字节的 fat table entry for (u32 i = 0; i < fs->superBlock.bpb.fat_sz; i++, sec++) { b = fs->read(fs, sec); // 遍历一个 fat 表,为什么可以 j++ 呢,因为一个表项大小就是 u32 , ++ 就到下一个表项了 for (u32 j = 0; j < FCB_PER_BLOCK; j++) { if (((u32*)(b->data))[j] == 0) { //设为末尾簇,什么用?,相当于链表的尾插法其实,新分配的在屁股上 ((u32*)(b->data))[j] = FAT32_EOC + 7; bwrite(b); brelse(b); u32 clus = i * FCB_PER_BLOCK + j; zero_clus(fs, clus); return clus; } } brelse(b); } panic("no clusters"); } static void free_clus(FileSystem *fs, uint32 cluster) { write_fat(fs, cluster, 0); } // 读写某个簇的 off 偏移往后长度 n 的内容 // 如果 user_src == 1,代表src是一个虚拟地址, off代表偏移量(byte),n代表要读写多少个字节 static uint rw_clus(FileSystem *fs, uint32 cluster, int write, int user_src, u64 src, uint off, uint n) { if (off + n > fs->superBlock.byts_per_clus) panic("offset out of range"); if (n < 0) panic("n cannot be under zero"); uint tot, m; struct buf* bp; uint sec = FirstSectorofCluster(cluster) + off / fs->superBlock.bpb.byts_per_sec; off = off % fs->superBlock.bpb.byts_per_sec; int bad = 0; for (tot = 0; tot < n; tot += m, off += m, src += m, sec++) { bp = fs->read(fs, sec); // m 代表这次 r or w 了多少个字节 // Bsize = 1024 = fs->superBlock.byts_per_clus m = min(n - tot, fs->superBlock.byts_per_clus - off % fs->superBlock.byts_per_clus); if (write) { if ((bad = either_copyin(bp->data + (off % fs->superBlock.byts_per_clus), user_src, src,m)) != -1) { bwrite(bp); } } else { bad = either_copyout(user_src, src, bp->data + (off % fs->superBlock.byts_per_clus), m); } brelse(bp); if (bad == -1) { break; } } return tot; } /* * 对于第 i 个 FAT 项 * 如果 FAT[i] == FAT_ENTRY_FREE,则第 i 个簇是可分配的