more fs code

This commit is contained in:
'mr software' 2023-10-27 21:54:33 -07:00
parent 2a95f22a7c
commit 39e58e033f
9 changed files with 325 additions and 101 deletions

View File

@ -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

View File

@ -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

View File

@ -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

52
src/mbr.s Normal file
View File

@ -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

View File

@ -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 && \
# mothfs
nasm mfs_hdr.s && \
xxd -i mfs_hdr > inc/mfs_hdr.h && \
$CC mkmothfs.c
$CC mfstool.c -o mfstool

View File

@ -1,3 +1,10 @@
#ifndef MOTHFS_H
#define MOTHFS_H
#include <stdint.h>
#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

View File

@ -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

225
tool/mfstool.c Normal file
View File

@ -0,0 +1,225 @@
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <fs.h> // structs for mothfs
#include <mfs_hdr.h> // 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;
}

View File

@ -1,10 +0,0 @@
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <mfs_hdr.h>
int main(int argc, char** argv) {
if(argc < 100) return !!printf("need arguments: ?\n");
}