修复ISO9660文件系统读取问题

This commit is contained in:
xiaoyi1212 2024-06-09 17:53:48 +08:00
parent 2c0b386a8b
commit 0fe64260c0
7 changed files with 242 additions and 196 deletions

View File

@ -6,6 +6,7 @@
bool read_sector(l9660_fs *fs, void *buf, uint32_t sector);
#define l9660_seekdir(dir, pos) (l9660_seek(&(dir)->file, L9660_SEEK_SET, (pos)))
#define l9660_telldir(dir) (l9660_tell(&(dir)->file))
xi#define get_root_dir(vfs) ((l9660_fs_status_t *)(vfs->cache))->root_dir
#define SEEK_END L9660_SEEK_END
#define SEEK_SET L9660_SEEK_SET
@ -41,77 +42,59 @@ static char gbuf[2048];
#define get_now_dir(vfs) ((l9660_fs_status_t *)(vfs->cache))->now_dir
static char *strchrnul(const char *s, int c)
{
while (*s)
{
static char *strchrnul(const char *s, int c) {
while (*s) {
if ((*s++) == c)
break;
}
return (char *)s;
}
static inline uint16_t
fsectoff(l9660_file
*f)
{
return f->position % 2048;
static inline uint16_t fsectoff(l9660_file *f) { return f->position % 2048; }
static inline uint32_t fsector(l9660_file *f) { return f->position / 2048; }
static inline uint32_t fnextsectpos(l9660_file *f) {
return (f->position + 2047) & ~2047;
}
static inline uint32_t
fsector(l9660_file
*f)
{
return f->position / 2048;
}
static inline uint32_t
fnextsectpos(l9660_file
*f)
{
return (f->position + 2047) & ~2047;
}
l9660_status l9660_openfs(l9660_fs *fs, bool (*read_sector)(l9660_fs *fs, void *buf, uint32_t sector), uint8_t disk_number)
{
fs->read_sector = read_sector;
fs->disk_number = disk_number;
logkf("fs--- %08x\n",fs->read_sector);
l9660_status l9660_openfs(l9660_fs *fs,
bool (*read_sector)(l9660_fs *fs, void *buf,
uint32_t sector),
uint8_t disk_number) {
fs->read_sector = read_sector;
fs->disk_number = disk_number;
#ifndef L9660_SINGLEBUFFER
l9660_vdesc_primary *pvd = PVD(&fs->pvd);
l9660_vdesc_primary *pvd = PVD(&fs->pvd);
#else
last_file = NULL;
l9660_vdesc_primary *pvd = PVD(gbuf);
last_file = NULL;
l9660_vdesc_primary *pvd = PVD(gbuf);
#endif
uint32_t idx = 0x10;
for (;;)
{
// Read next sector
if (!read_sector(fs, pvd, idx))
return L9660_EIO;
uint32_t idx = 0x10;
for (;;) {
// Read next sector
if (!read_sector(fs, pvd, idx))
return L9660_EIO;
// Validate magic
if (
memcmp(pvd
->hdr.magic,
"CD001", 5) != 0)
return L9660_EBADFS;
// Validate magic
if (memcmp(pvd->hdr.magic, "CD001", 5) != 0)
return L9660_EBADFS;
if (pvd->hdr.type == 1)
break; // Found PVD
else if (pvd->hdr.type == 255)
return L9660_EBADFS;
}
if (pvd->hdr.type == 1)
break; // Found PVD
else if (pvd->hdr.type == 255)
return L9660_EBADFS;
}
#ifdef L9660_SINGLEBUFFER
memcpy(&fs->root_dir_ent, &pvd->root_dir_ent, pvd->root_dir_ent.length);
memcpy(&fs->root_dir_ent, &pvd->root_dir_ent, pvd->root_dir_ent.length);
#endif
return L9660_OK;
return L9660_OK;
}
l9660_status l9660_fs_open_root(l9660_dir *dir, l9660_fs *fs)
{
l9660_status l9660_fs_open_root(l9660_dir *dir, l9660_fs *fs) {
l9660_file *f = &dir->file;
#ifndef L9660_SINGLEBUFFER
l9660_dirent *dirent = &PVD(&fs->pvd)->root_dir_ent;
@ -127,35 +110,32 @@ l9660_status l9660_fs_open_root(l9660_dir *dir, l9660_fs *fs)
return L9660_OK;
}
static l9660_status buffer(l9660_file *f)
{
static l9660_status buffer(l9660_file *f) {
#ifdef L9660_SINGLEBUFFER
last_file = f;
#endif
logkf("%08x %08x\n",read_sector,f->fs->read_sector);
if (!f->fs->read_sector(f->fs, BUF(f), f->first_sector + f->position / 2048))
return L9660_EIO;
else
return L9660_OK;
}
static l9660_status prebuffer(l9660_file *f)
{
static l9660_status prebuffer(l9660_file *f) {
if (!HAVEBUFFER(f) || (f->position % 2048) == 0)
return buffer(f);
else
return L9660_OK;
}
static l9660_status openat_raw(l9660_file *child, l9660_dir *parent, const char *name, bool isdir)
{
static l9660_status openat_raw(l9660_file *child, l9660_dir *parent,
const char *name, bool isdir) {
l9660_status rv;
l9660_dirent *dent = NULL;
if ((rv = l9660_seekdir(parent, 0)))
return rv;
do
{
do {
const char *seg = name;
name = strchrnul(name, '/');
size_t seglen = name - seg;
@ -165,14 +145,12 @@ static l9660_status openat_raw(l9660_file *child, l9660_dir *parent, const char
seg = "\0";
/* ISO9660 stores ".." as '\1' */
if (seglen == 2 && seg[0] == '.' && seg[1] == '.')
{
if (seglen == 2 && seg[0] == '.' && seg[1] == '.') {
seg = "\1";
seglen = 1;
}
for (;;)
{
for (;;) {
if ((rv = l9660_readdir(parent, &dent)))
return rv;
@ -204,20 +182,17 @@ static l9660_status openat_raw(l9660_file *child, l9660_dir *parent, const char
child->first_sector = READ32(dent->sector) + dent->xattr_length;
child->length = READ32(dent->size);
child->position = 0;
parent->file.position = 0;
if (*name && (dent->flags & DENT_ISDIR) != 0)
return L9660_ENOTDIR;
parent = (l9660_dir *)child;
} while (*name);
if (isdir)
{
if (isdir) {
if ((dent->flags & DENT_ISDIR) == 0)
return L9660_ENOTDIR;
}
else
{
} else {
if ((dent->flags & DENT_ISDIR) != 0)
return L9660_ENOTFILE;
}
@ -225,33 +200,28 @@ static l9660_status openat_raw(l9660_file *child, l9660_dir *parent, const char
return L9660_OK;
}
l9660_status l9660_opendirat(l9660_dir *dir, l9660_dir *parent, const char *path)
{
l9660_status l9660_opendirat(l9660_dir *dir, l9660_dir *parent,
const char *path) {
return openat_raw(&dir->file, parent, path, true);
}
static inline unsigned aligneven(unsigned v)
{
return v + (v & 1);
}
static inline unsigned aligneven(unsigned v) { return v + (v & 1); }
l9660_status l9660_readdir(l9660_dir *dir, l9660_dirent **pdirent)
{
l9660_status l9660_readdir(l9660_dir *dir, l9660_dirent **pdirent) {
l9660_status rv;
l9660_file *f = &dir->file;
rebuffer:
if (f->position >= f->length)
{
rebuffer:
if (f->position >= f->length) {
*pdirent = NULL;
f->position = 0;
return L9660_OK;
}
if ((rv = prebuffer(f)))
return rv;
char *off = BUF(f) + fsectoff(f);
if (*off == 0)
{
if (*off == 0) {
// Padded end of sector
f->position = fnextsectpos(f);
goto rebuffer;
@ -264,34 +234,31 @@ rebuffer:
return L9660_OK;
}
l9660_status l9660_openat(l9660_file *child, l9660_dir *parent, const char *name)
{
l9660_status l9660_openat(l9660_file *child, l9660_dir *parent,
const char *name) {
return openat_raw(child, parent, name, false);
}
/*! Seek the file to \p offset from \p whence */
l9660_status l9660_seek(l9660_file *f, int whence, int32_t offset)
{
l9660_status l9660_seek(l9660_file *f, int whence, int32_t offset) {
l9660_status rv;
uint32_t cursect = fsector(f);
switch (whence)
{
case SEEK_SET:
f->position = offset;
break;
switch (whence) {
case SEEK_SET:
f->position = offset;
break;
case SEEK_CUR:
f->position = f->position + offset;
break;
case SEEK_CUR:
f->position = f->position + offset;
break;
case SEEK_END:
f->position = f->length - offset;
break;
case SEEK_END:
f->position = f->length - offset;
break;
}
if (fsector(f) != cursect && fsectoff(f) != 0)
{
if (fsector(f) != cursect && fsectoff(f) != 0) {
if ((rv = buffer(f)))
return rv;
}
@ -299,13 +266,9 @@ l9660_status l9660_seek(l9660_file *f, int whence, int32_t offset)
return L9660_OK;
}
uint32_t l9660_tell(l9660_file *f)
{
return f->position;
}
uint32_t l9660_tell(l9660_file *f) { return f->position; }
l9660_status l9660_read(l9660_file *f, void *buf, size_t size, size_t *read)
{
l9660_status l9660_read(l9660_file *f, void *buf, size_t size, size_t *read) {
l9660_status rv;
if ((rv = prebuffer(f)))
@ -324,91 +287,54 @@ l9660_status l9660_read(l9660_file *f, void *buf, size_t size, size_t *read)
return L9660_OK;
}
bool read_sector(l9660_fs *fs, void *buf, uint32_t sector)
{
return CDROM_Read(sector,1,buf,fs->disk_number);
char *strdup(const char *s) {
size_t l = strlen(s);
char *d = kmalloc(l + 1);
if (!d)
return NULL;
return memcpy(d, s, l + 1);
}
bool read_sector(l9660_fs *fs, void *buf, uint32_t sector) {
return CDROM_Read(sector, 1, buf, fs->disk_number);
}
bool ISO_Check(uint8_t disk_number)
{
bool ISO_Check(uint8_t disk_number) {
unsigned char *buffer = kmalloc(2049); // 假设扇区大小为 2048 字节
bool ok = CDROM_Read(16, 1, buffer, disk_number);
if (buffer[0] == 0x01 && buffer[1] == 'C' && buffer[2] == 'D' && buffer[3] == '0' &&
buffer[4] == '0' && buffer[5] == '1')
{
if (buffer[0] == 0x01 && buffer[1] == 'C' && buffer[2] == 'D' &&
buffer[3] == '0' && buffer[4] == '0' && buffer[5] == '1') {
kfree(buffer);
return true; // 是 ISO9660 文件系统
}
else{
} else {
kfree(buffer);
return false; // 不是 ISO9660 文件系统
}
}
void ISO_InitFs(struct vfs_t *vfs, uint8_t disk_number)
{
void ISO_InitFs(struct vfs_t *vfs, uint8_t disk_number) {
l9660_fs_status_t *fs_m;
fs_m = (l9660_fs_status_t*) kmalloc(sizeof(l9660_fs_status_t));
fs_m = (l9660_fs_status_t *)kmalloc(sizeof(l9660_fs_status_t));
fs_m->fs = (l9660_fs *)kmalloc(sizeof(l9660_fs));
vfs->cache = (void *)fs_m;
printf("ISO Load init...");
l9660_openfs(fs_m->fs,read_sector,disk_number);
l9660_openfs(fs_m->fs, read_sector, disk_number);
l9660_fs_open_root(&fs_m->root_dir, fs_m->fs);
fs_m->now_dir = fs_m->root_dir;
logkf("%08x\n",vfs->cache);
/*
l9660_file file;
for (;;) {
l9660_dirent *dent;
l9660_readdir(root_dir, &dent);
if (dent == 0)
break;
printf("%.*s\n", dent->name_len, dent->name);
}
a = l9660_openat(&file, dir, "fuck.txt");
if(a) {
printf("failed\n");
for(;;);
}
for(;;) {
char buf[128];
size_t read;
l9660_read(&file, buf, 128, &read);
if (read == 0)
break;
for(int i = 0;i<read;i++) {
printf("%c",buf[i]);
}
}
while (1)
asm("hlt");
*/
logkf("%08x\n", vfs->cache);
}
void ISO_CDFile(){}
void ISO_CDFile() {}
vfs_file *ISO_GetFile(char* path1){
// strtoupper(path1);
// if (strcmp(path1, "/") == 0) {
// return fs_m->root_dir;
// }
return NULL;
}
void ISO_CopyCache(struct vfs_t *dest, struct vfs_t *src){
void ISO_CopyCache(struct vfs_t *dest, struct vfs_t *src) {
dest->cache = kmalloc(sizeof(l9660_fs_status_t));
memcpy(dest->cache, src->cache, sizeof(l9660_fs_status_t));
}
int ISO_cd(struct vfs_t *vfs, char *dictname){
//
// strtoupper(dictname);
//
int ISO_cd(struct vfs_t *vfs, char *dictname) {
//
// strtoupper(dictname);
//
if (strcmp(dictname, "/") == 0) {
while (vfs->path->ctl->all != 0) {
kfree((FindForCount(vfs->path->ctl->all, vfs->path)->val));
@ -418,10 +344,20 @@ int ISO_cd(struct vfs_t *vfs, char *dictname){
get_now_dir(vfs) = fs_m->root_dir;
return 1;
}
int free_flag = 0;
l9660_dir finfo;
l9660_status a = l9660_opendirat(&finfo,&get_now_dir(vfs),dictname);
l9660_status a;
RE:
a = l9660_opendirat(&finfo, &get_now_dir(vfs), dictname);
if (a) {
if (free_flag) {
kfree(dictname);
} else {
dictname = strdup(dictname);
strtoupper(dictname);
free_flag = 1;
goto RE;
}
return 0;
}
get_now_dir(vfs) = finfo;
@ -435,37 +371,64 @@ int ISO_cd(struct vfs_t *vfs, char *dictname){
kfree((FindForCount(vfs->path->ctl->all, vfs->path)->val));
DeleteVal(vfs->path->ctl->all, vfs->path);
}
return 1;
if (free_flag) {
kfree(dictname);
}
return 1;
}
bool ISO_ReadFile(struct vfs_t *vfs, char *path, char *buffer){
bool ISO_ReadFile(struct vfs_t *vfs, char *path, char *buffer) {
l9660_file file;
l9660_status a = l9660_openat(&file, &get_now_dir(vfs),path);
if(a) {
l9660_status a;
int free_flag = 0;
RE:
a = l9660_openat(&file, &get_now_dir(vfs), path);
if (a) {
if (free_flag) {
kfree(path);
} else {
path = strdup(path);
strtoupper(path);
free_flag = 1;
goto RE;
}
return false; // not found
}
for(;;) {
for (;;) {
size_t read;
l9660_read(&file, buffer, 128, &read);
if (read == 0)
break;
buffer += read;
}
if (free_flag) {
kfree(path);
}
return true;
}
List *ISO_ListFile(struct vfs_t *vfs, char *dictpath){
List *ISO_ListFile(struct vfs_t *vfs, char *dictpath) {
l9660_dir finfo;
if(strcmp(dictpath,"") == 0)
int free_flag = 0;
if (strcmp(dictpath, "") == 0)
finfo = get_now_dir(vfs);
else {
l9660_status a = l9660_opendirat(&finfo,&get_now_dir(vfs),dictpath);
l9660_status a;
RE:
a = l9660_opendirat(&finfo, &get_now_dir(vfs), dictpath);
if (a) {
if (free_flag) {
kfree(dictpath);
} else {
dictpath = strdup(dictpath);
strtoupper(dictpath);
free_flag = 1;
goto RE;
}
return NULL;
}
}
List *result = NewList();
for (;;) {
l9660_dirent *dent;
@ -474,47 +437,69 @@ List *ISO_ListFile(struct vfs_t *vfs, char *dictpath){
if (dent == 0)
break;
vfs_file *d = kmalloc(sizeof(vfs_file));
memclean((void *)d,sizeof(vfs_file));
memclean((void *)d, sizeof(vfs_file));
int j = 0;
if(memcmp("\0",dent->name,dent->name_len) == 0) {
if (memcmp("\0", dent->name, dent->name_len) == 0) {
if (finfo.file.first_sector == get_root_dir(vfs).file.first_sector) {
kfree(d);
continue;
}
d->name[j++] = '.';
d->name[j] = 0;
} else if (memcmp("\1",dent->name,dent->name_len) == 0) {
} else if (memcmp("\1", dent->name, dent->name_len) == 0) {
if (finfo.file.first_sector == get_root_dir(vfs).file.first_sector) {
kfree(d);
continue;
}
d->name[j++] = '.';
d->name[j++] = '.';
d->name[j] = 0;
}
else
for(;j<dent->name_len;j++) {
if(dent->name[j] == ';') {
} else
for (; j < dent->name_len; j++) {
if (dent->name[j] == ';') {
break;
}
d->name[j] = dent->name[j];
}
d->name[j] = 0;
d->name[j] = 0;
d->type = FLE;
if(dent->flags & DENT_ISDIR) {
if (dent->flags & DENT_ISDIR) {
d->type = DIR;
} else {
d->size = READ32(dent->size);
}
AddVal(d, result);
}
if (free_flag) {
kfree(dictpath);
}
return result;
}
int ISO_FileSize(struct vfs_t *vfs, char *filename) {
l9660_file file;
l9660_status a = l9660_openat(&file, &get_now_dir(vfs),filename);
if(a) {
return -1; // not found
l9660_status a;
int free_flag = 0;
RE:
a = l9660_openat(&file, &get_now_dir(vfs), filename);
if (a) {
if (free_flag) {
kfree(filename);
} else {
filename = strdup(filename);
strtoupper(filename);
free_flag = 1;
goto RE;
}
return -1; // not found
}
if (free_flag) {
kfree(filename);
}
return file.length;
}
void init_iso9660()
{
void init_iso9660() {
vfs_t fs;
fs.flag = 1;
fs.cache = NULL;

View File

@ -122,6 +122,7 @@ typedef struct tss_table {
} tss_entry;
void write_tss(int32_t num, uint16_t ss0, uint32_t esp0);
void set_kernel_stack(uintptr_t stack);
void gdt_install();
void idt_install();

46
src/include/elf.h Normal file
View File

@ -0,0 +1,46 @@
#ifndef CRASHPOWEROS_ELF_H
#define CRASHPOWEROS_ELF_H
#define ELF_MAGIC 0x464c457f
#include "common.h"
/* elf 32 header */
typedef struct elf32hdr {
uint32_t magic; // equal ELF_MAGIC
char elf[12];
uint16_t type;
uint16_t machine;
uint32_t version;
uint32_t entry; // program entry
uint32_t phoff; // offset of program header
uint32_t shoff;
uint32_t flags;
uint16_t ehsize;
uint16_t phentsize;
uint16_t phnum; // number of program header
uint16_t shentsize;
uint16_t shnum;
uint16_t shstrndx;
}elf32hdr_t;
/* proghdr type */
#define ELF_PROG_LOAD 1
/* proghdr flag*/
#define ELF_PROG_EXEC 0x1
#define ELF_PROG_WRITE 0x2
#define ELF_PROG_READ 0x4
struct proghdr{
uint32_t type;
uint32_t off;
uint32_t vaddr;
uint32_t paddr;
uint32_t filesz;
uint32_t memsz;
uint32_t flag;
uint32_t align;
};
#endif

View File

@ -93,4 +93,6 @@ void alloc_frame_line(page_t *page, unsigned line,int is_kernel, int is_writable
void free_frame(page_t *page);
void page_flush(page_directory_t *dir);
#endif //CRASHPOWEROS_MEMORY_H

View File

@ -86,6 +86,12 @@ void free_frame(page_t *page) {
}
}
void page_flush(page_directory_t *dir){
asm volatile("invlpg (%0)" ::"r"(&dir->tablesPhysical));
current_directory = dir;
//asm volatile("mov %0, %%cr3" : : "r"(&dir->physicalAddr));
}
void switch_page_directory(page_directory_t *dir) {
current_directory = dir;
asm volatile("mov %0, %%cr3" : : "r"(&dir->tablesPhysical));
@ -200,7 +206,7 @@ void init_page(multiboot_t *mboot) {
current_directory = kernel_directory;
int i = 0;
while (i < placement_address) {
while (i < placement_address + 0x30000) {
// 内核部分对ring3而言可读不可写 | 无偏移页表映射
alloc_frame(get_page(i, 1, kernel_directory), 0, 0);
i += 0x1000;

View File

@ -2,6 +2,7 @@
#include "../include/common.h"
#include "../include/graphics.h"
#include "../include/io.h"
#include "../include/description_table.h"
struct task_struct *running_proc_head = NULL;
struct task_struct *wait_proc_head = NULL;
@ -157,7 +158,8 @@ void change_task_to(struct task_struct *next) {
struct task_struct *prev = current;
current = next;
switch_page_directory(current->pgd_dir);
page_flush(current->pgd_dir);
set_kernel_stack(current->stack);
switch_to(&(prev->context), &(current->context));
}
}
@ -172,7 +174,7 @@ int32_t kernel_thread(int (*fn)(void *), void *arg,char* name) {
new_task->state = TASK_RUNNABLE;
new_task->stack = current;
new_task->pid = now_pid++;
new_task->pgd_dir = kernel_directory;
new_task->pgd_dir = clone_directory(kernel_directory) ;
new_task->name = name;

View File

@ -6,7 +6,9 @@
#include "../include/cmos.h"
#include "../include/vdisk.h"
#include "../include/vfs.h"
#include "../include/common.h"
#include "../include/sb16.h"
#include "../include/elf.h"
extern Queue *key_char_queue;
extern vdisk vdisk_ctl[10];
@ -239,6 +241,8 @@ void cmd_type(int argc,char ** argv){
printf("%s",buffer);
else printf("Cannot read file.\n");
kfree(buffer);
print("\n");
}