From 39e58e033fc4cebf17c931f77134efa56ff03fd2 Mon Sep 17 00:00:00 2001 From: mothcompute Date: Fri, 27 Oct 2023 21:54:33 -0700 Subject: [PATCH] more fs code --- Makefile | 10 +-- config.s | 6 -- src/boot.s | 63 -------------- src/mbr.s | 52 +++++++++++ tool/build | 11 ++- tool/inc/fs.h | 35 +++++--- tool/mfs_hdr.s | 14 ++- tool/mfstool.c | 225 ++++++++++++++++++++++++++++++++++++++++++++++++ tool/mkmothfs.c | 10 --- 9 files changed, 325 insertions(+), 101 deletions(-) delete mode 100644 src/boot.s create mode 100644 src/mbr.s create mode 100644 tool/mfstool.c delete mode 100644 tool/mkmothfs.c diff --git a/Makefile b/Makefile index 19c6245..f903c73 100644 --- a/Makefile +++ b/Makefile @@ -5,21 +5,21 @@ FILES = config.s \ $(wildcard src/int21/*.s) .PHONY: all qemu clean -all: obj/boot.o obj/kernel.o $(TARGET) +all: obj/mbr.o obj/kernel.o $(TARGET) qemu: all qemu-system-i386 -fda $(TARGET) -obj/boot.o: src/boot.s +obj/mbr.o: src/mbr.s @mkdir -p obj - nasm -I. -Isrc src/boot.s -o obj/boot.o + nasm -I. -Isrc src/mbr.s -o obj/mbr.o obj/kernel.o: $(FILES) @mkdir -p obj nasm -I. -Isrc src/kernel.s -o obj/kernel.o -$(TARGET): src/boot.s $(FILES) - cat obj/boot.o obj/kernel.o > $(TARGET) +$(TARGET): src/mbr.s $(FILES) + cat obj/mbr.o obj/kernel.o > $(TARGET) clean: rm -rf obj/ $(TARGET) kernel.map diff --git a/config.s b/config.s index b83f73d..e69de29 100644 --- a/config.s +++ b/config.s @@ -1,6 +0,0 @@ -NUMSEG equ 4; TODO build system should calculate this value - -; might be good to move one of these into the high memory area -KERNEL_SEG equ 0x50 -STACK_SEG equ 0x1050 -BOOTPART equ 0 ; 0-3 diff --git a/src/boot.s b/src/boot.s deleted file mode 100644 index 83de06b..0000000 --- a/src/boot.s +++ /dev/null @@ -1,63 +0,0 @@ -; foxdos boot sector - -%include "config.s" - -[org 0x7C00] -[bits 16] - -mov ax, KERNEL_SEG -push ax ; setup for ds -mov es, ax -mov gs, ax -mov fs, ax - -xor cx, cx -mov ds, cx -mov word [0x21*4], 3 ; see kjmp in kernel.s -mov word [0x21*4+2], ax - -mov ax, 0x200 | NUMSEG -mov cl, ah -xor dh, dh -int 13h - -; 64kb stack -pop ds -mov ax, STACK_SEG -mov ss, ax -xor sp, sp -mov ax, sp -not sp - -; kernel time(?) -push ds -push ax -retf - -; TODO filesystem and reserve space for mbr partition table - -times 446 - ($-$$) db 0 -times BOOTPART*16 db 0 - -; some programs do not accept values with bits 0-6 set -status db 0 - -; chs offset :/ -off_head db 0 -off_sector_cyl db 0 -off_cyl_low db 0 - -; https://en.wikipedia.org/wiki/Partition_type -type db 0 - -; chs... end? -end_head db 0 -end_sector_cyl db 0 -end_cyl_low db 0 - -; lba :) -lba_off dd 0 -lba_len dd 0 - -times 510 - ($-$$) db 0 -dw 0xAA55 diff --git a/src/mbr.s b/src/mbr.s new file mode 100644 index 0000000..21e4318 --- /dev/null +++ b/src/mbr.s @@ -0,0 +1,52 @@ +[org 0x500] +base equ $ + + +mov sp, 0x7C00 +xor ax, ax +push ax +push ax +pop es +pop ds +mov di, 0x500 +mov cx, (dsize&0xFE) +cld +mov si, sp +repnz movsw +jmp 0:entry + +entry: mov bx, 0x7DBE + mov cx, 4 +.disk: mov al, [bx] + shl al, 1 + jc ldvbr + add bx, 16 + dec cl + jnz .disk + int 18h +ldvbr: + ; https://twitter.com/mothcompute/status/1620626616325148672 + ; should be mov dh, [bx+1]. but it is not + mov dx, [bx] + + mov cx, [bx+2] + mov di, 5 +.loop: push di + mov bx, 0x7C00 + mov ax, 0x0201 + int 13h + jnc chkvbr + xor ax, ax + int 13h + pop di + dec di + jnz .loop +err: int 18h +chkvbr: mov bx, 0x7DFE + cmp word [bx], 0xAA55 + jnz err + jmp 0:0x7C00 +dsize equ ($-base)|2 + +times 510 - ($-$$) db 0 +dxr: dw 0xAA55 diff --git a/tool/build b/tool/build index ef269f1..b30adf6 100755 --- a/tool/build +++ b/tool/build @@ -1,9 +1,12 @@ +#!/bin/sh + for i in xxd; do which $i || exit; done CC='cc -O3 -Iinc' -for i in bin2h; do [ ! -f "$i" ] && $CC "$i.c" -o "$i"; done +#for i in bin2h; do [ ! -f "$i" ] && $CC "$i.c" -o "$i"; done -[ ! -f mkmothfs ] && nasm mfs_hdr.s && \ - xxd -i mfs_hdr > inc/mfs_hdr.h && \ - $CC mkmothfs.c +# mothfs +nasm mfs_hdr.s && \ +xxd -i mfs_hdr > inc/mfs_hdr.h && \ +$CC mfstool.c -o mfstool diff --git a/tool/inc/fs.h b/tool/inc/fs.h index 1732188..938f07d 100644 --- a/tool/inc/fs.h +++ b/tool/inc/fs.h @@ -1,3 +1,10 @@ +#ifndef MOTHFS_H +#define MOTHFS_H +#include + +#define MFS_FILE 0 +#define MFS_DIR 1 + typedef struct { uint32_t jmp; // used to jump past the header uint8_t magic[7]; // 'MOTHFS\0' @@ -29,19 +36,21 @@ typedef struct { uint8_t type; // 0 - file // 1 - directory - uint8_t perms[3]; // unused in foxdos. good for alignment. top bit of - // each nibble must be zero - - uint32_t ext; // undefined in version 0 - contains uid, gid, data - // for other file types, long filename, etc - - uint8_t name[8]; // filename - uint8_t ext[3]; // extension - uint8_t lfn; // size of long filename - must be zero in version 0 - // this is on par with most filesystems - + uint8_t pad; // keep 2-byte alignment uint16_t freebytes; // number of bytes unused in last sector of file data - uint16_t pad; + + uint32_t dir; // pointer to parent directory + + uint32_t ext; // undefined in version 0 - contains pointer to uid, gid, + // data for other file types, long filename, linux caps, + // unix permissions, etc. if missing, must be zero + + // both of these values are zero padded + uint8_t name[8]; // filename + uint8_t fxt[3]; // extension + + uint8_t lfn; // size of long filename - should be zero in version 0 + // max length of 255 is on par with most filesystems uint32_t data[122]; @@ -56,3 +65,5 @@ typedef struct { // sector containing 128 more sector offsets. the rules for this are similar // enough to how files work that i do not want to write it out again } mothfs_file; // 512 bytes + +#endif diff --git a/tool/mfs_hdr.s b/tool/mfs_hdr.s index 7ed9c21..a5285e3 100644 --- a/tool/mfs_hdr.s +++ b/tool/mfs_hdr.s @@ -6,6 +6,7 @@ jmp entry times 4 - ($-$$) db 0 +; 16mb shown as example db "MOTHFS",0 db 0 sz: dd 32768 ; 32768 * 512 = 16mb disk image @@ -15,8 +16,19 @@ rsv: db 127 ; 64kb of boot code abm: dd 4096 ; 16mb/(512*8) entry: - push cs + + xor ax, ax + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov ss, ax + mov sp, 0x7BFE ; 30kb stack until 0x500 + mov bp, sp + push ax pop ds + + mov dx, 0x80 ; change disk number to 80 because every bios is the worst push dx ; enable a20 a few different ways diff --git a/tool/mfstool.c b/tool/mfstool.c new file mode 100644 index 0000000..06805c7 --- /dev/null +++ b/tool/mfstool.c @@ -0,0 +1,225 @@ +#include +#include +#include +#include +#include +#include + +#include // structs for mothfs +#include // bootcode + +#define setbit(x, y) x[y >> 3] |= 1 << (y & 7) + +#define NUM_MULTICALL 1 + +typedef struct { + char* name; + int (*fn)(int, char**); +} multicall; + +int pstrlen(char* d, char* typ) { + int i = 0; + while((d[i] ^ '/') && d[i] != 0) i++; // slash or null terminated + *typ = d[i] ? 1 : 0; + return i; +} + +char** psplit(char* path, int* i) { + int l, a = 8; + char** rpth = malloc(sizeof(char*)*a); + *i = 0; + char x = 1, dir = 0; + + if(*path == '/') { + rpth[(*i)++] = memcpy(malloc(2), "/", 2); + path++; + } + + if(path[strlen(path) - 1] == '/') dir = 1; + + while(1) { + while(*path == '/') path++; + l = pstrlen(path, &x); + rpth[*i] = memcpy(malloc(l + 1), path, l); + rpth[(*i)++][l] = 0; + path += l + x; // prevent buffer overrun + if(!x) break; + if(*i >= a) rpth = realloc(rpth, sizeof(char*)*(a += 4)); + } + + if(dir) { + if(*i + 1 >= a) rpth = realloc(rpth, sizeof(char*)*(a += 4)); + rpth[(*i)++] = memcpy(malloc(2), "/", 2); + } + + return rpth; +} + +int xstrlen(char* s) { + int i = strlen(s) - 1; + for(;s[i] != '.' && i; i--); + return i; +} + +// s: passed path +// d: path in fs to check against +// TODO does this even work +int nmatch(char* s, char* d) { + int x = xstrlen(s); + for(int i = 0; i < (x > 8 ? 8 : x); i++) { + if( + (s[i] & ((s[i] >= 'a' && s[i] <= 'z') ? 0xDF: 0xFF)) != d[i] + ) return 0; + } + s = s + x + 1; + x = strlen(s); + for(int i = 0; i < (x > 3 ? 3 : x); i++) { + if( + (s[i] & ((s[i] >= 'a' && s[i] <= 'z') ? 0xDF: 0xFF)) != d[i] + ) return 0; + } +} + +// returns sector of file or directory +uint32_t mfs_traverse(int fd, uint32_t from, char* name) { + uint64_t r = 0; // sector to return? + mothfs_file d, next; + int sz; + char** rpth = psplit(name, &sz); + + int i = 0; + + if(!strcmp(*rpth, "/")) { + lseek(fd, 0, SEEK_SET); + read(fd, &d, 512); + mothfs_header* e = &d; + from = e->reserved + e->abm + 1; + i++; + } + + for(; i < sz; i++) { // TODO . and .. + lseek(fd, ((uint64_t)from) << 9, SEEK_SET); + read(fd, &d, 512); + switch(d.type) { + case 0: // file + r = strcmp(rpth[sz - 1], "/") ? from : 0; + if(sz - !strcmp(rpth[sz - 1], "/") - 1 != i) r = 0; // TODO does this line even work + goto ret; + break; + case 1: + uint32_t* sp = d.data + 121; + for(int c = 0; c < 121; c++) { + if(!d.data[c]) { + r = 0; + goto ret; + } + lseek(fd, ((uint64_t)d.data[c]) << 9, SEEK_SET); + read(fd, &next, 512); + if(nmatch(next.name, rpth[i])) { + from = d.data[c]; + // TODO set r if last element + break; + } + } // else check linked sector + uint32_t* ns = malloc(512); // TODO ns is never freed + cls: lseek(fd, ((uint64_t)(*sp)) << 9, SEEK_SET); + read(fd, ns, 512); + for(int c = 0; c < 127; c++) { + if(!ns[c]) { + r = 0; + goto ret; + } + lseek(fd, ((uint64_t)d.data[c]) << 9, SEEK_SET); + read(fd, &next, 512); + if(nmatch(next.name, rpth[i])) { + from = d.data[c]; + // TODO set r if last element + break; + } + } // else go to next linked sector + sp = ns + 127; + goto cls; + break; + } + } + +ret: for(; i < sz; i++) free(rpth[i]); + free(rpth); + return r; +} + +#define LFIL argv[1] +#define SIZE argv[2] +#define SKIP argv[3] + +int mfs_new(int argc, char** argv) { + if(argc < 4) return !!printf("need arguments: [file] [size] [sector offset]\n"); + int fd; + if((fd = open(LFIL, O_RDWR|O_CREAT, 0644)) < 0) return !!printf("could not open %s\n", LFIL); + uint64_t sz = atol(SIZE); + sz = (sz + ((sz & 0x1FF) ? 512 : 0)) >> 9; // round up to number of sectors + uint64_t skip = atol(SKIP); + ftruncate(fd, sz << 9); + + mothfs_header* header = (mothfs_header*)mfs_hdr; + header->size = sz; + header->offset = skip; + header->reserved = 127; + + // currently uses 1/8 of the partition but that isnt too bad for now + header->abm = (sz + ((sz & 7) ? 8 : 0)) >> 3; + + write(fd, header, 512); // write bootloader + + // start writing initial abm + lseek(fd, 512*(header->reserved + 1), SEEK_SET); + + // volume name + memcpy(header->volname, "mothfs\0????????", 15); // this will look really funny if parsed wrong + + // reserve the boot sector, bootcode area, and abm + uint8_t* rsv = malloc(header->abm << 9); + memset(rsv, 0, header->abm << 9); + for(unsigned long i = 0; i < 1 + header->reserved + header->abm; i++) setbit(rsv, i); + write(fd, rsv, header->abm << 9); + free(rsv); + + mothfs_file root; + memset(&root, 0, sizeof(mothfs_file)); + + root.type = MFS_DIR; + root.ext = 0; + *root.data = 0; // no files yet - that is the user's job + + // set root to itself + root.dir = ((uint64_t)lseek(fd, 0, SEEK_CUR)) >> 9; + + write(fd, &root, 512); +} + +int mfs_insert(int argc, char** argv) { + if(argc < 3) return !!printf("need arguments: [mothfs file] [file to insert]\n"); +} + +multicall mc[NUM_MULTICALL] = { + {"new", mfs_new}, +// {"insert", mfs_insert}, +}; + +int main(int argc, char** argv) { + + int y; + char** x = psplit("//doc/toc////foc//", &y); + + printf("%i\n", y); + for(int i = 0; i < y; i++) printf("%s\n", x[i]); + + if(argc < 2) err: { + printf("valid functions:"); + for(int i = 0; i < NUM_MULTICALL; i++) printf(" %s%c", mc[i].name, ((NUM_MULTICALL - i) ^ 1) ? ',' : '\n'); + return 1; + } + for(int i = 0; i < NUM_MULTICALL; i++) if(!strcmp(argv[1], mc[i].name)) return mc[i].fn(argc - 1, argv + 1); + goto err; +} + diff --git a/tool/mkmothfs.c b/tool/mkmothfs.c deleted file mode 100644 index f705a2f..0000000 --- a/tool/mkmothfs.c +++ /dev/null @@ -1,10 +0,0 @@ -#include -#include -#include - -#include - -int main(int argc, char** argv) { - if(argc < 100) return !!printf("need arguments: ?\n"); - -}