diff --git a/file.c b/file.c index ae511b7..ec40bdc 100644 --- a/file.c +++ b/file.c @@ -1,78 +1,113 @@ #include "file.h" #include "fs.h" -#define MAXFS (0x20000/sizeof(filesystem)) -filesystem (*const FilesystemTable)[MAXFS] = (filesystem (* const)[MAXFS])0x240000; - // TODO Replace with something better 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 int file_open(FILE *file, char *path, char mode) { - filesystem *fs = &(*FilesystemTable)[0]; - return fs->ops.file_open(fs->fs_data, file, path, mode); + char *adj_path; + 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. 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); } // Returns 0 on error, bytes read on success. 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); } // Returns 0 on error, bytes written on success. 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); } void file_close(FILE *file) { - filesystem *fs = &(*FilesystemTable)[0]; + filesystem *fs = GetFilesystem(file->filesystem_id); return fs->ops.file_close(fs->fs_data, file); } // Returns 0 on success, non-zero error code on error. Fills provided struct DIR int dir_open(DIR *dir, char *path) { - filesystem *fs = &(*FilesystemTable)[0]; - return fs->ops.dir_open(fs->fs_data, dir, path); + char *adj_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. 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); } void dir_close(DIR *dir) { - filesystem *fs = &(*FilesystemTable)[0]; + filesystem *fs = GetFilesystem(dir->filesystem_id); return fs->ops.dir_close(fs->fs_data, dir); } // Returns 0 on success, non-zero error code on error. Fills provided struct dirent. int path_getinfo(char *path, dirent *ent) { - filesystem *fs = &(*FilesystemTable)[0]; - return fs->ops.path_getinfo(fs->fs_data, path, ent); + char *adj_path; + 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. int path_mkdir(char *path) { - filesystem *fs = &(*FilesystemTable)[0]; - return fs->ops.path_mkdir(fs->fs_data, path); + char *adj_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. int path_rmdir(char *path) { - filesystem *fs = &(*FilesystemTable)[0]; - return fs->ops.path_rmdir(fs->fs_data, path); + char *adj_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. int path_rmfile(char *path) { - filesystem *fs = &(*FilesystemTable)[0]; - return fs->ops.path_rmfile(fs->fs_data, path); + char *adj_path; + filesystem *fs = GetFilesystem(GetFsFromPath(path, &adj_path)); + return fs->ops.path_rmfile(fs->fs_data, adj_path); } diff --git a/fs.c b/fs.c index 731b7e6..facf22d 100644 --- a/fs.c +++ b/fs.c @@ -1,15 +1,16 @@ #include "fs.h" +#include "disk.h" struct FsType { uint32_t type_id; - int (*init_func)(filesystem *, char); + int (*init_func)(filesystem *, uint32_t); // Not yet decided - char (*detect_func)(); + char (*detect_func)(uint32_t); }; // TODO Get these dynamically somehow -int InitDosFs(filesystem *fs, char partition); -char DetectDosPart(); +int InitDosFs(filesystem *fs, uint32_t start_sector); +char DetectDosPart(uint32_t start_sector); struct FsType SupportedFilesystems[] = { { @@ -19,18 +20,111 @@ struct FsType SupportedFilesystems[] = { } }; -#define MAXFS (0x20000/sizeof(filesystem)) -filesystem (*const ActiveFilesystems)[MAXFS] = (filesystem (* const)[MAXFS])0x240000; +#define MAXFS 255 +filesystem *ActiveFilesystems = (filesystem *)0x240000; -// TODO Replace with something better -uint8_t ActiveFsId; +uint8_t ActiveFsIdx; -// TODO Make functions and just use those instead -int MakeSystemVolume(uint8_t sysPartition) { - filesystem *sys = &(*ActiveFilesystems)[0]; - SupportedFilesystems[0].init_func(sys, sysPartition); - sys->type = SupportedFilesystems[0].type_id; - sys->id = 0; - ActiveFsId = 0; - return 0; +filesystem *GetFilesystem(uint8_t idx) { + if (idx >= MAXFS) return 0; + filesystem *fs = &ActiveFilesystems[idx]; + return fs->type != 0 ? fs : 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; + } + + // Init Failed + return -1; } diff --git a/fs.h b/fs.h index 17a6e20..062cbf7 100644 --- a/fs.h +++ b/fs.h @@ -3,9 +3,7 @@ #include "file_s.h" typedef struct filesystem { - uint8_t id; - uint8_t resv0; - uint16_t resv1; + uint32_t resv0; uint32_t type; struct fs_operations { int (*file_open)(uint8_t *, FILE *, char *, char); @@ -24,5 +22,11 @@ typedef struct filesystem { } ops; uint8_t labellen; char label[255]; - uint8_t fs_data[512-4-4-44-256]; + uint8_t fs_data[2048-4-4-44-256]; } __attribute__((packed)) filesystem; + +filesystem *GetFilesystem(uint8_t idx); +filesystem *GetActiveFilesystem(); +uint8_t GetActiveFilesystemId(); +filesystem *SetActiveFilesystem(uint8_t idx); +void ActiveFilesystemBitmap(char *bitmap); diff --git a/fs_dos.c b/fs_dos.c index 5dde8b1..a57e7dd 100644 --- a/fs_dos.c +++ b/fs_dos.c @@ -2,6 +2,10 @@ #include "fs.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 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; } +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) { fsdat *fs = (fsdat *)dat; 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) { fsdat *fs = (fsdat *)dat; - uint8_t *scratch = (uint8_t *)0x20000; DIRENT de; for (;;) { 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 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) { fsdat *fs = (fsdat *)dat; 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; } @@ -152,20 +192,27 @@ int dos_path_rmfile(uint8_t *dat, char *path) { // DOSFS doesn't have anything to clean up void dos_endfs(uint8_t *dat) { return; } -// Not yet decided -char DetectDosPart() { +// Try to detect if partition is a valid DOS partition +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; } -int InitDosFs(filesystem *fs, char partition) { +int InitDosFs(filesystem *fs, uint32_t start_sector) { 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; - if (DFS_GetVolInfo(0, diskReadBuf, pstart, (VOLINFO *)fs->fs_data)) { + if (DFS_GetVolInfo(0, diskReadBuf, start_sector, (VOLINFO *)fs->fs_data)) { return -1; } diff --git a/hexedit.c b/hexedit.c index ae6d0b3..6742156 100644 --- a/hexedit.c +++ b/hexedit.c @@ -12,30 +12,28 @@ uint32_t blockLenMap[TOTALBLOCKS] __attribute__((section(".hexbss")));; // so that it can be expanded without telling C how much // it actually needs uint8_t writeStoreBase[BLOCKSIZE] __attribute__((section(".hexlatebss"))); -void HexEditor(char *path, dirent *de) { +void HexEditor(char *path) { uint32_t err; uint16_t *vga_text = (uint16_t *)0xb8000; uint32_t screenSize = 80*25; - uint8_t *scratch = (uint8_t *)0x20000; uint8_t (*writeStore)[BLOCKSIZE] = &writeStoreBase; - uint32_t filelen = de->size; for (int i = 0; i < TOTALBLOCKS; i++) writtenMap[i] = 0; uint8_t *screenBuff = *writeStore; // First two blocks are screen buffer uint32_t nextFreeBlock = 2; - FILE file; vga_text = (uint16_t *)0xb8000; for (int i = 0; i < 80*50; i++) vga_text[i] = 0x0f00; - err = file_open(&file, path, OPENREAD|OPENWRITE); + dirent de; + err = path_getinfo(path, &de); if (err) { - vga_text += printStr("Open Error: ", vga_text); - printDword(err, vga_text); + vga_text += printStr("Error getting file info.", vga_text); kbd_wait(); return; } + uint32_t filelen = de.size; if (filelen == 0) { vga_text += printStr("File ", vga_text); vga_text += printStr((char*)path, vga_text); @@ -50,6 +48,14 @@ void HexEditor(char *path, dirent *de) { kbd_wait(); 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; char cont = 1; uint32_t byteCount = 16*24, lastByteCount = 0; diff --git a/kernel.c b/kernel.c index 8fe20f1..91d9842 100644 --- a/kernel.c +++ b/kernel.c @@ -1,6 +1,7 @@ #include #include "file.h" +#include "fs.h" #include "print.h" #include "interrupt.h" #include "kbd.h" @@ -281,13 +282,17 @@ void ScancodeTest() { } extern void create_child(uint32_t esp, uint32_t eip, uint32_t argc, ...); uint16_t FileSelectScreen[80*25]; +char ValidFilesystems[256]; void FileSelect() { + ActiveFilesystemBitmap(ValidFilesystems); + uint8_t currentFsId = 0; char current_path[80]; uintptr_t current_path_end; for (int i = 0; i < sizeof(current_path); i++) current_path[i] = 0; - current_path[0] = '/'; - current_path_end = 1; + current_path[0] = '0'; + current_path[1] = '/'; + current_path_end = 2; fileCount = 5; uint16_t *vga_text = (uint16_t *)FileSelectScreen; int32_t fileHovered = 0; @@ -305,6 +310,8 @@ void FileSelect() { vga += 80; printStr("O to open directory", vga); vga += 80; + printStr("S to switch volume", vga); + vga += 80; printStr("F4 to run tests", vga); } printStr(current_path, &vga_text[80*4 + 2]); @@ -360,7 +367,7 @@ void FileSelect() { for (int i = 0; i < DirEntries[fileHovered].namelen; i++) current_path[current_path_end + i] = DirEntries[fileHovered].name[i]; 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; RestoreVGA(); reload = 1; @@ -370,7 +377,7 @@ void FileSelect() { for (int i = 0; i < DirEntries[fileHovered].namelen; i++) current_path[current_path_end + i] = DirEntries[fileHovered].name[i]; 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; RestoreVGA(); reload = 1; @@ -381,7 +388,7 @@ void FileSelect() { for (int i = 0; i < DirEntries[fileHovered].namelen; i++) current_path[current_path_end + i] = DirEntries[fileHovered].name[i]; 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; RestoreVGA(); reload = 1; @@ -419,6 +426,25 @@ void FileSelect() { fileOffset = 0; } 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: ScancodeTest(); reload = 1; @@ -430,6 +456,7 @@ void FileSelect() { } int MakeSystemVolume(uint8_t sysPartition); +void MakeMBRPartitions(); void SystemRun(uint8_t sysPartition) { uint16_t *vga_text = (word *)0xb8000; RestoreVGA(); @@ -439,7 +466,6 @@ void SystemRun(uint8_t sysPartition) { // Check for FAT partition { - // TODO Check partitions beyond 0 while (1) { create_child(GetFreeStack(), (uintptr_t)MakeSystemVolume, 1, sysPartition); if (!check_error_code()) break; @@ -449,6 +475,7 @@ void SystemRun(uint8_t sysPartition) { vga_text += printStr("Press R to retry.", vga_text); for (;(get_scancode() & 0xff) != KEY_R;); } + create_child(GetFreeStack(), (uintptr_t)MakeMBRPartitions, 0); } for (;;) { diff --git a/progs.c b/progs.c index cbbebbd..cc93a10 100644 --- a/progs.c +++ b/progs.c @@ -3,7 +3,7 @@ extern char _USERMODE, _USERMODE_END; 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; for (int i = 0; i < 80*25; i++) vga_text[i] = 0x0f00; @@ -11,7 +11,13 @@ void ProgramLoadTest(char *path, dirent *de) { uint8_t *diskReadBuf = (uint8_t *)&_USERMODE; { 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; err = file_open(&file, path, OPENREAD); if (err) { @@ -19,18 +25,13 @@ void ProgramLoadTest(char *path, dirent *de) { printDword(err, vga_text); return; } - if (de->size > 0x300000) { - vga_text += printStr("File too large.", vga_text); - kbd_wait(); - return; - } err = file_seek(&file, 0); if (err) { vga_text += printStr("Seek Error", vga_text); return; } - err = file_read(&file, diskReadBuf, de->size); - if (!err && de->size > 0) { + successcount = err = file_read(&file, diskReadBuf, de.size); + if (!err && de.size > 0) { vga_text += printStr("Read Error", vga_text); printDword(err, vga_text); return; diff --git a/progs.h b/progs.h index fabfd71..c0a8a2f 100644 --- a/progs.h +++ b/progs.h @@ -7,6 +7,6 @@ #include "helper.h" #include "file.h" -void HexEditor(char *path, dirent *de); -void TextViewTest(char *path, dirent *de); -void ProgramLoadTest(char *path, dirent *de); +void HexEditor(char *path); +void TextViewTest(char *path); +void ProgramLoadTest(char *path); diff --git a/textedit.c b/textedit.c index 0e1308f..4cf0df0 100644 --- a/textedit.c +++ b/textedit.c @@ -12,12 +12,19 @@ uint8_t editedBlocks[TOTALBLOCKS] __attribute__((section(".textbss")));; uint8_t fileBuffer[MAXFILESIZE] __attribute__((aligned(0x1000))) __attribute__((section(".textlatebss"))); -void TextViewTest(char *path, dirent *de) { +void TextViewTest(char *path) { uint16_t *vga_text = (uint16_t *)0xb8000; - uint32_t fileLen = de->size; + uint32_t fileLen; { 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; err = file_open(&file, path, OPENREAD); if (err) {