Failed to fetch fork details. Try again later.
-
尹健徽 authored993ae342
Forked from
10183_BOOT / OSKernel2024-10183_BOOT
Source project has a limited visibility.
#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 个簇是可分配的