more fs code
This commit is contained in:
parent
2a95f22a7c
commit
39e58e033f
10
Makefile
10
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
|
||||
|
|
6
config.s
6
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
|
63
src/boot.s
63
src/boot.s
|
@ -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
|
|
@ -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
|
11
tool/build
11
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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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");
|
||||
|
||||
}
|
Loading…
Reference in New Issue