feat(mkfs.stpd): make filesystem bootable (WIP)

This commit is contained in:
d0p1 🏳️‍⚧️ 2024-07-25 08:46:56 +00:00
parent a98288b28c
commit edbd42fdf4
5 changed files with 165 additions and 4 deletions

View file

@ -13,6 +13,10 @@ AM_PROG_AR
AC_PROG_INSTALL AC_PROG_INSTALL
AC_PROG_RANLIB AC_PROG_RANLIB
AM_PROG_CC_C_O AM_PROG_CC_C_O
AC_CHECK_PROG([NASM], [nasm], [nasm])
AS_IF([test -z "$NASM"], [
AC_MSG_ERROR([nasm is required])
])
AC_CONFIG_HEADERS([config.h]) AC_CONFIG_HEADERS([config.h])

View file

@ -1,2 +1,2 @@
noinst_LIBRARIES = libstpdfs.a noinst_LIBRARIES = libstpdfs.a
liblzp_a_SOURCES = super.c bio.c inode.c file.c dir.c libstpdfs_a_SOURCES = super.c bio.c inode.c file.c dir.c

View file

@ -4,7 +4,16 @@ LDADD = ../lib/libstpdfs.a
bin_PROGRAMS = mkfs.stpd tools.stpd bin_PROGRAMS = mkfs.stpd tools.stpd
mkfs_stpd_SOURCES = mkfs/main.c mkfs_stpd_SOURCES = mkfs/main.c
mkfs_stpd_LDADD = ../lib/libstpdfs.a mkfs/bootsector.o
tools_stpd_SOURCES = tools/main.c tools_stpd_SOURCES = tools/main.c
man_MANS = mkfs/mkfs.stpd.8 tools/tools.stpd.8 mkfs/boot.o: mkfs/boot.asm
$(NASM) -fbin -o $@ $<
mkfs/bootsector.o: mkfs/boot.o
ld -r -b binary -o $@ $<
man_MANS = mkfs/mkfs.stpd.8 tools/tools.stpd.8
CLEANFILES = mkfs/boot.o mkfs/bootsector.o

134
tools/mkfs/boot.asm Normal file
View file

@ -0,0 +1,134 @@
[BITS 16]
[ORG 0x7c00]
LOADER_BASE equ 0x1000
DISK_BUFFER equ 0x8000
STPDFS_MAGIC equ 0x44505453
INODE_SIZE equ 34
INODE_ALLOCATED equ (1<<15)
struc inode
.mode: resb 1
.nlink: resb 1
.uid: resb 1
.gid: resb 1
.flags: resb 1
.size: resd 1
.zones: resd 10
.actime: resq 1
.modtime: resq 1
endstruc
jmp start
nop
bpb:
db 0, 0, 0
.oem_id: db "STUPIDFS"
.sector_size: dw 512
.sects_per_cluster: db 0
.reserved_sects: dw 0
.fat_count: db 0
.root_dir_entries: dw 0
.sector_count: dw 0
.media_type: db 0
.sects_per_fat: dw 0
.sects_per_track: dw 18
.head_count: dw 2
.hidden_sects: dd 0
.sector_count_big: dd 0
.drive_num: db 0
.reserved: db 0
.signature: db 0
.volume_id: dd 0
.volume_label: db "STPD.MKFS "
.filesystem_type: times 8 db 0
start:
cli
cld
jmp 0x0:.canonicalize_cs
.canonicalize_cs:
xor ax, ax
mov ds, ax
mov ss, ax
mov es, ax
mov sp, 0x7c00
mov [bpb.drive_num], dl
; ensure lba mode is supported
mov ah, 0x41
mov bx, 0x55AA
int 0x13
jc .err_lba
; reset disk
.reset_disk:
mov dl, [bpb.drive_num]
xor ah, ah
int 0x13
jc .reset_disk
; read superblock
mov ax, DISK_BUFFER/10
mov es, ax
; load two sector in memory
; superblock and first inodes
mov eax, 1
mov cx, 2
xor bx, bx
call disk_read_sectors
mov dword eax, [DISK_BUFFER]
cmp eax, STPDFS_MAGIC
jne .err_magic
; inode 0 bad
; inode 1 root dir
; inode 2 is loader, let's keep things easy
mov ax, word [DISK_BUFFER + 34 * 2 + inode.flags]
and ax, INODE_ALLOCATED
jz .err_no_loader
mov dword eax, [DISK_BUFFER + 34 * 2 + inode.size] ; size
mov eax, DISK_BUFFER + 34 * 2 + 14 ; first zone
jmp 0x0:LOADER_BASE
.err_no_loader:
.err_magic:
.err_lba:
hlt
jmp $
disk_read_sectors:
mov word [disk_packet.sectors], cx
mov word [disk_packet.segment], es
mov word [disk_packet.offset], bx
mov dword [disk_packet.lba], eax
mov ds, [disk_packet]
mov dl, [bpb.drive_num]
mov ah, 0x42
int 0x13
ret
disk_packet:
db 0x10
db 0
.sectors:
dw 0
.segment:
dw 0
.offset:
dw 0
.lba:
dd 0
dd 0
times 510-($-$$) db 0
dw 0xAA55

View file

@ -23,12 +23,17 @@ static const char *prg_name;
static int inodes = -1; static int inodes = -1;
static const char *device; static const char *device;
static int blocks = -1; static int blocks = -1;
static int bootable = 0;
static struct stpdfs_sb super; static struct stpdfs_sb super;
extern const char _binary_mkfs_boot_o_start[];
extern const char _binary_mkfs_boot_o_end[];
#ifdef HAVE_STRUCT_OPTION #ifdef HAVE_STRUCT_OPTION
static struct option long_options[] = { static struct option long_options[] = {
{"help", no_argument, 0, 'h'}, {"help", no_argument, 0, 'h'},
{"version", no_argument, 0, 'V'}, {"version", no_argument, 0, 'V'},
{"boot", no_argument, 0, 'b'},
{"inodes", required_argument, 0, 'i'}, {"inodes", required_argument, 0, 'i'},
{0, 0, 0, 0} {0, 0, 0, 0}
}; };
@ -45,6 +50,7 @@ usage(int retval)
{ {
printf("Usage: %s [options] /dev/name [blocks]\n\n", prg_name); printf("Usage: %s [options] /dev/name [blocks]\n\n", prg_name);
printf("Options:\n"); printf("Options:\n");
printf(" -b, --boot make filesystem bootable\n");
printf(" -i, --inode <num> number of inodes for the filesystem\n"); printf(" -i, --inode <num> number of inodes for the filesystem\n");
printf(" -h, --help display this help\n"); printf(" -h, --help display this help\n");
printf(" -V, --version display version\n\n"); printf(" -V, --version display version\n\n");
@ -168,6 +174,11 @@ mkfs()
super.state = STPDFS_CLEANLY_UNMOUNTED; super.state = STPDFS_CLEANLY_UNMOUNTED;
stpdfs_write(fd, 1, &super, sizeof(struct stpdfs_sb)); stpdfs_write(fd, 1, &super, sizeof(struct stpdfs_sb));
if (bootable)
{
stpdfs_write(fd, 0, (void *)_binary_mkfs_boot_o_start, STPDFS_BLOCK_SIZE);
}
/* we finished \o/ */ /* we finished \o/ */
printf("StupidFS: %u blocks (%u Inodes)\n", super.fsize, super.isize); printf("StupidFS: %u blocks (%u Inodes)\n", super.fsize, super.isize);
@ -189,9 +200,9 @@ main(int argc, char **argv)
#endif /* HAVE_LIBGEN_H */ #endif /* HAVE_LIBGEN_H */
#if defined(HAVE_GETOPT_LONG) && defined(HAVE_STRUCT_OPTION) #if defined(HAVE_GETOPT_LONG) && defined(HAVE_STRUCT_OPTION)
while ((c = getopt_long(argc, argv, "hVi:", long_options, &idx)) != EOF) while ((c = getopt_long(argc, argv, "hVbi:", long_options, &idx)) != EOF)
#else #else
while ((c = getopt(argc, argv, "hVi:")) != EOF) while ((c = getopt(argc, argv, "hVbi:")) != EOF)
#endif /* HAVE_GETOPT_LONG && HAVE_STRUCT_OPTION */ #endif /* HAVE_GETOPT_LONG && HAVE_STRUCT_OPTION */
{ {
switch (c) switch (c)
@ -202,6 +213,9 @@ main(int argc, char **argv)
case 'V': case 'V':
version(); version();
break; break;
case 'b':
bootable = 1;
break;
case 'i': case 'i':
inodes = atoi(optarg); inodes = atoi(optarg);
break; break;