Support for multiple volumes, filesystem detection (currently FAT)
This commit is contained in:
parent
d0a5eb4c6f
commit
e688617286
77
file.c
77
file.c
@ -1,78 +1,113 @@
|
|||||||
#include "file.h"
|
#include "file.h"
|
||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
|
|
||||||
#define MAXFS (0x20000/sizeof(filesystem))
|
|
||||||
filesystem (*const FilesystemTable)[MAXFS] = (filesystem (* const)[MAXFS])0x240000;
|
|
||||||
|
|
||||||
// TODO Replace with something better
|
// TODO Replace with something better
|
||||||
extern uint8_t ActiveFsId;
|
extern uint8_t ActiveFsId;
|
||||||
|
|
||||||
|
// Sets adjusted_path to the path without filesystem info,
|
||||||
|
// returns the filesystem calculated
|
||||||
|
uint8_t GetFsFromPath(char *path, char **adjusted_path) {
|
||||||
|
// On active filsystem
|
||||||
|
if (*path == '/') {
|
||||||
|
*adjusted_path = path;
|
||||||
|
return GetActiveFilesystemId();
|
||||||
|
}
|
||||||
|
// Read the filesystem ID
|
||||||
|
uint8_t id = 0;
|
||||||
|
char *tmp_path = path;
|
||||||
|
// Find first /
|
||||||
|
for (;*tmp_path != '/';tmp_path++);
|
||||||
|
*adjusted_path = tmp_path;
|
||||||
|
// Read octal num
|
||||||
|
tmp_path--;
|
||||||
|
for (uint8_t bit_off = 0; tmp_path >= path; tmp_path--, bit_off+=3) {
|
||||||
|
// Outside of octal range, error
|
||||||
|
if (*tmp_path < '0' || *tmp_path > '8') return 0;
|
||||||
|
id += (*tmp_path - '0') << bit_off;
|
||||||
|
|
||||||
|
}
|
||||||
|
// Return filesystem
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
// Returns 0 on success, non-zero error code on error. Fills provided struct FILE
|
// Returns 0 on success, non-zero error code on error. Fills provided struct FILE
|
||||||
int file_open(FILE *file, char *path, char mode) {
|
int file_open(FILE *file, char *path, char mode) {
|
||||||
filesystem *fs = &(*FilesystemTable)[0];
|
char *adj_path;
|
||||||
return fs->ops.file_open(fs->fs_data, file, path, mode);
|
uint8_t fsid = GetFsFromPath(path, &adj_path);
|
||||||
|
filesystem *fs = GetFilesystem(fsid);
|
||||||
|
int err = fs->ops.file_open(fs->fs_data, file, adj_path, mode);
|
||||||
|
file->filesystem_id = fsid;
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns 0 on success, non-zero error code on error.
|
// Returns 0 on success, non-zero error code on error.
|
||||||
int file_seek(FILE *file, uint32_t offset) {
|
int file_seek(FILE *file, uint32_t offset) {
|
||||||
filesystem *fs = &(*FilesystemTable)[0];
|
filesystem *fs = GetFilesystem(file->filesystem_id);
|
||||||
return fs->ops.file_seek(fs->fs_data, file, offset);
|
return fs->ops.file_seek(fs->fs_data, file, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns 0 on error, bytes read on success.
|
// Returns 0 on error, bytes read on success.
|
||||||
int file_read(FILE *file, uint8_t *dest, uint32_t len) {
|
int file_read(FILE *file, uint8_t *dest, uint32_t len) {
|
||||||
filesystem *fs = &(*FilesystemTable)[0];
|
filesystem *fs = GetFilesystem(file->filesystem_id);
|
||||||
return fs->ops.file_read(fs->fs_data, file, dest, len);
|
return fs->ops.file_read(fs->fs_data, file, dest, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns 0 on error, bytes written on success.
|
// Returns 0 on error, bytes written on success.
|
||||||
int file_write(FILE *file, uint8_t *src, uint32_t len) {
|
int file_write(FILE *file, uint8_t *src, uint32_t len) {
|
||||||
filesystem *fs = &(*FilesystemTable)[0];
|
filesystem *fs = GetFilesystem(file->filesystem_id);
|
||||||
return fs->ops.file_write(fs->fs_data, file, src, len);
|
return fs->ops.file_write(fs->fs_data, file, src, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void file_close(FILE *file) {
|
void file_close(FILE *file) {
|
||||||
filesystem *fs = &(*FilesystemTable)[0];
|
filesystem *fs = GetFilesystem(file->filesystem_id);
|
||||||
return fs->ops.file_close(fs->fs_data, file);
|
return fs->ops.file_close(fs->fs_data, file);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns 0 on success, non-zero error code on error. Fills provided struct DIR
|
// Returns 0 on success, non-zero error code on error. Fills provided struct DIR
|
||||||
int dir_open(DIR *dir, char *path) {
|
int dir_open(DIR *dir, char *path) {
|
||||||
filesystem *fs = &(*FilesystemTable)[0];
|
char *adj_path;
|
||||||
return fs->ops.dir_open(fs->fs_data, dir, path);
|
uint8_t fsid = GetFsFromPath(path, &adj_path);
|
||||||
|
filesystem *fs = GetFilesystem(fsid);
|
||||||
|
int err = fs->ops.dir_open(fs->fs_data, dir, adj_path);
|
||||||
|
dir->filesystem_id = fsid;
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return 0 on success, non-zero error code on error. Fills provided struct dirent.
|
// Return 0 on success, non-zero error code on error. Fills provided struct dirent.
|
||||||
int dir_nextentry(DIR *dir, dirent *ent) {
|
int dir_nextentry(DIR *dir, dirent *ent) {
|
||||||
filesystem *fs = &(*FilesystemTable)[0];
|
filesystem *fs = GetFilesystem(dir->filesystem_id);
|
||||||
return fs->ops.dir_nextentry(fs->fs_data, dir, ent);
|
return fs->ops.dir_nextentry(fs->fs_data, dir, ent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dir_close(DIR *dir) {
|
void dir_close(DIR *dir) {
|
||||||
filesystem *fs = &(*FilesystemTable)[0];
|
filesystem *fs = GetFilesystem(dir->filesystem_id);
|
||||||
return fs->ops.dir_close(fs->fs_data, dir);
|
return fs->ops.dir_close(fs->fs_data, dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns 0 on success, non-zero error code on error. Fills provided struct dirent.
|
// Returns 0 on success, non-zero error code on error. Fills provided struct dirent.
|
||||||
int path_getinfo(char *path, dirent *ent) {
|
int path_getinfo(char *path, dirent *ent) {
|
||||||
filesystem *fs = &(*FilesystemTable)[0];
|
char *adj_path;
|
||||||
return fs->ops.path_getinfo(fs->fs_data, path, ent);
|
filesystem *fs = GetFilesystem(GetFsFromPath(path, &adj_path));
|
||||||
|
return fs->ops.path_getinfo(fs->fs_data, adj_path, ent);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns 0 on success, non-zero error code on error.
|
// Returns 0 on success, non-zero error code on error.
|
||||||
int path_mkdir(char *path) {
|
int path_mkdir(char *path) {
|
||||||
filesystem *fs = &(*FilesystemTable)[0];
|
char *adj_path;
|
||||||
return fs->ops.path_mkdir(fs->fs_data, path);
|
filesystem *fs = GetFilesystem(GetFsFromPath(path, &adj_path));
|
||||||
|
return fs->ops.path_mkdir(fs->fs_data, adj_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns 0 on success, non-zero error code on error.
|
// Returns 0 on success, non-zero error code on error.
|
||||||
int path_rmdir(char *path) {
|
int path_rmdir(char *path) {
|
||||||
filesystem *fs = &(*FilesystemTable)[0];
|
char *adj_path;
|
||||||
return fs->ops.path_rmdir(fs->fs_data, path);
|
filesystem *fs = GetFilesystem(GetFsFromPath(path, &adj_path));
|
||||||
|
return fs->ops.path_rmdir(fs->fs_data, adj_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns 0 on success, non-zero error code on error.
|
// Returns 0 on success, non-zero error code on error.
|
||||||
int path_rmfile(char *path) {
|
int path_rmfile(char *path) {
|
||||||
filesystem *fs = &(*FilesystemTable)[0];
|
char *adj_path;
|
||||||
return fs->ops.path_rmfile(fs->fs_data, path);
|
filesystem *fs = GetFilesystem(GetFsFromPath(path, &adj_path));
|
||||||
|
return fs->ops.path_rmfile(fs->fs_data, adj_path);
|
||||||
}
|
}
|
||||||
|
124
fs.c
124
fs.c
@ -1,15 +1,16 @@
|
|||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
|
#include "disk.h"
|
||||||
|
|
||||||
struct FsType {
|
struct FsType {
|
||||||
uint32_t type_id;
|
uint32_t type_id;
|
||||||
int (*init_func)(filesystem *, char);
|
int (*init_func)(filesystem *, uint32_t);
|
||||||
// Not yet decided
|
// Not yet decided
|
||||||
char (*detect_func)();
|
char (*detect_func)(uint32_t);
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO Get these dynamically somehow
|
// TODO Get these dynamically somehow
|
||||||
int InitDosFs(filesystem *fs, char partition);
|
int InitDosFs(filesystem *fs, uint32_t start_sector);
|
||||||
char DetectDosPart();
|
char DetectDosPart(uint32_t start_sector);
|
||||||
|
|
||||||
struct FsType SupportedFilesystems[] = {
|
struct FsType SupportedFilesystems[] = {
|
||||||
{
|
{
|
||||||
@ -19,18 +20,111 @@ struct FsType SupportedFilesystems[] = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MAXFS (0x20000/sizeof(filesystem))
|
#define MAXFS 255
|
||||||
filesystem (*const ActiveFilesystems)[MAXFS] = (filesystem (* const)[MAXFS])0x240000;
|
filesystem *ActiveFilesystems = (filesystem *)0x240000;
|
||||||
|
|
||||||
// TODO Replace with something better
|
uint8_t ActiveFsIdx;
|
||||||
uint8_t ActiveFsId;
|
|
||||||
|
|
||||||
// TODO Make functions and just use those instead
|
filesystem *GetFilesystem(uint8_t idx) {
|
||||||
int MakeSystemVolume(uint8_t sysPartition) {
|
if (idx >= MAXFS) return 0;
|
||||||
filesystem *sys = &(*ActiveFilesystems)[0];
|
filesystem *fs = &ActiveFilesystems[idx];
|
||||||
SupportedFilesystems[0].init_func(sys, sysPartition);
|
return fs->type != 0 ? fs : 0;
|
||||||
sys->type = SupportedFilesystems[0].type_id;
|
}
|
||||||
sys->id = 0;
|
|
||||||
ActiveFsId = 0;
|
filesystem *GetActiveFilesystem() {
|
||||||
|
return &ActiveFilesystems[ActiveFsIdx];
|
||||||
|
}
|
||||||
|
uint8_t GetActiveFilesystemId() {
|
||||||
|
return ActiveFsIdx;
|
||||||
|
}
|
||||||
|
|
||||||
|
filesystem *SetActiveFilesystem(uint8_t idx) {
|
||||||
|
if (idx >= MAXFS) return 0;
|
||||||
|
filesystem *fs = &ActiveFilesystems[idx];
|
||||||
|
if (fs->type == 0) return 0;
|
||||||
|
ActiveFsIdx = idx;
|
||||||
|
return fs;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActiveFilesystemBitmap(char *bitmap) {
|
||||||
|
for (int i = 0; i < 256; i++)
|
||||||
|
bitmap[i] = ActiveFilesystems[i].type != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct PartTableEntry_t {
|
||||||
|
uint8_t attr;
|
||||||
|
uint8_t start_chs0;
|
||||||
|
uint8_t start_chs1;
|
||||||
|
uint8_t start_chs2;
|
||||||
|
uint8_t type;
|
||||||
|
uint8_t end_chs0;
|
||||||
|
uint8_t end_chs1;
|
||||||
|
uint8_t end_chs2;
|
||||||
|
uint32_t start_lba;
|
||||||
|
uint32_t num_sectors;
|
||||||
|
};
|
||||||
|
typedef struct MBR_t {
|
||||||
|
char boot_code[0x1B8];
|
||||||
|
uint32_t signature;
|
||||||
|
uint16_t reserved;
|
||||||
|
struct PartTableEntry_t partTable[4];
|
||||||
|
uint16_t boot_sig;
|
||||||
|
} __attribute__((__packed__)) MBR_t;
|
||||||
|
|
||||||
|
// TODO Just check for this
|
||||||
|
uint8_t BootPartition;
|
||||||
|
uint8_t NextAvailableFilesystem;
|
||||||
|
|
||||||
|
MBR_t SysMbr;
|
||||||
|
|
||||||
|
void MakeMBRPartitions() {
|
||||||
|
// Get MBR
|
||||||
|
MBR_t *mbr = &SysMbr;
|
||||||
|
Disk_ReadSector(0, (uint8_t*)mbr, 0, 1);
|
||||||
|
|
||||||
|
// Scan partitions
|
||||||
|
for (int p = 0; p < 4; p++) {
|
||||||
|
if (p == BootPartition) continue;
|
||||||
|
if (mbr->partTable[p].type == 0) continue;
|
||||||
|
uint32_t partStart = mbr->partTable[p].start_lba;
|
||||||
|
if (partStart == 0) continue;
|
||||||
|
// Scan supported filesystems
|
||||||
|
filesystem *sys = &ActiveFilesystems[NextAvailableFilesystem];
|
||||||
|
for (int i = 0; i < sizeof(SupportedFilesystems)/sizeof(struct FsType); i++) {
|
||||||
|
if (!SupportedFilesystems[i].detect_func(partStart)) continue;
|
||||||
|
SupportedFilesystems[i].init_func(sys, partStart);
|
||||||
|
sys->type = SupportedFilesystems[i].type_id;
|
||||||
|
ActiveFsIdx = NextAvailableFilesystem;
|
||||||
|
NextAvailableFilesystem++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int MakeSystemVolume(uint8_t bootPartition) {
|
||||||
|
// Clear out filesystem area
|
||||||
|
for (int i = 0; i < (sizeof(filesystem)*MAXFS)/sizeof(uint32_t);i++)
|
||||||
|
((uint32_t*)ActiveFilesystems)[i] = 0;
|
||||||
|
|
||||||
|
BootPartition = bootPartition;
|
||||||
|
NextAvailableFilesystem = 1;
|
||||||
|
// Get MBR
|
||||||
|
MBR_t *mbr = &SysMbr;
|
||||||
|
Disk_ReadSector(0, (uint8_t*)mbr, 0, 1);
|
||||||
|
// Get boot partition sector
|
||||||
|
uint32_t sys_sector = mbr->partTable[bootPartition].start_lba;
|
||||||
|
|
||||||
|
// Scan supported filesystems
|
||||||
|
filesystem *sys = &ActiveFilesystems[0];
|
||||||
|
for (int i = 0; i < sizeof(SupportedFilesystems)/sizeof(struct FsType); i++) {
|
||||||
|
asm volatile("xchg %bx,%bx");
|
||||||
|
if (!SupportedFilesystems[i].detect_func(sys_sector)) continue;
|
||||||
|
SupportedFilesystems[i].init_func(sys, sys_sector);
|
||||||
|
sys->type = SupportedFilesystems[i].type_id;
|
||||||
|
ActiveFsIdx = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Init Failed
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
12
fs.h
12
fs.h
@ -3,9 +3,7 @@
|
|||||||
#include "file_s.h"
|
#include "file_s.h"
|
||||||
|
|
||||||
typedef struct filesystem {
|
typedef struct filesystem {
|
||||||
uint8_t id;
|
uint32_t resv0;
|
||||||
uint8_t resv0;
|
|
||||||
uint16_t resv1;
|
|
||||||
uint32_t type;
|
uint32_t type;
|
||||||
struct fs_operations {
|
struct fs_operations {
|
||||||
int (*file_open)(uint8_t *, FILE *, char *, char);
|
int (*file_open)(uint8_t *, FILE *, char *, char);
|
||||||
@ -24,5 +22,11 @@ typedef struct filesystem {
|
|||||||
} ops;
|
} ops;
|
||||||
uint8_t labellen;
|
uint8_t labellen;
|
||||||
char label[255];
|
char label[255];
|
||||||
uint8_t fs_data[512-4-4-44-256];
|
uint8_t fs_data[2048-4-4-44-256];
|
||||||
} __attribute__((packed)) filesystem;
|
} __attribute__((packed)) filesystem;
|
||||||
|
|
||||||
|
filesystem *GetFilesystem(uint8_t idx);
|
||||||
|
filesystem *GetActiveFilesystem();
|
||||||
|
uint8_t GetActiveFilesystemId();
|
||||||
|
filesystem *SetActiveFilesystem(uint8_t idx);
|
||||||
|
void ActiveFilesystemBitmap(char *bitmap);
|
||||||
|
67
fs_dos.c
67
fs_dos.c
@ -2,6 +2,10 @@
|
|||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
#include "dosfs/dosfs.h"
|
#include "dosfs/dosfs.h"
|
||||||
|
|
||||||
|
char *strncpy(char *restrict d, const char *restrict s, uintptr_t n);
|
||||||
|
int strcmp(const char *l, const char *r);
|
||||||
|
void *memcpy(void *restrict dest, const void *restrict src, uintptr_t n);
|
||||||
|
|
||||||
// Implementations for DOSFS
|
// Implementations for DOSFS
|
||||||
|
|
||||||
uint32_t DFS_ReadSector(uint8_t unit, uint8_t *buffer, uint32_t sector, uint32_t count) {
|
uint32_t DFS_ReadSector(uint8_t unit, uint8_t *buffer, uint32_t sector, uint32_t count) {
|
||||||
@ -40,6 +44,18 @@ int file83ToPath(uint8_t *src, char *path) {
|
|||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uintptr_t stripToDir(char *path) {
|
||||||
|
int i = 0;
|
||||||
|
// find end of string
|
||||||
|
for (;path[i];i++);
|
||||||
|
// find last /
|
||||||
|
for (;path[i] != '/' && i >= 0;i--);
|
||||||
|
// path[i] == '/'
|
||||||
|
// set next to end, return split location
|
||||||
|
path[i+1] = 0;
|
||||||
|
return i + 1;
|
||||||
|
}
|
||||||
|
|
||||||
int dos_file_open(uint8_t *dat, FILE *f, char *path, char mode) {
|
int dos_file_open(uint8_t *dat, FILE *f, char *path, char mode) {
|
||||||
fsdat *fs = (fsdat *)dat;
|
fsdat *fs = (fsdat *)dat;
|
||||||
uint8_t *scratch = (uint8_t *)0x20000;
|
uint8_t *scratch = (uint8_t *)0x20000;
|
||||||
@ -92,7 +108,6 @@ int dos_dir_open(uint8_t *dat, DIR *d, char *path) {
|
|||||||
|
|
||||||
int dos_dir_nextentry(uint8_t *dat, DIR *d, dirent *ent) {
|
int dos_dir_nextentry(uint8_t *dat, DIR *d, dirent *ent) {
|
||||||
fsdat *fs = (fsdat *)dat;
|
fsdat *fs = (fsdat *)dat;
|
||||||
uint8_t *scratch = (uint8_t *)0x20000;
|
|
||||||
DIRENT de;
|
DIRENT de;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
uint32_t code = DFS_GetNext(&fs->vi, (DIRINFO *)d->bytes, &de);
|
uint32_t code = DFS_GetNext(&fs->vi, (DIRINFO *)d->bytes, &de);
|
||||||
@ -121,10 +136,35 @@ int dos_dir_nextentry(uint8_t *dat, DIR *d, dirent *ent) {
|
|||||||
// DOSFS doesn't have anything to clean up
|
// DOSFS doesn't have anything to clean up
|
||||||
void dos_dir_close(uint8_t *dat, DIR *d) { return; }
|
void dos_dir_close(uint8_t *dat, DIR *d) { return; }
|
||||||
|
|
||||||
// TODO Unimplemented
|
// TODO Make this less expensive -> Use DOSFS directly?
|
||||||
int dos_path_getinfo(uint8_t *dat, char *path, dirent *d) {
|
int dos_path_getinfo(uint8_t *dat, char *path, dirent *d) {
|
||||||
fsdat *fs = (fsdat *)dat;
|
fsdat *fs = (fsdat *)dat;
|
||||||
uint8_t *scratch = (uint8_t *)0x20000;
|
uint8_t *scratch = (uint8_t *)0x20000;
|
||||||
|
|
||||||
|
// Get directory path is in
|
||||||
|
uint8_t tmppath[MAX_PATH];
|
||||||
|
strncpy((char*)tmppath,path,MAX_PATH);
|
||||||
|
tmppath[MAX_PATH-1]=0;
|
||||||
|
uintptr_t nameidx = stripToDir((char*)tmppath);
|
||||||
|
char *name = &path[nameidx];
|
||||||
|
|
||||||
|
// Open directory
|
||||||
|
DIR dir;
|
||||||
|
dos_dir_open(dat, &dir, (char*)tmppath);
|
||||||
|
|
||||||
|
dirent de;
|
||||||
|
// Enumerate info
|
||||||
|
for (;dos_dir_nextentry(dat, &dir, &de) == 0;) {
|
||||||
|
// Check if correct entry
|
||||||
|
if (strcmp(de.name, name) == 0) {
|
||||||
|
// Copy to caller dirent
|
||||||
|
for (int i = 0; i < sizeof(dirent); i++)
|
||||||
|
((uint8_t*)d)[i] = ((uint8_t*)&de)[i];
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Did not find or error
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,20 +192,27 @@ int dos_path_rmfile(uint8_t *dat, char *path) {
|
|||||||
// DOSFS doesn't have anything to clean up
|
// DOSFS doesn't have anything to clean up
|
||||||
void dos_endfs(uint8_t *dat) { return; }
|
void dos_endfs(uint8_t *dat) { return; }
|
||||||
|
|
||||||
// Not yet decided
|
// Try to detect if partition is a valid DOS partition
|
||||||
char DetectDosPart() {
|
char DetectDosPart(uint32_t start_sector) {
|
||||||
|
// Read sector
|
||||||
|
//uint8_t *scratch = (uint8_t *)0x20000;
|
||||||
|
//Disk_ReadSector(0, scratch, start_sector, 1);
|
||||||
|
//// Check for start bytes EBXX90
|
||||||
|
//if (((*(uint32_t*)&scratch[0]) & 0x00FF00FF) != 0x9000EB) return 0;
|
||||||
|
//// Check for bytes per sector == 512 (We don't support other values anyway)
|
||||||
|
//if (*(uint16_t*)&scratch[0xB] != 512) return 0;
|
||||||
|
|
||||||
|
// TODO Check more, so we *know* it's FAT
|
||||||
|
|
||||||
|
// We're probably FAT
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int InitDosFs(filesystem *fs, char partition) {
|
int InitDosFs(filesystem *fs, uint32_t start_sector) {
|
||||||
uint8_t *diskReadBuf = (uint8_t *)0x20000;
|
uint8_t *diskReadBuf = (uint8_t *)0x20000;
|
||||||
uint8_t pactive, ptype;
|
|
||||||
uint32_t pstart, psize;
|
|
||||||
pstart = DFS_GetPtnStart(0, diskReadBuf, partition, &pactive, &ptype, &psize);
|
|
||||||
if (pstart == -1) return -1;
|
|
||||||
|
|
||||||
VOLINFO *vi = (VOLINFO *)fs->fs_data;
|
VOLINFO *vi = (VOLINFO *)fs->fs_data;
|
||||||
if (DFS_GetVolInfo(0, diskReadBuf, pstart, (VOLINFO *)fs->fs_data)) {
|
if (DFS_GetVolInfo(0, diskReadBuf, start_sector, (VOLINFO *)fs->fs_data)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
20
hexedit.c
20
hexedit.c
@ -12,30 +12,28 @@ uint32_t blockLenMap[TOTALBLOCKS] __attribute__((section(".hexbss")));;
|
|||||||
// so that it can be expanded without telling C how much
|
// so that it can be expanded without telling C how much
|
||||||
// it actually needs
|
// it actually needs
|
||||||
uint8_t writeStoreBase[BLOCKSIZE] __attribute__((section(".hexlatebss")));
|
uint8_t writeStoreBase[BLOCKSIZE] __attribute__((section(".hexlatebss")));
|
||||||
void HexEditor(char *path, dirent *de) {
|
void HexEditor(char *path) {
|
||||||
uint32_t err;
|
uint32_t err;
|
||||||
uint16_t *vga_text = (uint16_t *)0xb8000;
|
uint16_t *vga_text = (uint16_t *)0xb8000;
|
||||||
uint32_t screenSize = 80*25;
|
uint32_t screenSize = 80*25;
|
||||||
uint8_t *scratch = (uint8_t *)0x20000;
|
|
||||||
uint8_t (*writeStore)[BLOCKSIZE] = &writeStoreBase;
|
uint8_t (*writeStore)[BLOCKSIZE] = &writeStoreBase;
|
||||||
uint32_t filelen = de->size;
|
|
||||||
for (int i = 0; i < TOTALBLOCKS; i++)
|
for (int i = 0; i < TOTALBLOCKS; i++)
|
||||||
writtenMap[i] = 0;
|
writtenMap[i] = 0;
|
||||||
uint8_t *screenBuff = *writeStore;
|
uint8_t *screenBuff = *writeStore;
|
||||||
// First two blocks are screen buffer
|
// First two blocks are screen buffer
|
||||||
uint32_t nextFreeBlock = 2;
|
uint32_t nextFreeBlock = 2;
|
||||||
|
|
||||||
FILE file;
|
|
||||||
vga_text = (uint16_t *)0xb8000;
|
vga_text = (uint16_t *)0xb8000;
|
||||||
for (int i = 0; i < 80*50; i++)
|
for (int i = 0; i < 80*50; i++)
|
||||||
vga_text[i] = 0x0f00;
|
vga_text[i] = 0x0f00;
|
||||||
err = file_open(&file, path, OPENREAD|OPENWRITE);
|
dirent de;
|
||||||
|
err = path_getinfo(path, &de);
|
||||||
if (err) {
|
if (err) {
|
||||||
vga_text += printStr("Open Error: ", vga_text);
|
vga_text += printStr("Error getting file info.", vga_text);
|
||||||
printDword(err, vga_text);
|
|
||||||
kbd_wait();
|
kbd_wait();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
uint32_t filelen = de.size;
|
||||||
if (filelen == 0) {
|
if (filelen == 0) {
|
||||||
vga_text += printStr("File ", vga_text);
|
vga_text += printStr("File ", vga_text);
|
||||||
vga_text += printStr((char*)path, vga_text);
|
vga_text += printStr((char*)path, vga_text);
|
||||||
@ -50,6 +48,14 @@ void HexEditor(char *path, dirent *de) {
|
|||||||
kbd_wait();
|
kbd_wait();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
FILE file;
|
||||||
|
err = file_open(&file, path, OPENREAD|OPENWRITE);
|
||||||
|
if (err) {
|
||||||
|
vga_text += printStr("Open Error: ", vga_text);
|
||||||
|
printDword(err, vga_text);
|
||||||
|
kbd_wait();
|
||||||
|
return;
|
||||||
|
}
|
||||||
uint32_t drawOffset = 0, lastDrawOffset = -1;
|
uint32_t drawOffset = 0, lastDrawOffset = -1;
|
||||||
char cont = 1;
|
char cont = 1;
|
||||||
uint32_t byteCount = 16*24, lastByteCount = 0;
|
uint32_t byteCount = 16*24, lastByteCount = 0;
|
||||||
|
39
kernel.c
39
kernel.c
@ -1,6 +1,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
|
#include "fs.h"
|
||||||
#include "print.h"
|
#include "print.h"
|
||||||
#include "interrupt.h"
|
#include "interrupt.h"
|
||||||
#include "kbd.h"
|
#include "kbd.h"
|
||||||
@ -281,13 +282,17 @@ void ScancodeTest() {
|
|||||||
}
|
}
|
||||||
extern void create_child(uint32_t esp, uint32_t eip, uint32_t argc, ...);
|
extern void create_child(uint32_t esp, uint32_t eip, uint32_t argc, ...);
|
||||||
uint16_t FileSelectScreen[80*25];
|
uint16_t FileSelectScreen[80*25];
|
||||||
|
char ValidFilesystems[256];
|
||||||
void FileSelect() {
|
void FileSelect() {
|
||||||
|
ActiveFilesystemBitmap(ValidFilesystems);
|
||||||
|
uint8_t currentFsId = 0;
|
||||||
char current_path[80];
|
char current_path[80];
|
||||||
uintptr_t current_path_end;
|
uintptr_t current_path_end;
|
||||||
for (int i = 0; i < sizeof(current_path); i++)
|
for (int i = 0; i < sizeof(current_path); i++)
|
||||||
current_path[i] = 0;
|
current_path[i] = 0;
|
||||||
current_path[0] = '/';
|
current_path[0] = '0';
|
||||||
current_path_end = 1;
|
current_path[1] = '/';
|
||||||
|
current_path_end = 2;
|
||||||
fileCount = 5;
|
fileCount = 5;
|
||||||
uint16_t *vga_text = (uint16_t *)FileSelectScreen;
|
uint16_t *vga_text = (uint16_t *)FileSelectScreen;
|
||||||
int32_t fileHovered = 0;
|
int32_t fileHovered = 0;
|
||||||
@ -305,6 +310,8 @@ void FileSelect() {
|
|||||||
vga += 80;
|
vga += 80;
|
||||||
printStr("O to open directory", vga);
|
printStr("O to open directory", vga);
|
||||||
vga += 80;
|
vga += 80;
|
||||||
|
printStr("S to switch volume", vga);
|
||||||
|
vga += 80;
|
||||||
printStr("F4 to run tests", vga);
|
printStr("F4 to run tests", vga);
|
||||||
}
|
}
|
||||||
printStr(current_path, &vga_text[80*4 + 2]);
|
printStr(current_path, &vga_text[80*4 + 2]);
|
||||||
@ -360,7 +367,7 @@ void FileSelect() {
|
|||||||
for (int i = 0; i < DirEntries[fileHovered].namelen; i++)
|
for (int i = 0; i < DirEntries[fileHovered].namelen; i++)
|
||||||
current_path[current_path_end + i] = DirEntries[fileHovered].name[i];
|
current_path[current_path_end + i] = DirEntries[fileHovered].name[i];
|
||||||
current_path[current_path_end + DirEntries[fileHovered].namelen] = 0;
|
current_path[current_path_end + DirEntries[fileHovered].namelen] = 0;
|
||||||
create_child(GetFreeStack(), (uintptr_t)ProgramLoadTest, 2, current_path, &DirEntries[fileHovered]);
|
create_child(GetFreeStack(), (uintptr_t)ProgramLoadTest, 1, current_path);
|
||||||
current_path[current_path_end] = 0;
|
current_path[current_path_end] = 0;
|
||||||
RestoreVGA();
|
RestoreVGA();
|
||||||
reload = 1;
|
reload = 1;
|
||||||
@ -370,7 +377,7 @@ void FileSelect() {
|
|||||||
for (int i = 0; i < DirEntries[fileHovered].namelen; i++)
|
for (int i = 0; i < DirEntries[fileHovered].namelen; i++)
|
||||||
current_path[current_path_end + i] = DirEntries[fileHovered].name[i];
|
current_path[current_path_end + i] = DirEntries[fileHovered].name[i];
|
||||||
current_path[current_path_end + DirEntries[fileHovered].namelen] = 0;
|
current_path[current_path_end + DirEntries[fileHovered].namelen] = 0;
|
||||||
create_child(GetFreeStack(), (uintptr_t)HexEditor, 2, current_path, &DirEntries[fileHovered]);
|
create_child(GetFreeStack(), (uintptr_t)HexEditor, 1, current_path);
|
||||||
current_path[current_path_end] = 0;
|
current_path[current_path_end] = 0;
|
||||||
RestoreVGA();
|
RestoreVGA();
|
||||||
reload = 1;
|
reload = 1;
|
||||||
@ -381,7 +388,7 @@ void FileSelect() {
|
|||||||
for (int i = 0; i < DirEntries[fileHovered].namelen; i++)
|
for (int i = 0; i < DirEntries[fileHovered].namelen; i++)
|
||||||
current_path[current_path_end + i] = DirEntries[fileHovered].name[i];
|
current_path[current_path_end + i] = DirEntries[fileHovered].name[i];
|
||||||
current_path[current_path_end + DirEntries[fileHovered].namelen] = 0;
|
current_path[current_path_end + DirEntries[fileHovered].namelen] = 0;
|
||||||
create_child(GetFreeStack(), (uintptr_t)TextViewTest, 2, current_path, &DirEntries[fileHovered]);
|
create_child(GetFreeStack(), (uintptr_t)TextViewTest, 1, current_path);
|
||||||
current_path[current_path_end] = 0;
|
current_path[current_path_end] = 0;
|
||||||
RestoreVGA();
|
RestoreVGA();
|
||||||
reload = 1;
|
reload = 1;
|
||||||
@ -419,6 +426,25 @@ void FileSelect() {
|
|||||||
fileOffset = 0;
|
fileOffset = 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case KEY_S:
|
||||||
|
// Next filesystem TODO Support over 077 I'm so lazy right now
|
||||||
|
for (currentFsId = (currentFsId + 1) % 64; !ValidFilesystems[currentFsId]; currentFsId = (currentFsId + 1) % 64);
|
||||||
|
if (currentFsId < 8) {
|
||||||
|
current_path[0] = '0' + currentFsId;
|
||||||
|
current_path[1] = '/';
|
||||||
|
current_path[2] = 0;
|
||||||
|
current_path_end = 2;
|
||||||
|
} else {
|
||||||
|
current_path[0] = '0' + (currentFsId >> 3);
|
||||||
|
current_path[1] = '0' + (currentFsId & 7);
|
||||||
|
current_path[2] = '/';
|
||||||
|
current_path[3] = 0;
|
||||||
|
current_path_end = 3;
|
||||||
|
}
|
||||||
|
reload = 1;
|
||||||
|
fileHovered = 0;
|
||||||
|
fileOffset = 0;
|
||||||
|
break;
|
||||||
case KEY_F6:
|
case KEY_F6:
|
||||||
ScancodeTest();
|
ScancodeTest();
|
||||||
reload = 1;
|
reload = 1;
|
||||||
@ -430,6 +456,7 @@ void FileSelect() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int MakeSystemVolume(uint8_t sysPartition);
|
int MakeSystemVolume(uint8_t sysPartition);
|
||||||
|
void MakeMBRPartitions();
|
||||||
void SystemRun(uint8_t sysPartition) {
|
void SystemRun(uint8_t sysPartition) {
|
||||||
uint16_t *vga_text = (word *)0xb8000;
|
uint16_t *vga_text = (word *)0xb8000;
|
||||||
RestoreVGA();
|
RestoreVGA();
|
||||||
@ -439,7 +466,6 @@ void SystemRun(uint8_t sysPartition) {
|
|||||||
|
|
||||||
// Check for FAT partition
|
// Check for FAT partition
|
||||||
{
|
{
|
||||||
// TODO Check partitions beyond 0
|
|
||||||
while (1) {
|
while (1) {
|
||||||
create_child(GetFreeStack(), (uintptr_t)MakeSystemVolume, 1, sysPartition);
|
create_child(GetFreeStack(), (uintptr_t)MakeSystemVolume, 1, sysPartition);
|
||||||
if (!check_error_code()) break;
|
if (!check_error_code()) break;
|
||||||
@ -449,6 +475,7 @@ void SystemRun(uint8_t sysPartition) {
|
|||||||
vga_text += printStr("Press R to retry.", vga_text);
|
vga_text += printStr("Press R to retry.", vga_text);
|
||||||
for (;(get_scancode() & 0xff) != KEY_R;);
|
for (;(get_scancode() & 0xff) != KEY_R;);
|
||||||
}
|
}
|
||||||
|
create_child(GetFreeStack(), (uintptr_t)MakeMBRPartitions, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
19
progs.c
19
progs.c
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
extern char _USERMODE, _USERMODE_END;
|
extern char _USERMODE, _USERMODE_END;
|
||||||
extern uint32_t create_user_child(uint32_t esp, uint32_t eip, uint32_t argc, ...);
|
extern uint32_t create_user_child(uint32_t esp, uint32_t eip, uint32_t argc, ...);
|
||||||
void ProgramLoadTest(char *path, dirent *de) {
|
void ProgramLoadTest(char *path) {
|
||||||
uint16_t *vga_text = (uint16_t *)0xb8000;
|
uint16_t *vga_text = (uint16_t *)0xb8000;
|
||||||
for (int i = 0; i < 80*25; i++)
|
for (int i = 0; i < 80*25; i++)
|
||||||
vga_text[i] = 0x0f00;
|
vga_text[i] = 0x0f00;
|
||||||
@ -11,7 +11,13 @@ void ProgramLoadTest(char *path, dirent *de) {
|
|||||||
uint8_t *diskReadBuf = (uint8_t *)&_USERMODE;
|
uint8_t *diskReadBuf = (uint8_t *)&_USERMODE;
|
||||||
{
|
{
|
||||||
uint32_t err;
|
uint32_t err;
|
||||||
uint8_t *scratch = (uint8_t *)0x20000;
|
dirent de;
|
||||||
|
err = path_getinfo(path, &de);
|
||||||
|
if (de.size > 0x300000 || err) {
|
||||||
|
vga_text += printStr("File too large or error.", vga_text);
|
||||||
|
kbd_wait();
|
||||||
|
return;
|
||||||
|
}
|
||||||
FILE file;
|
FILE file;
|
||||||
err = file_open(&file, path, OPENREAD);
|
err = file_open(&file, path, OPENREAD);
|
||||||
if (err) {
|
if (err) {
|
||||||
@ -19,18 +25,13 @@ void ProgramLoadTest(char *path, dirent *de) {
|
|||||||
printDword(err, vga_text);
|
printDword(err, vga_text);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (de->size > 0x300000) {
|
|
||||||
vga_text += printStr("File too large.", vga_text);
|
|
||||||
kbd_wait();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
err = file_seek(&file, 0);
|
err = file_seek(&file, 0);
|
||||||
if (err) {
|
if (err) {
|
||||||
vga_text += printStr("Seek Error", vga_text);
|
vga_text += printStr("Seek Error", vga_text);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
err = file_read(&file, diskReadBuf, de->size);
|
successcount = err = file_read(&file, diskReadBuf, de.size);
|
||||||
if (!err && de->size > 0) {
|
if (!err && de.size > 0) {
|
||||||
vga_text += printStr("Read Error", vga_text);
|
vga_text += printStr("Read Error", vga_text);
|
||||||
printDword(err, vga_text);
|
printDword(err, vga_text);
|
||||||
return;
|
return;
|
||||||
|
6
progs.h
6
progs.h
@ -7,6 +7,6 @@
|
|||||||
#include "helper.h"
|
#include "helper.h"
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
|
|
||||||
void HexEditor(char *path, dirent *de);
|
void HexEditor(char *path);
|
||||||
void TextViewTest(char *path, dirent *de);
|
void TextViewTest(char *path);
|
||||||
void ProgramLoadTest(char *path, dirent *de);
|
void ProgramLoadTest(char *path);
|
||||||
|
13
textedit.c
13
textedit.c
@ -12,12 +12,19 @@ uint8_t editedBlocks[TOTALBLOCKS] __attribute__((section(".textbss")));;
|
|||||||
uint8_t fileBuffer[MAXFILESIZE]
|
uint8_t fileBuffer[MAXFILESIZE]
|
||||||
__attribute__((aligned(0x1000)))
|
__attribute__((aligned(0x1000)))
|
||||||
__attribute__((section(".textlatebss")));
|
__attribute__((section(".textlatebss")));
|
||||||
void TextViewTest(char *path, dirent *de) {
|
void TextViewTest(char *path) {
|
||||||
uint16_t *vga_text = (uint16_t *)0xb8000;
|
uint16_t *vga_text = (uint16_t *)0xb8000;
|
||||||
uint32_t fileLen = de->size;
|
uint32_t fileLen;
|
||||||
{
|
{
|
||||||
uint32_t err;
|
uint32_t err;
|
||||||
uint8_t *scratch = (uint8_t *)0x20000;
|
dirent de;
|
||||||
|
err = path_getinfo(path, &de);
|
||||||
|
if (err) {
|
||||||
|
vga_text += printStr("Error getting file info.", vga_text);
|
||||||
|
kbd_wait();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fileLen = de.size;
|
||||||
FILE file;
|
FILE file;
|
||||||
err = file_open(&file, path, OPENREAD);
|
err = file_open(&file, path, OPENREAD);
|
||||||
if (err) {
|
if (err) {
|
||||||
|
Loading…
Reference in New Issue
Block a user