mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-09 11:16:47 +00:00
🆕 在fat32文件系统中按照路径寻找文件
This commit is contained in:
parent
db8b4a4877
commit
9b382dab60
@ -85,6 +85,9 @@ softirq.o: exception/softirq.c
|
||||
fat32.o: filesystem/fat32/fat32.c
|
||||
gcc $(CFLAGS) -c filesystem/fat32/fat32.c -o filesystem/fat32/fat32.o
|
||||
|
||||
MBR.o: filesystem/MBR.c
|
||||
gcc $(CFLAGS) -c filesystem/MBR.c -o filesystem/MBR.o
|
||||
|
||||
# IPI的代码
|
||||
ifeq ($(ARCH), x86_64)
|
||||
OBJ_LIST += ipi.o
|
||||
@ -145,9 +148,9 @@ all: kernel
|
||||
objcopy -I elf64-x86-64 -O elf64-x86-64 -R ".comment" -R ".eh_frame" kernel ../bin/kernel/kernel.elf
|
||||
#
|
||||
|
||||
kernel: head.o entry.o main.o printk.o trap.o mm.o slab.o irq.o pic.o process.o sched.o syscall.o multiboot2.o cpu.o acpi.o ps2_keyboard.o ps2_mouse.o ata.o pci.o ahci.o smp.o apu_boot.o rtc.o HPET.o softirq.o timer.o fat32.o $(OBJ_LIST)
|
||||
kernel: head.o entry.o main.o printk.o trap.o mm.o slab.o irq.o pic.o process.o sched.o syscall.o multiboot2.o cpu.o acpi.o ps2_keyboard.o ps2_mouse.o ata.o pci.o ahci.o smp.o apu_boot.o rtc.o HPET.o softirq.o timer.o fat32.o MBR.o $(OBJ_LIST)
|
||||
ld -b elf64-x86-64 -z muldefs -o kernel head.o exception/entry.o main.o common/printk.o exception/trap.o exception/irq.o mm/mm.o mm/slab.o process/process.o syscall/syscall.o driver/multiboot2/multiboot2.o \
|
||||
common/cpu.o smp/smp.o smp/apu_boot.o exception/softirq.o sched/sched.o filesystem/fat32/fat32.o \
|
||||
common/cpu.o smp/smp.o smp/apu_boot.o exception/softirq.o sched/sched.o filesystem/fat32/fat32.o filesystem/MBR.o \
|
||||
driver/acpi/acpi.o driver/interrupt/pic.o driver/keyboard/ps2_keyboard.o driver/mouse/ps2_mouse.o driver/disk/ata.o driver/pci/pci.o driver/disk/ahci/ahci.o driver/timers/rtc/rtc.o driver/timers/HPET/HPET.o driver/timers/timer.o \
|
||||
$(LD_LIST) \
|
||||
-T link.lds
|
||||
|
@ -21,7 +21,7 @@
|
||||
#define ORANGE 0x00ff8000 //橙
|
||||
#define YELLOW 0x00ffff00 //黄
|
||||
#define GREEN 0x0000ff00 //绿
|
||||
#define ORANGEBLUE 0x000000ff //蓝
|
||||
#define BLUE 0x000000ff //蓝
|
||||
#define INDIGO 0x0000ffff //靛
|
||||
#define PURPLE 0x008000ff //紫
|
||||
|
||||
|
20
kernel/filesystem/MBR.c
Normal file
20
kernel/filesystem/MBR.c
Normal file
@ -0,0 +1,20 @@
|
||||
#include "MBR.h"
|
||||
#include <common/kprint.h>
|
||||
#include <driver/disk/ahci/ahci.h>
|
||||
|
||||
struct MBR_disk_partition_table_t MBR_partition_tables[MBR_MAX_AHCI_CTRL_NUM][MBR_MAX_AHCI_PORT_NUM] = {0};
|
||||
|
||||
/**
|
||||
* @brief 读取磁盘的分区表
|
||||
*
|
||||
* @param ahci_ctrl_num ahci控制器编号
|
||||
* @param ahci_port_num ahci端口编号
|
||||
*/
|
||||
struct MBR_disk_partition_table_t *MBR_read_partition_table(uint8_t ahci_ctrl_num, uint8_t ahci_port_num)
|
||||
{
|
||||
unsigned char buf[512];
|
||||
memset(buf, 0, 512);
|
||||
ahci_operation.transfer(ATA_CMD_READ_DMA_EXT, 0, 1, (uint64_t)&buf, ahci_ctrl_num, ahci_port_num);
|
||||
MBR_partition_tables[ahci_ctrl_num][ahci_port_num] = *(struct MBR_disk_partition_table_t *)buf;
|
||||
return &MBR_partition_tables[ahci_ctrl_num][ahci_port_num];
|
||||
}
|
@ -11,34 +11,47 @@
|
||||
#pragma once
|
||||
#include <common/glib.h>
|
||||
|
||||
#define MBR_MAX_AHCI_CTRL_NUM 4 // 系统支持的最大的ahci控制器数量
|
||||
#define MBR_MAX_AHCI_PORT_NUM 32 // 系统支持的每个ahci控制器对应的MBR磁盘数量(对应ahci磁盘号)
|
||||
|
||||
/**
|
||||
* @brief MBR硬盘分区表项的结构
|
||||
*
|
||||
*/
|
||||
struct MBR_disk_partition_table_entry_t
|
||||
{
|
||||
uint8_t flags; // 引导标志符,标记此分区为活动分区
|
||||
uint8_t starting_head; // 起始磁头号
|
||||
uint8_t flags; // 引导标志符,标记此分区为活动分区
|
||||
uint8_t starting_head; // 起始磁头号
|
||||
uint16_t starting_sector : 6, // 起始扇区号
|
||||
starting_cylinder : 10; // 起始柱面号
|
||||
uint8_t type; // 分区类型ID
|
||||
uint8_t ending_head; // 结束磁头号
|
||||
uint8_t type; // 分区类型ID
|
||||
uint8_t ending_head; // 结束磁头号
|
||||
|
||||
uint16_t ending_sector : 6, // 结束扇区号
|
||||
ending_cylinder : 10; // 结束柱面号
|
||||
|
||||
uint16_t ending_sector:6, // 结束扇区号
|
||||
ending_cylinder:10; // 结束柱面号
|
||||
|
||||
uint32_t starting_LBA; // 起始逻辑扇区
|
||||
uint32_t total_sectors; // 分区占用的磁盘扇区数
|
||||
|
||||
}__attribute__((packed));
|
||||
} __attribute__((packed));
|
||||
|
||||
/**
|
||||
* @brief MBR磁盘分区表结构体
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct MBR_disk_partition_table_t
|
||||
{
|
||||
uint8_t reserved[446];
|
||||
struct MBR_disk_partition_table_entry_t DPTE[4]; // 磁盘分区表项
|
||||
struct MBR_disk_partition_table_entry_t DPTE[4]; // 磁盘分区表项
|
||||
uint16_t BS_TrailSig;
|
||||
}__attribute__((packed));
|
||||
} __attribute__((packed));
|
||||
|
||||
extern struct MBR_disk_partition_table_t MBR_partition_tables[MBR_MAX_AHCI_CTRL_NUM][MBR_MAX_AHCI_PORT_NUM]; // 导出全局的MBR磁盘分区表
|
||||
|
||||
/**
|
||||
* @brief 读取磁盘的分区表
|
||||
*
|
||||
* @param ahci_ctrl_num ahci控制器编号
|
||||
* @param ahci_port_num ahci端口编号
|
||||
*/
|
||||
struct MBR_disk_partition_table_t *MBR_read_partition_table(uint8_t ahci_ctrl_num, uint8_t ahci_port_num);
|
@ -1,42 +1,444 @@
|
||||
#include "fat32.h"
|
||||
#include <common/kprint.h>
|
||||
#include <driver/disk/ahci/ahci.h>
|
||||
#include <filesystem/MBR.h>
|
||||
#include <process/spinlock.h>
|
||||
#include <mm/slab.h>
|
||||
|
||||
struct fat32_partition_info_t fat32_part_info[FAT32_MAX_PARTITION_NUM] = {0};
|
||||
static int total_fat32_parts = 0;
|
||||
static int max_fat32_parts_id = -1;
|
||||
static uint64_t fat32_part_info_bmp[FAT32_MAX_PARTITION_NUM / 64 + 1] = {0};
|
||||
|
||||
static spinlock_t fat32_part_reg_lock;
|
||||
|
||||
/**
|
||||
* @brief 读取指定磁盘上的第0个分区的fat32文件系统
|
||||
*
|
||||
* @param disk_num
|
||||
* @brief 注册指定磁盘上的指定分区的fat32文件系统
|
||||
*
|
||||
* @param ahci_ctrl_num ahci控制器编号
|
||||
* @param ahci_port_num ahci控制器端口编号
|
||||
* @param part_num 磁盘分区编号
|
||||
*
|
||||
* @return int 全局fat32分区id
|
||||
*/
|
||||
void fat32_FS_init(int disk_num)
|
||||
int fat32_register_partition(uint8_t ahci_ctrl_num, uint8_t ahci_port_num, uint8_t part_num)
|
||||
{
|
||||
int i;
|
||||
unsigned char buf[512];
|
||||
struct MBR_disk_partition_table_t DPT;
|
||||
struct fat32_BootSector_t fat32_bootsector;
|
||||
struct fat32_FSInfo_t fat32_fsinfo;
|
||||
for (int i = 0; i <= max_fat32_parts_id; ++i)
|
||||
{
|
||||
if (fat32_part_info_bmp[i / 64] & (1 << (i % 64)))
|
||||
{
|
||||
// 已经注册
|
||||
if (ahci_ctrl_num == fat32_part_info[i].ahci_ctrl_num && ahci_port_num == fat32_part_info[i].ahci_port_num && part_num == fat32_part_info[i].part_num)
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
// 注册分区
|
||||
spin_lock(&fat32_part_reg_lock);
|
||||
int current_part_id;
|
||||
for (int i = 0; i <= max_fat32_parts_id; ++i)
|
||||
{
|
||||
if ((fat32_part_info_bmp[i / 64] & (1 << (i % 64))) == 0)
|
||||
{
|
||||
current_part_id = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
++max_fat32_parts_id;
|
||||
current_part_id = max_fat32_parts_id;
|
||||
fat32_part_info_bmp[current_part_id / 64] |= (1 << (current_part_id % 64));
|
||||
spin_unlock(&fat32_part_reg_lock);
|
||||
|
||||
fat32_part_info[current_part_id].ahci_ctrl_num = ahci_ctrl_num;
|
||||
fat32_part_info[current_part_id].ahci_port_num = ahci_port_num;
|
||||
fat32_part_info[current_part_id].part_num = part_num;
|
||||
fat32_part_info[current_part_id].partition_id = current_part_id;
|
||||
|
||||
struct MBR_disk_partition_table_t *DPT = MBR_read_partition_table(ahci_ctrl_num, ahci_port_num);
|
||||
|
||||
memset(buf, 0, 512);
|
||||
ahci_operation.transfer(ATA_CMD_READ_DMA_EXT, 0, 1, (uint64_t)&buf, 0, 0);
|
||||
DPT = *(struct MBR_disk_partition_table_t *)buf;
|
||||
// for(i = 0 ;i < 512 ; i++)
|
||||
// color_printk(PURPLE,WHITE,"%02x",buf[i]);
|
||||
printk_color(ORANGE, BLACK, "DPTE[0] start_LBA:%#018lx\ttype:%#018lx\n", DPT.DPTE[0].starting_LBA, DPT.DPTE[0].type);
|
||||
printk_color(ORANGE, BLACK, "DPTE[0] start_LBA:%#018lx\ttype:%#018lx\n", DPT->DPTE[part_num].starting_LBA, DPT->DPTE[part_num].type);
|
||||
|
||||
memset(buf, 0, 512);
|
||||
|
||||
ahci_operation.transfer(ATA_CMD_READ_DMA_EXT, DPT.DPTE[0].starting_LBA, 1, (uint64_t)&buf, 0, 0);
|
||||
ahci_operation.transfer(ATA_CMD_READ_DMA_EXT, DPT->DPTE[part_num].starting_LBA, 1, (uint64_t)&buf, ahci_ctrl_num, ahci_port_num);
|
||||
|
||||
fat32_bootsector = *(struct fat32_BootSector_t *)buf;
|
||||
// for(i = 0 ;i < 512 ; i++)
|
||||
// printk_color(PURPLE,WHITE,"%02x",buf[i]);
|
||||
printk_color(ORANGE, BLACK, "FAT32 Boot Sector\n\tBPB_FSInfo:%#018lx\n\tBPB_BkBootSec:%#018lx\n\tBPB_TotSec32:%#018lx\n", fat32_bootsector.BPB_FSInfo, fat32_bootsector.BPB_BkBootSec, fat32_bootsector.BPB_TotSec32);
|
||||
fat32_part_info[current_part_id].bootsector = *(struct fat32_BootSector_t *)buf;
|
||||
|
||||
// 计算数据区起始扇区号
|
||||
fat32_part_info[current_part_id].first_data_sector = DPT->DPTE[part_num].starting_LBA + fat32_part_info[current_part_id].bootsector.BPB_RsvdSecCnt +
|
||||
fat32_part_info[current_part_id].bootsector.BPB_FATSz32 * fat32_part_info[current_part_id].bootsector.BPB_NumFATs;
|
||||
// 计算FAT1的起始扇区号
|
||||
fat32_part_info[current_part_id].FAT1_base_sector = DPT->DPTE[part_num].starting_LBA + fat32_part_info[current_part_id].bootsector.BPB_RsvdSecCnt;
|
||||
// 计算FAT2的起始扇区号
|
||||
fat32_part_info[current_part_id].FAT2_base_sector = fat32_part_info[current_part_id].FAT1_base_sector + fat32_part_info[current_part_id].bootsector.BPB_FATSz32;
|
||||
// 计算每个簇的大小
|
||||
fat32_part_info[current_part_id].bytes_per_clus = fat32_part_info[current_part_id].bootsector.BPB_BytesPerSec * fat32_part_info[current_part_id].bootsector.BPB_SecPerClus;
|
||||
|
||||
kdebug("fat32_part_info[current_part_id].FAT1_base_sector=%#018lx", fat32_part_info[current_part_id].FAT1_base_sector);
|
||||
printk_color(ORANGE, BLACK, "FAT32 Boot Sector\n\tBPB_FSInfo:%#018lx\n\tBPB_BkBootSec:%#018lx\n\tBPB_TotSec32:%#018lx\n", fat32_part_info[current_part_id].bootsector.BPB_FSInfo, fat32_part_info[current_part_id].bootsector.BPB_BkBootSec, fat32_part_info[current_part_id].bootsector.BPB_TotSec32);
|
||||
|
||||
memset(buf, 0, 512);
|
||||
ahci_operation.transfer(ATA_CMD_READ_DMA_EXT, DPT.DPTE[0].starting_LBA+ fat32_bootsector.BPB_FSInfo, 1, (uint64_t)&buf, 0, 0);
|
||||
ahci_operation.transfer(ATA_CMD_READ_DMA_EXT, DPT->DPTE[part_num].starting_LBA + fat32_part_info[current_part_id].bootsector.BPB_FSInfo, 1, (uint64_t)&buf, ahci_ctrl_num, ahci_port_num);
|
||||
|
||||
|
||||
fat32_fsinfo = *(struct fat32_FSInfo_t *)buf;
|
||||
fat32_part_info[current_part_id].fsinfo = *(struct fat32_FSInfo_t *)buf;
|
||||
// for(i = 0 ;i < 512 ; i++)
|
||||
// printk_color(PURPLE,WHITE,"%02x",buf[i]);
|
||||
printk_color(ORANGE, BLACK, "FAT32 FSInfo\n\tFSI_LeadSig:%#018lx\n\tFSI_StrucSig:%#018lx\n\tFSI_Free_Count:%#018lx\n", fat32_fsinfo.FSI_LeadSig, fat32_fsinfo.FSI_StrucSig, fat32_fsinfo.FSI_Free_Count);
|
||||
printk_color(ORANGE, BLACK, "FAT32 FSInfo\n\tFSI_LeadSig:%#018lx\n\tFSI_StrucSig:%#018lx\n\tFSI_Free_Count:%#018lx\n", fat32_part_info[current_part_id].fsinfo.FSI_LeadSig, fat32_part_info[current_part_id].fsinfo.FSI_StrucSig, fat32_part_info[current_part_id].fsinfo.FSI_Free_Count);
|
||||
kdebug("fat32_part_info[part_id].bootsector.BPB_RootClus = %#018lx", fat32_part_info[current_part_id].bootsector.BPB_RootClus);
|
||||
return current_part_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 读取指定簇的FAT表项
|
||||
*
|
||||
* @param part_id 分区id
|
||||
* @param cluster
|
||||
* @return uint32_t 下一个簇的簇号
|
||||
*/
|
||||
uint32_t fat32_read_FAT_entry(uint32_t part_id, uint32_t cluster)
|
||||
{
|
||||
|
||||
uint32_t fat_ent_per_sec = (fat32_part_info[part_id].bootsector.BPB_BytesPerSec >> 2); // 该值应为2的n次幂
|
||||
uint32_t buf[256];
|
||||
memset(buf, 0, fat32_part_info[part_id].bootsector.BPB_BytesPerSec);
|
||||
|
||||
ahci_operation.transfer(ATA_CMD_READ_DMA_EXT, fat32_part_info[part_id].FAT1_base_sector + (cluster / fat_ent_per_sec), 1, (uint64_t)&buf, fat32_part_info[part_id].ahci_ctrl_num, fat32_part_info[part_id].ahci_port_num);
|
||||
|
||||
uint32_t ret = buf[cluster & (fat_ent_per_sec - 1)] & 0x0fffffff;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 写入指定簇的FAT表项
|
||||
*
|
||||
* @param part_id 分区id
|
||||
* @param cluster
|
||||
* @param value 要写入该fat表项的值
|
||||
* @return uint32_t 下一个簇的簇号
|
||||
*/
|
||||
uint32_t fat32_write_FAT_entry(uint32_t part_id, uint32_t cluster, uint32_t value)
|
||||
{
|
||||
uint32_t fat_ent_per_sec = (fat32_part_info[part_id].bootsector.BPB_BytesPerSec >> 2); // 该值应为2的n次幂
|
||||
uint32_t buf[256];
|
||||
memset(buf, 0, fat32_part_info[part_id].bootsector.BPB_BytesPerSec);
|
||||
|
||||
ahci_operation.transfer(ATA_CMD_READ_DMA_EXT, fat32_part_info[part_id].FAT1_base_sector + (cluster / fat_ent_per_sec), 1, (uint64_t)&buf, fat32_part_info[part_id].ahci_ctrl_num, fat32_part_info[part_id].ahci_port_num);
|
||||
|
||||
buf[cluster & (fat_ent_per_sec - 1)] = (buf[cluster & (fat_ent_per_sec - 1)] & 0xf0000000) | (value & 0x0fffffff);
|
||||
// 向FAT1和FAT2写入数据
|
||||
ahci_operation.transfer(ATA_CMD_WRITE_DMA_EXT, fat32_part_info[part_id].FAT1_base_sector + (cluster / fat_ent_per_sec), 1, (uint64_t)&buf, fat32_part_info[part_id].ahci_ctrl_num, fat32_part_info[part_id].ahci_port_num);
|
||||
ahci_operation.transfer(ATA_CMD_WRITE_DMA_EXT, fat32_part_info[part_id].FAT2_base_sector + (cluster / fat_ent_per_sec), 1, (uint64_t)&buf, fat32_part_info[part_id].ahci_ctrl_num, fat32_part_info[part_id].ahci_port_num);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 在父目录中寻找指定的目录项
|
||||
*
|
||||
* @param part_id 分区id
|
||||
* @param name 目录项名字
|
||||
* @param name_len 目录项名字长度
|
||||
* @param dentry 父目录
|
||||
* @param flags
|
||||
* @return struct fat32_Directory_t* 目标目录项
|
||||
*/
|
||||
struct fat32_Directory_t *fat32_lookup(uint32_t part_id, char *name, int name_len, struct fat32_Directory_t *dentry, int flags)
|
||||
{
|
||||
int errcode = 0;
|
||||
uint8_t *buf = kmalloc(fat32_part_info[part_id].bytes_per_clus, 0);
|
||||
memset(buf, 0, fat32_part_info[part_id].bytes_per_clus);
|
||||
|
||||
// 计算父目录项的起始簇号
|
||||
uint32_t cluster = ((dentry->DIR_FstClusHI << 16) | (dentry->DIR_FstClusLO)) & 0x0fffffff;
|
||||
/*
|
||||
kdebug("dentry->DIR_FstClusHI=%#010lx", dentry->DIR_FstClusHI);
|
||||
kdebug("dentry->DIR_FstClusLo=%#010lx", dentry->DIR_FstClusLO);
|
||||
kdebug("cluster=%#010lx", cluster);
|
||||
*/
|
||||
while (true)
|
||||
{
|
||||
|
||||
// 计算父目录项的起始LBA扇区号
|
||||
uint64_t sector = fat32_part_info[part_id].first_data_sector + (cluster - 2) * fat32_part_info[part_id].bootsector.BPB_SecPerClus;
|
||||
//kdebug("fat32_part_info[part_id].bootsector.BPB_SecPerClus=%d",fat32_part_info[part_id].bootsector.BPB_SecPerClus);
|
||||
//kdebug("sector=%d",sector);
|
||||
|
||||
// 读取父目录项的起始簇数据
|
||||
ahci_operation.transfer(ATA_CMD_READ_DMA_EXT, sector, fat32_part_info[part_id].bootsector.BPB_SecPerClus, (uint64_t)buf, 0, 0);
|
||||
//ahci_operation.transfer(ATA_CMD_READ_DMA_EXT, sector, fat32_part_info[part_id].bootsector.BPB_SecPerClus, (uint64_t)buf, fat32_part_info[part_id].ahci_ctrl_num, fat32_part_info[part_id].ahci_port_num);
|
||||
|
||||
struct fat32_Directory_t *tmp_dEntry = (struct fat32_Directory_t *)buf;
|
||||
|
||||
// 查找短目录项
|
||||
for (int i = 0; i < fat32_part_info[part_id].bytes_per_clus; i += 32, ++tmp_dEntry)
|
||||
{
|
||||
// 跳过长目录项
|
||||
if (tmp_dEntry->DIR_Attr == ATTR_LONG_NAME)
|
||||
continue;
|
||||
|
||||
// 跳过无效页表项、空闲页表项
|
||||
if (tmp_dEntry->DIR_Name[0] == 0xe5 || tmp_dEntry->DIR_Name[0] == 0x00 || tmp_dEntry->DIR_Name[0] == 0x05)
|
||||
continue;
|
||||
|
||||
// 找到长目录项,位于短目录项之前
|
||||
struct fat32_LongDirectory_t *tmp_ldEntry = (struct fat32_LongDirectory_t *)tmp_dEntry - 1;
|
||||
|
||||
int js = 0;
|
||||
// 遍历每个长目录项
|
||||
while (tmp_ldEntry->LDIR_Attr == ATTR_LONG_NAME && tmp_ldEntry->LDIR_Ord != 0xe5)
|
||||
{
|
||||
// 比较name1
|
||||
for (int x = 0; x < 5; ++x)
|
||||
{
|
||||
if (js > name_len && tmp_ldEntry->LDIR_Name1[x] == 0xffff)
|
||||
continue;
|
||||
else if (js > name_len || tmp_ldEntry->LDIR_Name1[x] != (uint16_t)(name[js++])) // 文件名不匹配,检索下一个短目录项
|
||||
goto continue_cmp_fail;
|
||||
}
|
||||
|
||||
// 比较name2
|
||||
for (int x = 0; x < 6; ++x)
|
||||
{
|
||||
if (js > name_len && tmp_ldEntry->LDIR_Name2[x] == 0xffff)
|
||||
continue;
|
||||
else if (js > name_len || tmp_ldEntry->LDIR_Name2[x] != (uint16_t)(name[js++])) // 文件名不匹配,检索下一个短目录项
|
||||
goto continue_cmp_fail;
|
||||
}
|
||||
|
||||
// 比较name3
|
||||
for (int x = 0; x < 2; ++x)
|
||||
{
|
||||
if (js > name_len && tmp_ldEntry->LDIR_Name3[x] == 0xffff)
|
||||
continue;
|
||||
else if (js > name_len || tmp_ldEntry->LDIR_Name3[x] != (uint16_t)(name[js++])) // 文件名不匹配,检索下一个短目录项
|
||||
goto continue_cmp_fail;
|
||||
}
|
||||
|
||||
if (js >= name_len) // 找到需要的目录项,返回
|
||||
{
|
||||
struct fat32_Directory_t *p = (struct fat32_Directory_t *)kmalloc(sizeof(struct fat32_Directory_t), 0);
|
||||
*p = *tmp_dEntry;
|
||||
kfree(buf);
|
||||
return p;
|
||||
}
|
||||
|
||||
--tmp_ldEntry; // 检索下一个长目录项
|
||||
}
|
||||
|
||||
// 不存在长目录项,匹配短目录项的基础名
|
||||
js = 0;
|
||||
for (int x = 0; x < 8; ++x)
|
||||
{
|
||||
switch (tmp_dEntry->DIR_Name[x])
|
||||
{
|
||||
case ' ':
|
||||
if (!(tmp_dEntry->DIR_Attr & ATTR_DIRECTORY)) // 不是文件夹(是文件)
|
||||
{
|
||||
if (name[js] == '.')
|
||||
continue;
|
||||
else if (tmp_dEntry->DIR_Name[x] == name[js])
|
||||
{
|
||||
++js;
|
||||
break;
|
||||
}
|
||||
else
|
||||
goto continue_cmp_fail;
|
||||
}
|
||||
else // 是文件夹
|
||||
{
|
||||
if (js < name_len && tmp_dEntry->DIR_Name[x] == name[js]) // 当前位正确匹配
|
||||
{
|
||||
++js;
|
||||
break; // 进行下一位的匹配
|
||||
}
|
||||
else if (js == name_len)
|
||||
continue;
|
||||
else
|
||||
goto continue_cmp_fail;
|
||||
}
|
||||
break;
|
||||
|
||||
// 当前位是字母
|
||||
case 'A' ... 'Z':
|
||||
case 'a' ... 'z':
|
||||
if (tmp_dEntry->DIR_NTRes & LOWERCASE_BASE) // 为兼容windows系统,检测DIR_NTRes字段
|
||||
{
|
||||
if (js < name_len && (tmp_dEntry->DIR_Name[x] + 32 == name[js]))
|
||||
{
|
||||
++js;
|
||||
break;
|
||||
}
|
||||
else
|
||||
goto continue_cmp_fail;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (js < name_len && tmp_dEntry->DIR_Name[x] == name[js])
|
||||
{
|
||||
++js;
|
||||
break;
|
||||
}
|
||||
else
|
||||
goto continue_cmp_fail;
|
||||
}
|
||||
break;
|
||||
case '0' ... '9':
|
||||
if (js < name_len && tmp_dEntry->DIR_Name[x] == name[js])
|
||||
{
|
||||
++js;
|
||||
break;
|
||||
}
|
||||
else
|
||||
goto continue_cmp_fail;
|
||||
|
||||
break;
|
||||
default:
|
||||
++js;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 若短目录项为文件,则匹配扩展名
|
||||
if (!(tmp_dEntry->DIR_Attr & ATTR_DIRECTORY))
|
||||
{
|
||||
++js;
|
||||
for (int x = 8; x < 11; ++x)
|
||||
{
|
||||
switch (tmp_dEntry->DIR_Name[x])
|
||||
{
|
||||
// 当前位是字母
|
||||
case 'A' ... 'Z':
|
||||
case 'a' ... 'z':
|
||||
if (tmp_dEntry->DIR_NTRes & LOWERCASE_EXT) // 为兼容windows系统,检测DIR_NTRes字段
|
||||
{
|
||||
if ((tmp_dEntry->DIR_Name[x] + 32 == name[js]))
|
||||
{
|
||||
++js;
|
||||
break;
|
||||
}
|
||||
else
|
||||
goto continue_cmp_fail;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tmp_dEntry->DIR_Name[x] == name[js])
|
||||
{
|
||||
++js;
|
||||
break;
|
||||
}
|
||||
else
|
||||
goto continue_cmp_fail;
|
||||
}
|
||||
break;
|
||||
case '0' ... '9':
|
||||
case ' ':
|
||||
if (tmp_dEntry->DIR_Name[x] == name[js])
|
||||
{
|
||||
++js;
|
||||
break;
|
||||
}
|
||||
else
|
||||
goto continue_cmp_fail;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
goto continue_cmp_fail;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
struct fat32_Directory_t *p = (struct fat32_Directory_t *)kmalloc(sizeof(struct fat32_Directory_t), 0);
|
||||
*p = *tmp_dEntry;
|
||||
kfree(buf);
|
||||
return p;
|
||||
continue_cmp_fail:;
|
||||
}
|
||||
|
||||
// 当前簇没有发现目标文件名,寻找下一个簇
|
||||
cluster = fat32_read_FAT_entry(part_id, cluster);
|
||||
|
||||
if (cluster >= 0x0ffffff7) // 寻找完父目录的所有簇,都没有找到目标文件名
|
||||
{
|
||||
kfree(buf);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 按照路径查找文件
|
||||
*
|
||||
* @param part_id fat32分区id
|
||||
* @param path
|
||||
* @param flags
|
||||
* @return struct fat32_Directory_t*
|
||||
*/
|
||||
struct fat32_Directory_t *fat32_path_walk(uint32_t part_id, char *path, uint64_t flags)
|
||||
{
|
||||
// 去除路径前的斜杠
|
||||
while (*path == '/')
|
||||
++path;
|
||||
|
||||
if ((!*path) || (*path == '\0'))
|
||||
return NULL;
|
||||
|
||||
struct fat32_Directory_t *parent = (struct fat32_Directory_t *)kmalloc(sizeof(struct fat32_Directory_t), 0);
|
||||
char *dEntry_name = kmalloc(PAGE_4K_SIZE, 0);
|
||||
|
||||
memset(parent, 0, sizeof(struct fat32_Directory_t));
|
||||
memset(dEntry_name, 0, PAGE_4K_SIZE);
|
||||
|
||||
parent->DIR_FstClusLO = fat32_part_info[part_id].bootsector.BPB_RootClus & 0xffff;
|
||||
parent->DIR_FstClusHI = (fat32_part_info[part_id].bootsector.BPB_RootClus >> 16) & 0xffff;
|
||||
|
||||
while (true)
|
||||
{
|
||||
// 提取出下一级待搜索的目录名或文件名,并保存在dEntry_name中
|
||||
char *tmp_path = path;
|
||||
while ((*path && *path != '\0') && (*path != '/'))
|
||||
++path;
|
||||
int tmp_path_len = path - tmp_path;
|
||||
memcpy(dEntry_name, tmp_path, tmp_path_len);
|
||||
dEntry_name[tmp_path_len] = '\0';
|
||||
//kdebug("dEntry_name=%s", dEntry_name);
|
||||
struct fat32_Directory_t *next_dir = fat32_lookup(part_id, dEntry_name, tmp_path_len, parent, flags);
|
||||
|
||||
if (next_dir == NULL)
|
||||
{
|
||||
// 搜索失败
|
||||
kerror("cannot find the file/dir : %s", dEntry_name);
|
||||
kfree(dEntry_name);
|
||||
kfree(parent);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (*path == '/')
|
||||
++path;
|
||||
|
||||
if ((!*path) || (*path == '\0')) // 已经到达末尾
|
||||
{
|
||||
if (flags & 1) // 返回父目录
|
||||
{
|
||||
kfree(dEntry_name);
|
||||
kfree(next_dir);
|
||||
return parent;
|
||||
}
|
||||
|
||||
kfree(dEntry_name);
|
||||
kfree(parent);
|
||||
return next_dir;
|
||||
}
|
||||
|
||||
*parent = *next_dir;
|
||||
kfree(next_dir);
|
||||
}
|
||||
}
|
||||
|
||||
void fat32_init()
|
||||
{
|
||||
spin_init(&fat32_part_reg_lock);
|
||||
}
|
@ -13,6 +13,8 @@
|
||||
|
||||
#include <filesystem/MBR.h>
|
||||
|
||||
#define FAT32_MAX_PARTITION_NUM 128 // 系统支持的最大的fat32分区数量
|
||||
|
||||
/**
|
||||
* @brief fat32文件系统引导扇区结构体
|
||||
*
|
||||
@ -56,22 +58,101 @@ struct fat32_BootSector_t
|
||||
|
||||
/**
|
||||
* @brief fat32文件系统的FSInfo扇区结构体
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct fat32_FSInfo_t
|
||||
{
|
||||
uint32_t FSI_LeadSig; // FS info扇区标志符 数值为0x41615252
|
||||
uint32_t FSI_LeadSig; // FS info扇区标志符 数值为0x41615252
|
||||
uint8_t FSI_Reserved1[480]; // 保留使用,全部置为0
|
||||
uint32_t FSI_StrucSig; // 另一个标志符,数值为0x61417272
|
||||
uint32_t FSI_Free_Count; // 上一次记录的空闲簇数量,这是一个参考值
|
||||
uint32_t FSI_Nxt_Free; // 空闲簇的起始搜索位置,这是为驱动程序提供的参考值
|
||||
uint32_t FSI_StrucSig; // 另一个标志符,数值为0x61417272
|
||||
uint32_t FSI_Free_Count; // 上一次记录的空闲簇数量,这是一个参考值
|
||||
uint32_t FSI_Nxt_Free; // 空闲簇的起始搜索位置,这是为驱动程序提供的参考值
|
||||
uint8_t FSI_Reserved2[12]; // 保留使用,全部置为0
|
||||
uint32_t FSI_TrailSig; // 结束标志,数值为0xaa550000
|
||||
uint32_t FSI_TrailSig; // 结束标志,数值为0xaa550000
|
||||
} __attribute__((packed));
|
||||
|
||||
#define ATTR_READ_ONLY (1 << 0)
|
||||
#define ATTR_HIDDEN (1 << 1)
|
||||
#define ATTR_SYSTEM (1 << 2)
|
||||
#define ATTR_VOLUME_ID (1 << 3)
|
||||
#define ATTR_DIRECTORY (1 << 4)
|
||||
#define ATTR_ARCHIVE (1 << 5)
|
||||
#define ATTR_LONG_NAME (ATTR_READ_ONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_VOLUME_ID)
|
||||
|
||||
/**
|
||||
* @brief 读取指定磁盘上的第0个分区的fat32文件系统
|
||||
*
|
||||
* @param disk_num
|
||||
* @brief fat32文件系统短目录项,大小为32bytes
|
||||
*
|
||||
*/
|
||||
void fat32_FS_init(int disk_num);
|
||||
struct fat32_Directory_t
|
||||
{
|
||||
unsigned char DIR_Name[11];
|
||||
unsigned char DIR_Attr; // 文件属性
|
||||
unsigned char DIR_NTRes; // EXT|BASE => 8(BASE).3(EXT)
|
||||
// BASE:LowerCase(8),UpperCase(0)
|
||||
// EXT:LowerCase(16),UpperCase(0)
|
||||
unsigned char DIR_CrtTimeTenth; // 文件创建的毫秒级时间戳
|
||||
unsigned short DIR_CrtTime; // 文件创建时间
|
||||
unsigned short DIR_CrtDate; // 文件创建日期
|
||||
unsigned short DIR_LastAccDate; // 文件的最后访问日期
|
||||
unsigned short DIR_FstClusHI; // 起始簇号(高16bit)
|
||||
unsigned short DIR_WrtTime; // 最后写入时间
|
||||
unsigned short DIR_WrtDate; // 最后写入日期
|
||||
unsigned short DIR_FstClusLO; // 起始簇号(低16bit)
|
||||
unsigned int DIR_FileSize; // 文件大小
|
||||
} __attribute__((packed));
|
||||
|
||||
#define LOWERCASE_BASE (8)
|
||||
#define LOWERCASE_EXT (16)
|
||||
|
||||
/**
|
||||
* @brief fat32文件系统长目录项,大小为32bytes
|
||||
*
|
||||
*/
|
||||
struct fat32_LongDirectory_t
|
||||
{
|
||||
unsigned char LDIR_Ord; // 长目录项的序号
|
||||
unsigned short LDIR_Name1[5]; // 长文件名的第1-5个字符,每个字符占2bytes
|
||||
unsigned char LDIR_Attr; // 目录项属性必须为ATTR_LONG_NAME
|
||||
unsigned char LDIR_Type; // 如果为0,则说明这是长目录项的子项
|
||||
unsigned char LDIR_Chksum; // 短文件名的校验和
|
||||
unsigned short LDIR_Name2[6]; // 长文件名的第6-11个字符,每个字符占2bytes
|
||||
unsigned short LDIR_FstClusLO; // 必须为0
|
||||
unsigned short LDIR_Name3[2]; // 长文件名的12-13个字符,每个字符占2bytes
|
||||
} __attribute__((packed));
|
||||
|
||||
struct fat32_partition_info_t
|
||||
{
|
||||
uint16_t partition_id; // 全局fat32分区id
|
||||
uint8_t ahci_ctrl_num;
|
||||
uint8_t ahci_port_num;
|
||||
uint8_t part_num; // 硬盘中的分区号
|
||||
|
||||
struct fat32_BootSector_t bootsector;
|
||||
struct fat32_FSInfo_t fsinfo;
|
||||
|
||||
uint64_t first_data_sector; // 数据区起始扇区号
|
||||
uint64_t bytes_per_clus; // 每簇字节数
|
||||
uint64_t FAT1_base_sector; // FAT1表的起始簇号
|
||||
uint64_t FAT2_base_sector; // FAT2表的起始簇号
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 注册指定磁盘上的指定分区的fat32文件系统
|
||||
*
|
||||
* @param ahci_ctrl_num ahci控制器编号
|
||||
* @param ahci_port_num ahci控制器端口编号
|
||||
* @param part_num 磁盘分区编号
|
||||
*/
|
||||
int fat32_register_partition(uint8_t ahci_ctrl_num, uint8_t ahci_port_num, uint8_t part_num);
|
||||
|
||||
/**
|
||||
* @brief 按照路径查找文件
|
||||
*
|
||||
* @param part_id fat32分区id
|
||||
* @param path
|
||||
* @param flags
|
||||
* @return struct fat32_Directory_t*
|
||||
*/
|
||||
struct fat32_Directory_t *fat32_path_walk(uint32_t part_id, char *path, uint64_t flags);
|
||||
|
||||
void fat32_init();
|
@ -147,6 +147,7 @@ void system_initialize()
|
||||
// ata_init();
|
||||
pci_init();
|
||||
ahci_init();
|
||||
fat32_init();
|
||||
// test_slab();
|
||||
// test_mm();
|
||||
|
||||
@ -155,7 +156,6 @@ void system_initialize()
|
||||
current_pcb->preempt_count = 0;
|
||||
process_init();
|
||||
HPET_init();
|
||||
|
||||
}
|
||||
|
||||
//操作系统内核从这里开始执行
|
||||
@ -182,11 +182,19 @@ void Start_Kernel(void)
|
||||
|
||||
system_initialize();
|
||||
|
||||
int part_id = fat32_register_partition(0, 0, 0);
|
||||
struct fat32_Directory_t *dentry = fat32_path_walk(part_id, "a.txt", 0);
|
||||
if (dentry != NULL)
|
||||
printk_color(BLUE, BLACK, "Find a.txt\nDIR_FstClusHI:%#018lx\tDIR_FstClusLO:%#018lx\tDIR_FileSize:%#018lx\n", dentry->DIR_FstClusHI, dentry->DIR_FstClusLO, dentry->DIR_FileSize);
|
||||
else
|
||||
printk_color(BLUE, BLACK, "Can`t find file\n");
|
||||
|
||||
fat32_FS_init(0);
|
||||
dentry = fat32_path_walk(part_id, "xx/12.png", 0);
|
||||
if (dentry != NULL)
|
||||
printk_color(BLUE, BLACK, "Find xx/12.png\nDIR_FstClusHI:%#018lx\tDIR_FstClusLO:%#018lx\tDIR_FileSize:%#018lx\n", dentry->DIR_FstClusHI, dentry->DIR_FstClusLO, dentry->DIR_FileSize);
|
||||
else
|
||||
printk_color(BLUE, BLACK, "Can`t find file\n");
|
||||
|
||||
|
||||
|
||||
// show_welcome();
|
||||
// test_mm();
|
||||
|
||||
@ -215,7 +223,7 @@ void Start_Kernel(void)
|
||||
|
||||
// ipi_send_IPI(DEST_PHYSICAL, IDLE, ICR_LEVEL_DE_ASSERT, EDGE_TRIGGER, 0xc8, ICR_APIC_FIXED, ICR_No_Shorthand, true, 1); // 测试ipi
|
||||
|
||||
//int last_sec = rtc_now.second;
|
||||
// int last_sec = rtc_now.second;
|
||||
/*
|
||||
while (1)
|
||||
{
|
||||
|
@ -1,4 +1,7 @@
|
||||
echo "Creating virtual disk image..."
|
||||
qemu-img create -f raw disk.img 16M
|
||||
mkfs.vfat -f 32 disk.img
|
||||
echo "Successfully created disk image, please move it to folder ../bin/"
|
||||
fdisk disk.img
|
||||
sudo losetup -P /dev/loop1 --show disk.img
|
||||
lsblk
|
||||
#mkfs.vfat -F 32 /dev/loop1p1
|
||||
echo "Successfully created disk image, please make a FAT32 filesystem on it and move it to folder ../bin/"
|
||||
|
4
tools/mount_virt_disk.sh
Normal file
4
tools/mount_virt_disk.sh
Normal file
@ -0,0 +1,4 @@
|
||||
sudo losetup -P /dev/loop1 --show ../bin/disk.img
|
||||
lsblk
|
||||
mkdir -p ../bin/disk_mount/
|
||||
sudo mount /dev/loop1p1 ../bin/disk_mount/
|
3
tools/umount_virt_disk.sh
Normal file
3
tools/umount_virt_disk.sh
Normal file
@ -0,0 +1,3 @@
|
||||
sudo umount ../bin/disk_mount/
|
||||
rm -rf ../bin/disk_mount/
|
||||
sudo losetup -d /dev/loop1
|
Loading…
x
Reference in New Issue
Block a user