aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarvin Borner2019-11-20 22:17:48 +0100
committerMarvin Borner2019-11-20 22:28:30 +0100
commit0ba991750314310a5e53b0d8135aef5b1352b261 (patch)
treeacae7106a24b85116cd7119bd239c3d9299f2ba8
parent6ca5f1bcec7f0716bad5e1cdd38d41be137fe7e5 (diff)
Began two-stage hdd bootloader and os installer
-rw-r--r--Makefile17
-rw-r--r--src/bootloader/cd.asm (renamed from src/bootloader/loader.asm)3
-rw-r--r--src/bootloader/grub.cfg7
-rw-r--r--src/bootloader/hdd1.asm118
-rw-r--r--src/bootloader/hdd2.asm388
-rw-r--r--src/bootloader/make_initrd.c53
-rw-r--r--src/kernel/boot.asm2
-rw-r--r--src/kernel/fs/ata_pio.c125
-rw-r--r--src/kernel/fs/ata_pio.h31
-rw-r--r--src/kernel/fs/atapi_pio.c32
-rw-r--r--src/kernel/fs/atapi_pio.h26
-rw-r--r--src/kernel/fs/initrd.c131
-rw-r--r--src/kernel/fs/initrd.h22
-rw-r--r--src/kernel/fs/install.c61
-rw-r--r--src/kernel/fs/install.h6
-rw-r--r--src/kernel/fs/iso9660/iso9660.c60
-rw-r--r--src/kernel/fs/iso9660/iso9660.h22
-rw-r--r--src/kernel/fs/marfs/directory.c55
-rw-r--r--src/kernel/fs/marfs/disklevel.c23
-rw-r--r--src/kernel/fs/marfs/marfs.h81
-rw-r--r--src/kernel/fs/marfs/new_file.c102
-rw-r--r--src/kernel/fs/marfs/read_whole_file.c65
-rw-r--r--src/kernel/fs/marfs/sectorlevel.c101
-rw-r--r--src/kernel/interact.asm4
-rw-r--r--src/kernel/interrupts/interrupts.h12
-rw-r--r--src/kernel/interrupts/isr.c9
-rw-r--r--src/kernel/kernel.c9
-rw-r--r--src/kernel/lib/alloc.c4
-rw-r--r--src/kernel/lib/alloc.h2
-rw-r--r--src/kernel/lib/lib.h5
-rw-r--r--src/kernel/lib/memory.c37
-rw-r--r--src/kernel/paging/paging.c2
-rw-r--r--src/kernel/timer/timer.c2
33 files changed, 1382 insertions, 235 deletions
diff --git a/Makefile b/Makefile
index 81fc74e..81229f0 100644
--- a/Makefile
+++ b/Makefile
@@ -28,19 +28,13 @@ build: clean
rm ./build/tmp; \
i686-elf-gcc -T ./src/kernel/linker.ld -I ./src -o ./build/melvix.bin -std=gnu99 -ffreestanding -O2 -nostdlib ./build/*.o || exit; \
- # Testing
- if grub-file --is-x86-multiboot ./build/melvix.bin; then \
- echo Multiboot confirmed; \
- else \
- echo Melvix has errors and won\'t be able to multi boot!; \
- exit; \
- fi; \
-
# Create ISO
mkdir -p ./iso/boot/; \
mv ./build/melvix.bin ./iso/boot/kernel.bin; \
- nasm ./src/bootloader/loader.asm -f bin -o ./iso/boot/boot.bin || exit; \
- genisoimage -no-emul-boot -b boot/boot.bin -o ./build/melvix.iso ./iso; \
+ nasm ./src/bootloader/cd.asm -f bin -o ./iso/boot/boot.bin || exit; \
+ nasm ./src/bootloader/hdd1.asm -f bin -o ./iso/boot/hdd1.bin || exit; \
+ nasm ./src/bootloader/hdd2.asm -f bin -o ./iso/boot/hdd2.bin || exit; \
+ genisoimage -no-emul-boot -b boot/boot.bin -o ./build/melvix.iso ./iso;
cross:
@set -e; \
@@ -74,7 +68,8 @@ debug:
@rm -f qemu.log
@echo "Starting simulation"
@echo "[SERIAL OUTPUT]"
- @qemu-system-x86_64 -no-reboot -M accel=kvm:tcg -vga std -serial stdio -rtc base=localtime -d cpu_reset -D qemu.log -m 512M -cdrom ./build/melvix.iso
+ @head -c 10485760 /dev/zero > ./build/hdd10M.img
+ @qemu-system-x86_64 -no-reboot -M accel=kvm:tcg -vga std -serial stdio -rtc base=localtime -d int,in_asm -D qemu.log -m 512M -cdrom ./build/melvix.iso -hda ./build/hdd10M.img
@echo "[END OF CONNECTION]"
.PHONY: build clean cross test debug \ No newline at end of file
diff --git a/src/bootloader/loader.asm b/src/bootloader/cd.asm
index 28e4562..1e83a3a 100644
--- a/src/bootloader/loader.asm
+++ b/src/bootloader/cd.asm
@@ -6,7 +6,6 @@ mov [bootDriveID], dl
jmp start
-; The print function
print:
mov ah, 0x0E
xor bh, bh
@@ -441,4 +440,4 @@ lba_not_supported:
boot db "BOOT"
boot_len equ ($ - boot)
kernelbin db "KERNEL.BIN", 0x3B, "1"
-kernelbin_len equ ($ - kernelbin) \ No newline at end of file
+kernelbin_len equ ($ - kernelbin)
diff --git a/src/bootloader/grub.cfg b/src/bootloader/grub.cfg
deleted file mode 100644
index cb265b1..0000000
--- a/src/bootloader/grub.cfg
+++ /dev/null
@@ -1,7 +0,0 @@
-set timeout=0
-set default=0
-menuentry "Melvix" {
- multiboot /boot/melvix.bin
- module /boot/melvix.initrd
- boot
-} \ No newline at end of file
diff --git a/src/bootloader/hdd1.asm b/src/bootloader/hdd1.asm
new file mode 100644
index 0000000..c347625
--- /dev/null
+++ b/src/bootloader/hdd1.asm
@@ -0,0 +1,118 @@
+BITS 16
+ORG 0x7C00
+
+%define INODE_ADDRESS 0xF000
+%define INODE_NBLOCKS 20
+%define INODE_DBP0 24
+
+; Save the boot drive id
+mov [bootDriveID], dl
+
+jmp start
+
+print:
+ mov ah, 0x0E
+ xor bh, bh
+ .print_L:
+ lodsb
+ test al, al
+ jz .print_end
+ int 0x10
+ jmp .print_L
+ .print_end:
+ ret
+
+bootDriveID: db 0
+
+dapack:
+ dapack_size: db 0x10
+ dapack_null: db 0x00
+ dapack_blkcount: dw 0x0001
+ dapack_boffset: dw 0x8000
+ dapack_bsegment: dw 0x0000
+ dapack_start: dd 0x00000000
+ dapack_upper_lba_bits: dd 0x00000000
+
+readsector:
+ mov dword [dapack_start], eax
+ mov ah, 0x42
+ mov dl, [bootDriveID]
+ xor bx, bx
+ mov ds, bx
+ mov si, dapack
+ int 0x13
+ ret
+
+; 5K max
+readwholefile:
+ mov bx, word [dapack_boffset]
+ push bx
+ mov bx, INODE_ADDRESS
+ mov word [dapack_boffset], bx
+ call readsector
+ pop bx
+ mov word [dapack_boffset], bx
+
+ mov edx, [INODE_ADDRESS+INODE_NBLOCKS]
+
+ xor ecx, ecx
+ .readwholefile_L:
+ lea bx, [INODE_ADDRESS + INODE_DBP0 + (ecx*4)]
+ mov eax, dword [bx]
+
+ push dx
+ call readsector
+ pop dx
+
+ add dword [dapack_boffset], 512
+
+ inc cx
+ cmp cx, dx
+ jl .readwholefile_L
+ ret
+
+welcome db "Melvix", 0x0A, 0x0D, 0x00
+nolba db "BIOS lacks support for LBA addressing.", 0x00
+signaturebad db "Bad disk signature.", 0x00
+
+start:
+ mov ax, 0x0003
+ int 0x10
+
+ mov si, welcome
+ call print
+
+ mov ah, 0x41
+ mov bx, 0x55AA
+ int 0x13
+ jc lba_not_supported
+ cmp bx, 0xAA55
+ jnz lba_not_supported
+
+ mov eax, 1
+ call readsector
+
+ mov eax, [0x8000+0]
+ cmp eax, 0x34B59645
+ jnz signature_BAD
+ mov eax, [0x8000+4]
+ cmp eax, 0x1083B99F
+ jnz signature_BAD
+
+ mov eax, 2
+ call readwholefile
+
+ jmp 0x8000
+
+lba_not_supported:
+ mov si, nolba
+ call print
+ jmp $
+
+signature_BAD:
+ mov si, signaturebad
+ call print
+ jmp $
+
+times 510-($-$$) db 0
+dw 0xAA55 \ No newline at end of file
diff --git a/src/bootloader/hdd2.asm b/src/bootloader/hdd2.asm
new file mode 100644
index 0000000..e289c39
--- /dev/null
+++ b/src/bootloader/hdd2.asm
@@ -0,0 +1,388 @@
+BITS 16
+ORG 0x8000
+
+%define SECTOR_BUFFER 0x9000
+%define INODE_NBLOCKS 20
+%define INODE_DBP0 24
+%define INODE_SIBP 64
+%define INODE_DIBP 68
+%define INODE_TIBP 72
+%define INODE_QIBP 76
+
+mov esp, 0xFFFF
+jmp start
+
+checkA20:
+ ; Stolen from https://wiki.osdev.org/A20_Line
+ pushf
+ push ds
+ push es
+ push di
+ push si
+ cli
+ xor ax, ax
+ mov es, ax
+ not ax
+ mov ds, ax
+ mov di, 0x0500
+ mov si, 0x0510
+ mov al, byte [es:di]
+ push ax
+ mov al, byte [ds:si]
+ push ax
+ mov byte [es:di], 0x00
+ mov byte [ds:si], 0xFF
+ cmp byte [es:di], 0xFF
+ pop ax
+ mov byte [ds:si], al
+ pop ax
+ mov byte [es:di], al
+ mov ax, 0
+ jz checkA20_exit
+ mov ax, 1
+ checkA20_exit:
+ pop si
+ pop di
+ pop es
+ pop ds
+ popf
+ ret
+
+last_maxlevel db 0
+getrecursive:
+ push edi
+ push esi
+ push ecx
+
+ mov eax, edi
+ cmp al, byte [last_maxlevel]
+ jna .last_maxlevel_updated
+ mov byte [last_maxlevel], al
+ .last_maxlevel_updated:
+
+ mov eax, esi
+ call 0x7c26
+
+ mov eax, dword [esp]
+ sub eax, 10
+
+ cmp byte [last_maxlevel], 1
+ jna .check1
+ mov ebx, 1
+ shl ebx, 7
+ sub eax, ebx
+ .check1:
+ cmp byte [last_maxlevel], 2
+ jna .check2
+ mov ebx, 1
+ shl ebx, 14
+ sub eax, ebx
+ .check2:
+ cmp byte [last_maxlevel], 3
+ jna .check3
+ mov ebx, 1
+ shl ebx, 21
+ sub eax, ebx
+ .check3:
+ mov ecx, dword [esp+8]
+ dec ecx
+ push ecx
+ shl ecx, 3
+ sub ecx, dword [esp]
+ add esp, 4
+ shr eax, cl
+
+ mov eax, dword [SECTOR_BUFFER+(4*eax)]
+
+ cmp dword [esp+8], 1
+ jna .finish_recursion
+ mov edi, [esp+8]
+ dec edi
+ mov esi, eax
+ mov ecx, [esp]
+ call getrecursive
+ .finish_recursion:
+ mov byte [last_maxlevel], 0
+
+ pop ecx
+ pop esi
+ pop edi
+ ret
+
+get_block:
+ push ecx
+ push ebx
+
+ xor ebx, ebx
+ inc ebx
+ shl ebx, 21
+ add ebx, 9
+ cmp ecx, ebx
+ jna .gtb1
+
+ mov edi, 4
+ mov esi, dword [SECTOR_BUFFER+INODE_QIBP]
+ call getrecursive
+ jmp .get_block_end
+
+ .gtb1:
+ xor ebx, ebx
+ inc ebx
+ shl ebx, 14
+ add ebx, 9
+ cmp ecx, ebx
+ jna .gtb2
+
+ mov edi, 3
+ mov esi, dword [SECTOR_BUFFER+INODE_TIBP]
+ call getrecursive
+ jmp .get_block_end
+
+ .gtb2:
+ xor ebx, ebx
+ inc ebx
+ shl ebx, 7
+ add ebx, 9
+ cmp ecx, ebx
+ jna .gtb3
+
+ mov edi, 2
+ mov esi, dword [SECTOR_BUFFER+INODE_DIBP]
+ call getrecursive
+ jmp .get_block_end
+
+ .gtb3:
+ cmp ecx, 9
+ jna .gtb4
+
+ mov edi, 1
+ mov esi, dword [SECTOR_BUFFER+INODE_SIBP]
+ call getrecursive
+ jmp .get_block_end
+
+ .gtb4:
+ mov eax, SECTOR_BUFFER+INODE_DBP0
+ mov eax, dword [eax+(4*ecx)]
+
+ .get_block_end:
+ pop ebx
+ pop ecx
+ ret
+
+noa20 db "A20 could not be enabled.", 0
+loading db "Loading kernel...", 0x0A, 0x0D, 0x00
+booting db "Booting...", 0x0A, 0x0D, 0x00
+nomem db "BIOS does not support memory detection!", 0
+memno20 db "BIOS returns memory detection with 24 bytes. This has never been seen!", 0
+
+start:
+ call checkA20
+ test ax, ax
+ jnz A20_ENABLED
+
+ in al, 0x92
+ or al, 2
+ out 0x92, al
+
+ call checkA20
+ test ax, ax
+ jnz A20_ENABLED
+
+ mov si, noa20
+ call 0x7c07
+ jmp $
+
+A20_ENABLED:
+ ; Inspired by https://wiki.osdev.org/Unreal_Mode
+ cli
+ push ds
+ lgdt [gdtinfo]
+
+ mov eax, cr0
+ or al, 1
+ mov cr0, eax
+
+ jmp $+2
+
+ mov bx, 0x08
+ mov ds, bx
+
+ and al, 0xFE
+ mov cr0, eax
+ pop ds
+
+ mov si, loading
+ call 0x7c07
+
+ mov word [0x7c1a], SECTOR_BUFFER
+
+ mov eax, 3
+ call 0x7c26
+ mov edx, dword [SECTOR_BUFFER + INODE_NBLOCKS]
+
+ xor ecx, ecx
+LOAD_KERNEL:
+ push edx
+
+ mov eax, 3
+ call 0x7c26
+ call get_block
+ call 0x7c26
+
+ mov eax, ecx
+ shl eax, 9
+ add eax, 0x200000
+
+ push ecx
+ xor ecx, ecx
+ .LOAD_KERNEL_L:
+ mov ebx, ecx
+ add ebx, SECTOR_BUFFER
+ mov ebx, dword [ebx]
+
+ mov edx, ebx
+ mov ebx, eax
+ add ebx, ecx
+ mov dword [ebx], edx
+
+ add ecx, 4
+ cmp ecx, 2048
+ jl .LOAD_KERNEL_L
+ pop ecx
+
+ inc ecx
+ pop edx
+ cmp ecx, edx
+ jl LOAD_KERNEL
+
+mov si, booting
+call 0x7c07
+
+mov dl, [0x7c15]
+mov byte [0x9000], dl
+
+mov di, 0xA000
+mov eax, 0xE820
+xor ebx, ebx
+mov ecx, 24
+mov edx, 0x534D4150
+int 0x15
+
+jc BIOS_NO_MEM
+cmp eax, 0x534D4150
+jnz BIOS_NO_MEM
+cmp cl, 20
+jnz BIOS_MEM_NO20
+
+MEM_L:
+ test ebx, ebx
+ jz MEM_FINISHED
+
+ mov ax, di
+ xor ch, ch
+ add ax, cx
+ mov di, ax
+
+ mov eax, 0xE820
+ mov ecx, 24
+ int 0x15
+ jmp MEM_L
+
+MEM_FINISHED:
+ mov eax, cr0
+ or al, 1
+ mov cr0, eax
+
+ mov ax, 0x08
+ mov ds, ax
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
+ mov ss, ax
+
+; Infomation: https://wiki.osdev.org/ELF
+mov ebx, 0x20002C
+mov dl, byte [ebx]
+push dx
+
+mov ebx, 0x20001C
+mov ebx, dword [ebx]
+push ebx
+
+xor dh, dh
+PHT:
+ xor eax, eax
+ mov al, dh
+ shl eax, 5
+ add eax, dword [esp]
+ add eax, 0x200000
+ mov ebx, eax
+
+ mov eax, dword [ebx]
+ cmp eax, 1
+ jnz .PHT_ignore
+
+ add ebx, 4
+ mov eax, dword [ebx]
+ add eax, 0x200000
+ push eax
+
+ add ebx, 4
+ mov eax, dword [ebx]
+ push eax
+
+ add ebx, 8
+ mov eax, dword [ebx]
+ push eax
+
+ push dx
+ xor ecx, ecx
+ .MOVE_KERNEL_L:
+ mov ebx, [esp+10]
+ add ebx, ecx
+ mov ebx, dword [ebx]
+
+ mov eax, ebx
+ mov ebx, dword [esp+6]
+ add ebx, ecx
+ mov dword [ebx], eax
+
+ add ecx, 4
+ cmp ecx, dword [esp+2]
+ jl .MOVE_KERNEL_L
+ pop dx
+ add esp, 12
+
+ .PHT_ignore:
+ inc dh
+ cmp dh, dl
+ jl PHT
+
+jmp (codedesc - gdt):protectedMode
+
+protectedMode:
+ BITS 32
+ mov ebx, 0x100000
+ mov eax, dword [ebx]
+ jmp eax
+
+BITS 16
+BIOS_NO_MEM:
+ mov si, nomem
+ call 0x7c07
+ jmp $
+BIOS_MEM_NO20:
+ mov si, memno20
+ call 0x7c07
+ jmp $
+
+gdtinfo:
+ dw gdt_end - gdt - 1
+ dd gdt
+ gdt dd 0, 0
+ flatdesc db 0xff, 0xff, 0, 0, 0, 10010010b, 11001111b, 0
+ codedesc db 0xff, 0xff, 0, 0, 0, 10011010b, 11001111b, 0
+ gdt_end:
+
+kernelbin db "KERNEL.BIN", 0x3B, "1"
+kernelbin_len equ ($ - kernelbin)
diff --git a/src/bootloader/make_initrd.c b/src/bootloader/make_initrd.c
deleted file mode 100644
index 6c2e7a0..0000000
--- a/src/bootloader/make_initrd.c
+++ /dev/null
@@ -1,53 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-struct initrd_header {
- unsigned char magic;
- char name[64];
- unsigned int offset;
- unsigned int length;
-};
-
-int main(char argc, char **argv) {
- int nheaders = (argc - 1) / 2;
- struct initrd_header headers[64];
- printf("size of header: %d\n", (int) sizeof(struct initrd_header));
- unsigned int off = sizeof(struct initrd_header) * 64 + sizeof(int);
-
- for (int i = 0; i < nheaders; i++) {
- printf("writing file %s->%s at 0x%x\n", argv[i * 2 + 1], argv[i * 2 + 2], off);
- strcpy(headers[i].name, argv[i * 2 + 2]);
- headers[i].name[strlen(argv[i * 2 + 2])] = '\0';
- headers[i].offset = off;
- FILE *stream = fopen(argv[i * 2 + 1], "r");
- if (stream == 0) {
- printf("Error: file not found: %s\n", argv[i * 2 + 1]);
- return 1;
- }
- fseek(stream, 0, SEEK_END);
- headers[i].length = ftell(stream);
- off += headers[i].length;
- fclose(stream);
- headers[i].magic = 0xBF;
- }
-
- FILE *wstream = fopen("./initrd.img", "w");
- unsigned char *data = (unsigned char *) malloc(off);
- fwrite(&nheaders, sizeof(int), 1, wstream);
- fwrite(headers, sizeof(struct initrd_header), 64, wstream);
-
- for (int i = 0; i < nheaders; i++) {
- FILE *stream = fopen(argv[i * 2 + 1], "r");
- unsigned char *buf = (unsigned char *) malloc(headers[i].length);
- fread(buf, 1, headers[i].length, stream);
- fwrite(buf, 1, headers[i].length, wstream);
- fclose(stream);
- free(buf);
- }
-
- fclose(wstream);
- free(data);
-
- return 0;
-}
diff --git a/src/kernel/boot.asm b/src/kernel/boot.asm
index b1f6018..9b4ddc7 100644
--- a/src/kernel/boot.asm
+++ b/src/kernel/boot.asm
@@ -18,7 +18,7 @@ section .text
mov esp, STACK_TOP
push ebx
push eax
-
+ cli
call kernel_main
cli
diff --git a/src/kernel/fs/ata_pio.c b/src/kernel/fs/ata_pio.c
new file mode 100644
index 0000000..d577ea1
--- /dev/null
+++ b/src/kernel/fs/ata_pio.c
@@ -0,0 +1,125 @@
+#include <kernel/io/io.h>
+#include <kernel/lib/alloc.h>
+#include <kernel/fs/ata_pio.h>
+#include <kernel/interrupts/interrupts.h>
+
+struct ATA_INTERFACE *new_ATA(uint8_t master, uint16_t portBase) {
+ struct ATA_INTERFACE *ret = kmalloc(sizeof(struct ATA_INTERFACE));
+
+ ret->master = master;
+ ret->dataPort = portBase;
+ ret->errorPort = portBase + 0x1;
+ ret->sectorCountPort = portBase + 0x2;
+ ret->lbaLowPort = portBase + 0x3;
+ ret->lbaMidPort = portBase + 0x4;
+ ret->lbaHiPort = portBase + 0x5;
+ ret->devicePort = portBase + 0x6;
+ ret->commandPort = portBase + 0x7;
+ ret->controlPort = portBase + 0x206;
+
+ // isr_ignore(0x06);
+ // isr_ignore(0x2E);
+ // isr_ignore(0x2F);
+
+ return ret;
+}
+
+uint8_t ATA_identify(struct ATA_INTERFACE *iface, uint16_t *retdata) {
+ send_b(iface->devicePort, iface->master ? 0xA0 : 0xB0);
+ send_b(iface->controlPort, 0);
+
+ send_b(iface->devicePort, 0xA0);
+ uint8_t status = receive_b(iface->commandPort);
+ if (status == 0xFF) return 1;
+
+ send_b(iface->devicePort, iface->master ? 0xA0 : 0xB0);
+ send_b(iface->sectorCountPort, 0);
+ send_b(iface->lbaLowPort, 0);
+ send_b(iface->lbaMidPort, 0);
+ send_b(iface->lbaHiPort, 0);
+ send_b(iface->commandPort, 0xEC); // Identify command
+
+ status = receive_b(iface->commandPort);
+ if (!status) return 1;
+
+ while (((status & 0x80) == 0x80) && ((status & 0x01) != 0x01)) {
+ status = receive_b(iface->commandPort);
+ }
+
+ if (status & 0x01) return 1;
+
+ for (int i = 0; i < 256; i++) retdata[i] = receive_w(iface->dataPort);
+ return 0;
+}
+
+uint8_t *ATA_read28(struct ATA_INTERFACE *iface, uint32_t sector) {
+ if (sector > 0x0FFFFFFF) return 0;
+
+ send_b(iface->devicePort, (iface->master ? 0xE0 : 0xF0) | ((sector & 0x0F000000) >> 24));
+
+ uint8_t status;
+ for (int i = 0; i < 5; i++) status = receive_b(iface->commandPort);
+ if (status == 0xFF) return 0;
+
+ send_b(iface->errorPort, 0);
+ send_b(iface->sectorCountPort, 1);
+ send_b(iface->lbaLowPort, sector & 0x000000FF);
+ send_b(iface->lbaMidPort, (sector & 0x0000FF00) >> 8);
+ send_b(iface->lbaHiPort, (sector & 0x00FF0000) >> 16);
+ send_b(iface->commandPort, 0x20); // Read command
+
+ status = receive_b(iface->commandPort);
+ while ((status & 0x80) && !(status & 0x01)) status = receive_b(iface->commandPort);
+
+ uint8_t *ret = kmalloc(BYTES_PER_SECTOR);
+ for (int i = 0; i < BYTES_PER_SECTOR; i += 2) {
+ uint16_t data = receive_w(iface->dataPort);
+ ret[i] = data & 0xFF;
+ ret[i + 1] = (data >> 8) & 0xFF;
+ }
+ return ret;
+}
+
+uint8_t ATA_write28(struct ATA_INTERFACE *iface, uint32_t sector, uint8_t *contents) {
+ if (sector > 0x0FFFFFFF) return 1;
+ asm volatile ("cli");
+
+ send_b(iface->devicePort, (iface->master ? 0xE0 : 0xF0) | ((sector & 0x0F000000) >> 24));
+
+ uint8_t status;
+ for (int i = 0; i < 5; i++) status = receive_b(iface->commandPort);
+ if (status == 0xFF) return 1;
+
+ send_b(iface->errorPort, 0);
+ send_b(iface->sectorCountPort, 1);
+ send_b(iface->lbaLowPort, sector & 0x000000FF);
+ send_b(iface->lbaMidPort, (sector & 0x0000FF00) >> 8);
+ send_b(iface->lbaHiPort, (sector & 0x00FF0000) >> 16);
+ send_b(iface->commandPort, 0x30); // Write command
+
+ while ((status & 0x80) || !(status & 0x08)) status = receive_b(iface->commandPort);
+
+ if (status & (0x01 || 0x20)) return 2;
+
+ for (int i = 0; i < BYTES_PER_SECTOR; i += 2) {
+ uint16_t data = contents[i];
+ data |= ((uint16_t) contents[i + 1]) << 8;
+ send_w(iface->dataPort, data);
+ }
+
+ send_b(iface->commandPort, 0xE7); // Flush command
+
+ for (int i = 0; i < 5; i++) status = receive_b(iface->commandPort);
+ if (!status) return 3;
+
+ while ((status & 0x80) && !(status & 0x01)) {
+ status = receive_b(iface->commandPort);
+ }
+
+ return 0;
+}
+
+uint8_t ATA_clear28(struct ATA_INTERFACE *iface, uint32_t sector) {
+ uint8_t emptysector[512] = {0};
+ return ATA_write28(iface, sector, emptysector);
+} \ No newline at end of file
diff --git a/src/kernel/fs/ata_pio.h b/src/kernel/fs/ata_pio.h
new file mode 100644
index 0000000..3f1439d
--- /dev/null
+++ b/src/kernel/fs/ata_pio.h
@@ -0,0 +1,31 @@
+#ifndef MELVIX_ATA_PIO_H
+#define MELVIX_ATA_PIO_H
+
+#include <stdint.h>
+
+#define BYTES_PER_SECTOR 512
+
+struct ATA_INTERFACE {
+ uint8_t master;
+ uint16_t dataPort;
+ uint16_t errorPort;
+ uint16_t sectorCountPort;
+ uint16_t lbaLowPort;
+ uint16_t lbaMidPort;
+ uint16_t lbaHiPort;
+ uint16_t devicePort;
+ uint16_t commandPort;
+ uint16_t controlPort;
+};
+
+struct ATA_INTERFACE *new_ATA(uint8_t master, uint16_t portBase);
+
+uint8_t ATA_identify(struct ATA_INTERFACE *iface, uint16_t *retdata);
+
+uint8_t *ATA_read28(struct ATA_INTERFACE *iface, uint32_t sector);
+
+uint8_t ATA_write28(struct ATA_INTERFACE *iface, uint32_t sector, uint8_t *contents);
+
+uint8_t ATA_clear28(struct ATA_INTERFACE *iface, uint32_t sector);
+
+#endif
diff --git a/src/kernel/fs/atapi_pio.c b/src/kernel/fs/atapi_pio.c
new file mode 100644
index 0000000..4f986d9
--- /dev/null
+++ b/src/kernel/fs/atapi_pio.c
@@ -0,0 +1,32 @@
+#include <stdint.h>
+#include <kernel/fs/atapi_pio.h>
+#include <kernel/system.h>
+#include <kernel/paging/paging.h>
+
+void ATAPI_read(uint16_t nblocks, uint32_t lba) {
+ struct dapack *d = (struct dapack *) ATAPI_PIO_DAPACK;
+ d->size = 0x10;
+ d->null = 0x00;
+ d->blkcount = nblocks;
+ d->boffset = ATAPI_PIO_BUFFER;
+ d->bsegment = 0x0000;
+ d->start = lba;
+ d->upper_lba_bits = 0x00000000;
+
+ regs16_t regs;
+ regs.ax = 0x4200;
+ regs.dx = ATAPI_PIO_DRIVE;
+ regs.ds = 0;
+ regs.si = ATAPI_PIO_DAPACK;
+
+ paging_disable();
+ int32(LBA_READ_INT, &regs);
+ paging_enable();
+}
+
+void ATAPI_granular_read(uint32_t nblocks, uint32_t lba, uint8_t *output) {
+ for (uint32_t i = 0; i < nblocks; i++) {
+ ATAPI_read(1, lba + i);
+ for (uint16_t j = 0; j < ATAPI_SECTOR_SIZE; j++) output[j + (2048 * i)] = ((uint8_t *) ATAPI_PIO_BUFFER)[j];
+ }
+} \ No newline at end of file
diff --git a/src/kernel/fs/atapi_pio.h b/src/kernel/fs/atapi_pio.h
new file mode 100644
index 0000000..5e89e85
--- /dev/null
+++ b/src/kernel/fs/atapi_pio.h
@@ -0,0 +1,26 @@
+#ifndef MELVIX_ATAPI_PIO_H
+#define MELVIX_ATAPI_PIO_H
+
+#include <stdint.h>
+
+#define ATAPI_PIO_DRIVE 0xE0
+#define LBA_READ_INT 0x13
+#define ATAPI_PIO_DAPACK 0x7E00
+#define ATAPI_PIO_BUFFER 0x8000
+#define ATAPI_SECTOR_SIZE 0x800
+
+struct dapack {
+ uint8_t size;
+ uint8_t null;
+ uint16_t blkcount;
+ uint16_t boffset;
+ uint16_t bsegment;
+ uint32_t start;
+ uint32_t upper_lba_bits;
+} __attribute__((packed));
+
+void ATAPI_read(uint16_t nblocks, uint32_t lba);
+
+void ATAPI_granular_read(uint32_t nblocks, uint32_t lba, uint8_t *output);
+
+#endif
diff --git a/src/kernel/fs/initrd.c b/src/kernel/fs/initrd.c
deleted file mode 100644
index acaceb8..0000000
--- a/src/kernel/fs/initrd.c
+++ /dev/null
@@ -1,131 +0,0 @@
-#include <stdint.h>
-#include <kernel/fs/initrd.h>
-#include <kernel/fs/vfs.h>
-#include <kernel/lib/lib.h>
-#include <kernel/lib/alloc.h>
-#include <kernel/io/io.h>
-#include <kernel/graphics/vesa.h>
-
-initrd_header_t *initrd_header;
-initrd_file_header_t *file_headers;
-fs_node_t *initrd_root;
-fs_node_t *initrd_dev;
-fs_node_t *root_nodes;
-int nroot_nodes;
-
-struct dirent dirent;
-
-static uint32_t initrd_read(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) {
- initrd_file_header_t header = file_headers[node->inode];
- if (offset > header.length)
- return 0;
- if (offset + size > header.length)
- size = header.length - offset;
- memcpy(buffer, (uint8_t *) (header.offset + offset), size);
- return size;
-}
-
-static struct dirent *initrd_readdir(fs_node_t *node, uint32_t index) {
- if (node == initrd_root && index == 0) {
- strcpy(dirent.name, "dev");
- dirent.name[3] = 0;
- dirent.ino = 0;
- return &dirent;
- }
-
- if (index - 1 >= (uint32_t) nroot_nodes)
- return 0;
- strcpy(dirent.name, root_nodes[index - 1].name);
- dirent.name[strlen(root_nodes[index - 1].name)] = 0;
- dirent.ino = root_nodes[index - 1].inode;
- return &dirent;
-}
-
-static fs_node_t *initrd_finddir(fs_node_t *node, char *name) {
- if (node == initrd_root &&
- !strcmp(name, "dev"))
- return initrd_dev;
-
- int i;
- for (i = 0; i < nroot_nodes; i++)
- if (!strcmp(name, root_nodes[i].name))
- return &root_nodes[i];
- return 0;
-}
-
-fs_node_t *initialise_initrd(uint32_t location) {
- initrd_header = (initrd_header_t *) location;
- file_headers = (initrd_file_header_t *) (location + sizeof(initrd_header_t));
-
- initrd_root = (fs_node_t *) kmalloc(sizeof(fs_node_t));
- strcpy(initrd_root->name, "initrd");
- initrd_root->mask = initrd_root->uid = initrd_root->gid = initrd_root->inode = initrd_root->length = 0;
- initrd_root->flags = FS_DIRECTORY;
- initrd_root->read = 0;
- initrd_root->write = 0;
- initrd_root->open = 0;
- initrd_root->close = 0;
- initrd_root->readdir = &initrd_readdir;
- initrd_root->finddir = &initrd_finddir;
- initrd_root->ptr = 0;
- initrd_root->impl = 0;
-
- initrd_dev = (fs_node_t *) kmalloc(sizeof(fs_node_t));
- strcpy(initrd_dev->name, "dev");
- initrd_dev->mask = initrd_dev->uid = initrd_dev->gid = initrd_dev->inode = initrd_dev->length = 0;
- initrd_dev->flags = FS_DIRECTORY;
- initrd_dev->read = 0;
- initrd_dev->write = 0;
- initrd_dev->open = 0;
- initrd_dev->close = 0;
- initrd_dev->readdir = &initrd_readdir;
- initrd_dev->finddir = &initrd_finddir;
- initrd_dev->ptr = 0;
- initrd_dev->impl = 0;
-
- root_nodes = (fs_node_t *) kmalloc(sizeof(fs_node_t) * initrd_header->nfiles);
- nroot_nodes = initrd_header->nfiles;
-
- for (uint32_t i = 0; i < initrd_header->nfiles; i++) {
- file_headers[i].offset += location;
-
- strcpy(root_nodes[i].name, (const char *) &file_headers[i].name);
- root_nodes[i].mask = root_nodes[i].uid = root_nodes[i].gid = 0;
- root_nodes[i].length = file_headers[i].length;
- root_nodes[i].inode = i;
- root_nodes[i].flags = FS_FILE;
- root_nodes[i].read = &initrd_read;
- root_nodes[i].write = 0;
- root_nodes[i].readdir = 0;
- root_nodes[i].finddir = 0;
- root_nodes[i].open = 0;
- root_nodes[i].close = 0;
- root_nodes[i].impl = 0;
- }
- return initrd_root;
-}
-
-void initrd_test() {
- int i = 0;
- struct dirent *node = 0;
- vesa_draw_string("\n");
- while ((node = readdir_fs(fs_root, i)) != 0) {
- vesa_draw_string("Found file: ");
- vesa_draw_string(node->name);
- vesa_draw_string("\n");
- fs_node_t *fsnode = finddir_fs(fs_root, node->name);
-
- if ((fsnode->flags & 0x7) == FS_DIRECTORY)
- vesa_draw_string("\t (directory)\n");
- else {
- vesa_draw_string("\t contents: \"");
- uint8_t buf[fsnode->length];
- uint32_t sz = read_fs(fsnode, 0, fsnode->length, buf);
- for (uint32_t j = 0; j < sz; j++)
- vesa_draw_char(buf[j]);
-
- vesa_draw_string("\"\n");
- }
- i++;
- }
-} \ No newline at end of file
diff --git a/src/kernel/fs/initrd.h b/src/kernel/fs/initrd.h
deleted file mode 100644
index bb5c376..0000000
--- a/src/kernel/fs/initrd.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef MELVIX_INITRD_H
-#define MELVIX_INITRD_H
-
-#include <stdint.h>
-#include <kernel/fs/vfs.h>
-
-typedef struct {
- uint32_t nfiles;
-} initrd_header_t;
-
-typedef struct {
- uint8_t magic;
- int8_t name[64];
- uint32_t offset;
- uint32_t length;
-} initrd_file_header_t;
-
-fs_node_t *initialise_initrd(uint32_t location);
-
-void initrd_test();
-
-#endif
diff --git a/src/kernel/fs/install.c b/src/kernel/fs/install.c
new file mode 100644
index 0000000..5a2cc61
--- /dev/null
+++ b/src/kernel/fs/install.c
@@ -0,0 +1,61 @@
+#include <kernel/graphics/vesa.h>
+#include <kernel/fs/ata_pio.h>
+#include <kernel/fs/marfs/marfs.h>
+#include <kernel/lib/alloc.h>
+#include <kernel/fs/iso9660/iso9660.h>
+#include "atapi_pio.h"
+
+void install_melvix() {
+ info("You're booting from a CD, Melvix will only run after an install");
+ asm volatile ("cli");
+ struct ATA_INTERFACE *primary_master = new_ATA(1, 0x1F0);
+ if (marfs_init(primary_master) != 0) {
+ panic("No HDD found!");
+ }
+
+ struct marfs_SUPERBLOCK *currentSB = marfs_read_superblock();
+ if (currentSB->signature == 0x1083B99F34B59645) { // WEEEOOOWEEEOOO
+ panic("Melvix seems to be already installed!");
+ }
+ kfree(currentSB);
+
+ info("Installing...\n");
+
+ // Copy MBR
+ info("Copying MBR... ");
+ char *stage1_p[] = {"BOOT", "HDD1.BIN"};
+ struct ISO9660_entity *stage1_e = ISO9660_get(stage1_p, 2);
+ if (!stage1_e)
+ panic("Couldn't find the first HDD bootloader!");
+ uint8_t *stage1 = ISO9660_read(stage1_e);
+ kfree(stage1_e);
+ marfs_write_mbr(stage1);
+
+ // Format disk
+ info("Formatting disk...");
+ marfs_format();
+
+ // Copy second stage
+ info("Copying second stage...");
+ char *stage2_p[] = {"BOOT", "HDD2.BIN"};
+ struct ISO9660_entity *stage2_e = ISO9660_get(stage2_p, 2);
+ if (!stage2_e)
+ panic("Couldn't find the second HDD bootloader!");
+ uint8_t *stage2 = ISO9660_read(stage2_e);
+ marfs_new_file(stage2_e->length, stage2, 0, 0, 0);
+ kfree(stage2_e);
+
+ // Copy the kernel
+ info("Copying the kernel... ");
+ char *kernel_p[] = {"BOOT", "KERNEL.BIN"};
+ struct ISO9660_entity *kernel_e = ISO9660_get(kernel_p, 2);
+ if (!kernel_e)
+ panic("WTH Kernel not found!?");
+ uint8_t *kernel = kmalloc(kernel_e->length + 2048);
+ ATAPI_granular_read(1 + (kernel_e->length / 2048), kernel_e->LBA, kernel);
+ marfs_new_file(kernel_e->length, kernel, 0, 0, 0);
+ kfree(kernel);
+ kfree(kernel_e);
+
+ info("Installation successful!");
+} \ No newline at end of file
diff --git a/src/kernel/fs/install.h b/src/kernel/fs/install.h
new file mode 100644
index 0000000..8475297
--- /dev/null
+++ b/src/kernel/fs/install.h
@@ -0,0 +1,6 @@
+#ifndef MELVIX_INSTALL_H
+#define MELVIX_INSTALL_H
+
+void install_melvix();
+
+#endif
diff --git a/src/kernel/fs/iso9660/iso9660.c b/src/kernel/fs/iso9660/iso9660.c
new file mode 100644
index 0000000..728d3cb
--- /dev/null
+++ b/src/kernel/fs/iso9660/iso9660.c
@@ -0,0 +1,60 @@
+#include <stdint.h>
+#include <kernel/lib/lib.h>
+#include <kernel/fs/atapi_pio.h>
+#include <kernel/fs/iso9660/iso9660.h>
+#include <kernel/lib/alloc.h>
+
+struct ISO9660_entity *ISO9660_get(char **dirs, uint8_t dirs_sz) {
+ ATAPI_read(1, 0x10);
+ uint32_t last_len = *(uint32_t *) (
+ ATAPI_PIO_BUFFER +
+ ISO9660_ROOT_RECORD_OFFSET +
+ ISO9660_DIR_EAR_LENGTH
+ );
+ uint32_t last_LBA = *(uint32_t *) (
+ ATAPI_PIO_BUFFER +
+ ISO9660_ROOT_RECORD_OFFSET +
+ ISO9660_DIR_EAR_LBA
+ );
+
+ for (uint8_t dirs_i = 0; dirs_i < dirs_sz; dirs_i++) {
+ ATAPI_read((last_len % 2048 != 0) + (last_len / 2048), last_LBA);
+
+ uint8_t found = 0;
+ for (uint32_t i = 0; i < last_len && !found;) {
+ if (!*(uint8_t *) (ATAPI_PIO_BUFFER + i + ISO9660_DIR_RECORD_LENGTH))
+ break;
+
+ char *filename = (char *) (ATAPI_PIO_BUFFER + i + ISO9660_DIR_FILENAME);
+
+ for (uint32_t j = 0; j < ISO9660_DIR_FILENAME_LENGTH; j++) {
+ if (filename[j] == ';') {
+ filename[j] = 0;
+ break;
+ }
+ }
+
+ if (strcmp(dirs[dirs_i], filename) == 0) {
+ found = 1;
+ last_LBA = *(uint32_t *) (ATAPI_PIO_BUFFER + i + ISO9660_DIR_EAR_LBA);
+ last_len = *(uint32_t *) (ATAPI_PIO_BUFFER + i + ISO9660_DIR_EAR_LENGTH);
+ } else {
+ i += *(uint8_t *) (ATAPI_PIO_BUFFER + i + ISO9660_DIR_RECORD_LENGTH);
+ }
+ }
+
+ if (!found) {
+ return (struct ISO9660_entity *) 0;
+ }
+ }
+
+ struct ISO9660_entity *ret = (struct ISO9660_entity *) kmalloc(sizeof(struct ISO9660_entity));
+ ret->LBA = last_LBA;
+ ret->length = last_len;
+ return ret;
+}
+
+uint8_t *ISO9660_read(struct ISO9660_entity *entity) {
+ ATAPI_read((entity->length % 2048 != 0) + (entity->length / 2048), entity->LBA);
+ return (uint8_t *) ATAPI_PIO_BUFFER;
+} \ No newline at end of file
diff --git a/src/kernel/fs/iso9660/iso9660.h b/src/kernel/fs/iso9660/iso9660.h
new file mode 100644
index 0000000..3de5d1a
--- /dev/null
+++ b/src/kernel/fs/iso9660/iso9660.h
@@ -0,0 +1,22 @@
+#ifndef MELVIX_ISO9660_H
+#define MELVIX_ISO9660_H
+
+#define ISO9660_ROOT_RECORD_OFFSET 156
+#define ISO9660_DIR_RECORD_LENGTH 0
+#define ISO9660_DIR_EAR_LBA 2
+#define ISO9660_DIR_EAR_LENGTH 10
+#define ISO9660_DIR_FILENAME_LENGTH 32
+#define ISO9660_DIR_FILENAME 33
+
+#include <stdint.h>
+
+struct ISO9660_entity {
+ uint32_t LBA;
+ uint32_t length;
+};
+
+struct ISO9660_entity *ISO9660_get(char **dirs, uint8_t dirs_sz);
+
+uint8_t *ISO9660_read(struct ISO9660_entity *entity);
+
+#endif
diff --git a/src/kernel/fs/marfs/directory.c b/src/kernel/fs/marfs/directory.c
new file mode 100644
index 0000000..f7783bb
--- /dev/null
+++ b/src/kernel/fs/marfs/directory.c
@@ -0,0 +1,55 @@
+#include <stdint.h>
+#include <kernel/fs/ata_pio.h>
+#include <kernel/lib/alloc.h>
+#include <kernel/lib/lib.h>
+#include "marfs.h"
+
+uint32_t marfs_new_dir(uint32_t uid) { return marfs_new_file(0, 0, uid, 0, 1); }
+
+
+void marfs_add_to_dir(uint32_t LBAinode, char *filename, uint32_t lba) {
+ struct marfs_INODE *inode = (struct marfs_INODE *) ATA_read28(iface, LBAinode);
+
+ // Read the content
+ uint8_t *old = marfs_allocate_and_read_whole_file(LBAinode);
+
+ // Allocate memory
+ uint8_t *contents = kmalloc(inode->size + strlen(filename) + 1 + 4);
+
+ // Copy the content
+ uint8_t lastWasNull = 0;
+ uint64_t newsize = 0;
+ for (uint64_t i = 0; i < inode->size; i++) {
+ if (old[i] == 0 && lastWasNull) continue;
+
+ contents[newsize++] = old[i];
+ lastWasNull = (old[i] == 0);
+ }
+ kfree(old);
+
+ // Append new file
+ for (uint16_t i = 0; i <= strlen(filename); i++) contents[newsize++] = filename[i];
+ for (signed char j = 24; j > 0; j -= 8) contents[newsize++] = (lba >> j) & 0xFF;
+
+ // Free the blocks
+ uint32_t newsize_in_blocks = newsize / 512;
+ if (newsize % 512) newsize_in_blocks++;
+ for (uint32_t i = 0; i < newsize_in_blocks; i++)
+ marfs_mark_block_as_free(marfs_get_block(inode, i));
+
+ // Overwrite
+ uint32_t aux_inode = marfs_new_file(newsize, contents, 0xDEADBEEF, 0, 0);
+ struct marfs_INODE *real_aux_inode = (struct marfs_INODE *) ATA_read28(iface, aux_inode);
+ for (uint8_t i = 0; i < 10; i++) inode->DBPs[i] = real_aux_inode->DBPs[i];
+ inode->ext_1 = real_aux_inode->ext_1;
+ inode->ext_2 = real_aux_inode->ext_2;
+ inode->ext_3 = real_aux_inode->ext_3;
+ inode->ext_4 = real_aux_inode->ext_4;
+ real_aux_inode->isUsed = 0;
+ ATA_write28(iface, aux_inode, (uint8_t *) real_aux_inode);
+ kfree(real_aux_inode);
+
+ inode->size = newsize;
+ ATA_write28(iface, LBAinode, (uint8_t *) inode);
+ kfree(inode);
+}
diff --git a/src/kernel/fs/marfs/disklevel.c b/src/kernel/fs/marfs/disklevel.c
new file mode 100644
index 0000000..b6fc8c2
--- /dev/null
+++ b/src/kernel/fs/marfs/disklevel.c
@@ -0,0 +1,23 @@
+#include <stdint.h>
+#include <kernel/fs/ata_pio.h>
+#include "marfs.h"
+
+void marfs_format(void) {
+ // Create superblock
+ struct marfs_SUPERBLOCK sb;
+ sb.signature = 0x1083B99F34B59645; // Huh, magic?!
+ sb.n_inodes = (marfs_get_max_lba() - 2) >> 5;
+ sb.n_chunks = (marfs_get_max_lba() - (2 + sb.n_inodes)) >> 9;
+ sb.n_first_unallocated_inode = 0;
+ sb.s_first_inode = 2;
+ sb.s_first_chunk = 2 + sb.n_inodes;
+
+ // Write to disk
+ marfs_writeSB(&sb);
+
+ // Initialize the inodes
+ for (uint32_t i = 0; i < sb.n_inodes; i++) ATA_clear28(iface, 2 + i);
+
+ // Initialize the chunks
+ for (uint32_t i = 0; i < sb.n_chunks; i++) ATA_clear28(iface, sb.s_first_chunk + i * 512);
+}
diff --git a/src/kernel/fs/marfs/marfs.h b/src/kernel/fs/marfs/marfs.h
new file mode 100644
index 0000000..ba6f0b3
--- /dev/null
+++ b/src/kernel/fs/marfs/marfs.h
@@ -0,0 +1,81 @@
+#ifndef MELVIX_MARFS_H
+#define MELVIX_MARFS_H
+
+#include <stdint.h>
+
+struct marfs_SUPERBLOCK {
+ uint64_t signature;
+ uint32_t n_inodes;
+ uint32_t n_chunks;
+ uint32_t n_first_unallocated_inode;
+ uint32_t s_first_inode;
+ uint32_t s_first_chunk;
+} __attribute__((packed));
+
+struct marfs_INODE {
+ uint64_t size;
+ uint32_t creation_time;
+ uint32_t last_mod_time;
+ uint32_t last_access_time;
+ uint32_t n_blocks;
+ uint32_t DBPs[10];
+ uint32_t ext_1;
+ uint32_t ext_2;
+ uint32_t ext_3;
+ uint32_t ext_4;
+ uint32_t uid;
+ uint8_t isApp;
+ uint8_t isDir;
+ uint8_t isUsed;
+} __attribute__((packed));
+
+enum marfs_RESERVED_INODES {
+ marfs_INODE_JBOOT2,
+ marfs_INODE_KERNEL,
+ marfs_INODE_ROOT
+};
+
+struct ATA_INTERFACE *iface;
+struct marfs_SUPERBLOCK sb_cache;
+uint32_t maxLBA;
+
+// marfs_sectorlevel.c
+uint8_t marfs_init(struct ATA_INTERFACE *iface);
+
+uint32_t marfs_get_max_lba(void);
+
+uint8_t marfs_write_mbr(uint8_t *mbr);
+
+struct marfs_SUPERBLOCK *marfs_read_superblock();
+
+uint8_t marfs_writeSB(struct marfs_SUPERBLOCK *sb);
+
+uint32_t marfs_get_free_lba_block(void);
+
+uint8_t marfs_mark_block_as_used(uint32_t LBAsector);
+
+uint8_t marfs_mark_block_as_free(uint32_t LBAsector);
+
+uint32_t marfs_get_free_lba_inode(void);
+
+void marfs_mark_inode_as_free(uint32_t LBAsector);
+
+// marfs_disklevel.c
+void marfs_format(void);
+
+// marfs_new_file.c
+uint32_t marfs_new_file(uint64_t size, uint8_t *data, uint32_t uid, uint8_t exec, uint8_t dir);
+
+// marfs_dir.c
+uint32_t marfs_new_dir(uint32_t uid);
+
+void marfs_add_to_dir(uint32_t LBAinode, char *filename, uint32_t lba);
+
+// marfs_read_whole_file.c
+uint32_t marfs_get_block(struct marfs_INODE *inode, uint32_t i);
+
+void marfs_read_whole_file(uint32_t LBAinode, uint8_t *buffer);
+
+uint8_t *marfs_allocate_and_read_whole_file(uint32_t LBAinode);
+
+#endif
diff --git a/src/kernel/fs/marfs/new_file.c b/src/kernel/fs/marfs/new_file.c
new file mode 100644
index 0000000..7b06621
--- /dev/null
+++ b/src/kernel/fs/marfs/new_file.c
@@ -0,0 +1,102 @@
+#include <stdint.h>
+#include <kernel/fs/ata_pio.h>
+#include <kernel/lib/alloc.h>
+#include "marfs.h"
+
+static uint8_t last_maxlevel = 0;
+
+void marfs_update_recursive(uint8_t level, uint32_t i, uint32_t recLBA, uint32_t realLBA) {
+ if (level > last_maxlevel) last_maxlevel = level;
+ uint32_t *contents = (uint32_t *) ATA_read28(iface, recLBA);
+
+ uint32_t idx = i - 10;
+ if (last_maxlevel > 1) idx -= 1 << 7;
+ if (last_maxlevel > 2) idx -= 1 << (7 * 2);
+ if (last_maxlevel > 3) idx -= 1 << (7 * 3);
+ idx >>= 7 * (level - 1);
+
+ if (level > 1) {
+ if (!contents[idx]) {
+ contents[idx] = marfs_get_free_lba_block();
+ marfs_mark_block_as_used(contents[idx]);
+ }
+ } else {
+ contents[idx] = realLBA;
+ }
+
+ ATA_write28(iface, recLBA, (uint8_t *) contents);
+
+ uint32_t contents_idx = contents[idx];
+ kfree(contents);
+ if (level != 1) {
+ marfs_update_recursive(level - 1, i, contents_idx, realLBA);
+ }
+ last_maxlevel = 0;
+}
+
+uint32_t marfs_new_file(uint64_t size, uint8_t *data, uint32_t uid, uint8_t exec, uint8_t dir) {
+ struct marfs_INODE *inode = (struct marfs_INODE *) kcalloc(1, 512);
+ inode->size = size;
+ inode->creation_time = inode->last_mod_time = inode->last_access_time = 0; // TODO: POSIX time
+ inode->n_blocks = size / 512;
+ if (size % 512) inode->n_blocks++;
+ inode->uid = uid;
+ inode->isApp = exec;
+ inode->isDir = dir;
+ inode->isUsed = 1;
+
+ uint32_t size_in_blocks = inode->n_blocks;
+
+ uint32_t LBA_singly, LBA_doubly, LBA_triply, LBA_quadruply;
+ LBA_singly = LBA_doubly = LBA_triply = LBA_quadruply = 0;
+ for (uint32_t i = 0; i < size_in_blocks; i++) {
+ uint32_t thisblock = marfs_get_free_lba_block();
+ if (i != size_in_blocks - 1) {
+ ATA_write28(iface, thisblock, data);
+ } else if (size % 512) {
+ uint8_t contents[512] = {0};
+ for (uint16_t i = 0; i < size % 512; i++) contents[i] = data[i];
+ ATA_write28(iface, thisblock, contents);
+ }
+ data += 512;
+ marfs_mark_block_as_used(thisblock);
+
+ if (i > 9 + (128 * 128 * 128)) {
+ if (!LBA_quadruply) {
+ LBA_quadruply = marfs_get_free_lba_block();
+ marfs_mark_block_as_used(LBA_quadruply);
+ inode->ext_4 = LBA_quadruply;
+ }
+ marfs_update_recursive(4, i, LBA_quadruply, thisblock);
+ } else if (i > 9 + (128 * 128)) {
+ if (!LBA_triply) {
+ LBA_triply = marfs_get_free_lba_block();
+ marfs_mark_block_as_used(LBA_triply);
+ inode->ext_3 = LBA_triply;
+ }
+ marfs_update_recursive(3, i, LBA_triply, thisblock);
+ } else if (i > 9 + 128) {
+ if (!LBA_doubly) {
+ LBA_doubly = marfs_get_free_lba_block();
+ marfs_mark_block_as_used(LBA_doubly);
+ inode->ext_2 = LBA_doubly;
+ }
+ marfs_update_recursive(2, i, LBA_doubly, thisblock);
+ } else if (i > 9) {
+ if (!LBA_singly) {
+ LBA_singly = marfs_get_free_lba_block();
+ marfs_mark_block_as_used(LBA_singly);
+ inode->ext_1 = LBA_singly;
+ }
+ marfs_update_recursive(1, i, LBA_singly, thisblock);
+ } else {
+ inode->DBPs[i] = thisblock;
+ }
+ }
+
+ // Write the inode
+ uint32_t inode_LBA = marfs_get_free_lba_inode();
+ ATA_write28(iface, inode_LBA, (uint8_t *) inode);
+
+ return inode_LBA;
+} \ No newline at end of file
diff --git a/src/kernel/fs/marfs/read_whole_file.c b/src/kernel/fs/marfs/read_whole_file.c
new file mode 100644
index 0000000..86aae5f
--- /dev/null
+++ b/src/kernel/fs/marfs/read_whole_file.c
@@ -0,0 +1,65 @@
+#include <stdint.h>
+#include <kernel/fs/ata_pio.h>
+#include <kernel/lib/alloc.h>
+#include "marfs.h"
+
+static uint8_t last_maxlevel = 0;
+
+uint32_t marfs_get_recursive(uint8_t level, uint32_t i, uint32_t recLBA) {
+ if (level > last_maxlevel) last_maxlevel = level;
+ uint32_t *contents = (uint32_t *) ATA_read28(iface, recLBA);
+ uint32_t idx = i - 10;
+ if (last_maxlevel > 1) idx -= 1 << 7;
+ if (last_maxlevel > 2) idx -= 1 << (7 * 2);
+ if (last_maxlevel > 3) idx -= 1 << (7 * 3);
+ idx >>= 7 * (level - 1);
+
+ uint32_t next_recLBA = contents[idx];
+ kfree(contents);
+
+ uint32_t toRet;
+ if (level > 1) toRet = marfs_get_recursive(level - 1, i, next_recLBA);
+ else toRet = next_recLBA;
+ last_maxlevel = 0;
+ return toRet;
+}
+
+uint32_t marfs_get_block(struct marfs_INODE *inode, uint32_t i) {
+ if (i > 9 + (128 * 128 * 128)) {
+ return marfs_get_recursive(4, i, inode->ext_4);
+ } else if (i > 9 + (128 * 128)) {
+ return marfs_get_recursive(3, i, inode->ext_3);
+ } else if (i > 9 + 128) {
+ return marfs_get_recursive(2, i, inode->ext_2);
+ } else if (i > 9) {
+ return marfs_get_recursive(1, i, inode->ext_1);
+ } else {
+ return inode->DBPs[i];
+ }
+}
+
+void marfs_read_whole_file(uint32_t LBAinode, uint8_t *buffer) {
+ struct marfs_INODE *inode = (struct marfs_INODE *) ATA_read28(iface, LBAinode);
+
+ uint32_t size_in_blocks = inode->n_blocks;
+ for (uint32_t i = 0; i < size_in_blocks; i++) {
+ uint32_t this_block = marfs_get_block(inode, i);
+ uint8_t *this_block_contents = ATA_read28(iface, this_block);
+ uint16_t upper_bound = (i != size_in_blocks - 1) ? 512 : (inode->size % 512);
+ for (uint16_t j = 0; j < upper_bound; j++) buffer[(i * 512) + j] = this_block_contents[j];
+ kfree(this_block_contents);
+ }
+
+ kfree(inode);
+}
+
+// TODO: Beautify
+uint8_t *marfs_allocate_and_read_whole_file(uint32_t LBAinode) {
+ struct marfs_INODE *inode = (struct marfs_INODE *) ATA_read28(iface, LBAinode);
+ uint64_t size = inode->size;
+ kfree(inode);
+
+ uint8_t *buffer = kmalloc(size);
+ marfs_read_whole_file(LBAinode, buffer);
+ return buffer;
+}
diff --git a/src/kernel/fs/marfs/sectorlevel.c b/src/kernel/fs/marfs/sectorlevel.c
new file mode 100644
index 0000000..7575f8c
--- /dev/null
+++ b/src/kernel/fs/marfs/sectorlevel.c
@@ -0,0 +1,101 @@
+#include <stdint.h>
+#include <kernel/lib/alloc.h>
+#include <kernel/fs/ata_pio.h>
+#include "marfs.h"
+
+uint8_t marfs_init(struct ATA_INTERFACE *_iface) {
+ iface = _iface;
+ uint16_t identifydata[256 * 2];
+ uint8_t ret = ATA_identify(iface, identifydata);
+ maxLBA = (identifydata[61] << 16) + identifydata[60];
+ return ret;
+}
+
+uint32_t marfs_get_max_lba(void) { return maxLBA; }
+
+uint8_t marfs_write_mbr(uint8_t *mbr) {
+ return ATA_write28(iface, 0, mbr);
+}
+
+struct marfs_SUPERBLOCK *marfs_read_superblock() {
+ struct marfs_SUPERBLOCK *p = (struct marfs_SUPERBLOCK *) ATA_read28(iface, 1);
+ sb_cache = *p;
+ return p;
+}
+
+uint8_t marfs_writeSB(struct marfs_SUPERBLOCK *sb) {
+ sb_cache = *sb;
+ return ATA_write28(iface, 1, (uint8_t *) sb);
+}
+
+uint32_t marfs_get_free_lba_block(void) {
+ uint32_t offset = 2 + sb_cache.s_first_chunk;
+ uint8_t *p = 0;
+ for (uint32_t i = 0; i < sb_cache.n_chunks; i++) {
+ p = ATA_read28(iface, offset);
+ if (!(*p & 0x80)) break;
+ kfree(p);
+ offset += 512;
+ }
+
+ offset++;
+ for (uint16_t i = 1; i < 512; i++) {
+ if (!p[i]) break;
+ offset++;
+ }
+ kfree(p);
+
+ ATA_clear28(iface, offset);
+
+ return offset;
+}
+
+static uint8_t marfs_mark_block(uint32_t lba_sector, uint8_t mode) {
+ lba_sector -= 2;
+ lba_sector -= sb_cache.s_first_chunk;
+ uint16_t block_in_chunk = lba_sector % 512;
+ lba_sector /= 512;
+ lba_sector = 2 + sb_cache.s_first_chunk + (512 * lba_sector);
+
+ uint8_t *p = ATA_read28(iface, lba_sector);
+ p[block_in_chunk] = mode;
+
+ if (mode == 0) {
+ p[0] = 0;
+ } else {
+ uint8_t full_chunk = 1;
+ for (uint16_t i = 1; i < 512; i++) {
+ if (!p[i]) {
+ full_chunk = 0;
+ break;
+ }
+ }
+ p[0] = full_chunk;
+ }
+
+ uint8_t ret = ATA_write28(iface, lba_sector, p);
+ kfree(p);
+ return ret;
+}
+
+uint8_t marfs_mark_block_as_free(uint32_t lba_sector) { return marfs_mark_block(lba_sector, 0); }
+
+uint8_t marfs_mark_block_as_used(uint32_t lba_sector) { return marfs_mark_block(lba_sector, 1); }
+
+uint32_t marfs_get_free_lba_inode(void) {
+ uint32_t offset;
+ for (offset = 2; offset < 2 + sb_cache.n_inodes; offset++) {
+ struct marfs_INODE *inode = (struct marfs_INODE *) ATA_read28(iface, offset);
+ uint8_t used = inode->isUsed;
+ kfree(inode);
+ if (!used) break;
+ }
+ return offset;
+}
+
+void marfs_mark_inode_as_free(uint32_t lba_sector) {
+ struct marfs_INODE *inode = (struct marfs_INODE *) ATA_read28(iface, lba_sector);
+ inode->isUsed = 0;
+ ATA_write28(iface, lba_sector, (uint8_t *) inode);
+ kfree(inode);
+} \ No newline at end of file
diff --git a/src/kernel/interact.asm b/src/kernel/interact.asm
index d24c79b..e2b7805 100644
--- a/src/kernel/interact.asm
+++ b/src/kernel/interact.asm
@@ -77,7 +77,7 @@ section .text
pop fs ; load fs from 16bit stack
pop es ; load es from 16bit stack
pop ds ; load ds from 16bit stack
- sti ; enable interrupts
+ ; sti ; enable interrupts
db 0xCD ; opcode of INT instruction with immediate byte
ib: db 0x00
cli ; disable interrupts
@@ -113,7 +113,7 @@ section .text
cld ; clear direction flag (so we copy forward)
rep movsb ; do the actual copy (16bit stack to 32bit stack)
popa ; restore registers
- sti ; enable interrupts
+ ; sti ; enable interrupts
ret ; return to caller
resetpic: ; reset's 8259 master and slave pic vectors
diff --git a/src/kernel/interrupts/interrupts.h b/src/kernel/interrupts/interrupts.h
index 80c9b27..cd96b7c 100644
--- a/src/kernel/interrupts/interrupts.h
+++ b/src/kernel/interrupts/interrupts.h
@@ -1,6 +1,8 @@
#ifndef MELVIX_INTERRUPTS_H
#define MELVIX_INTERRUPTS_H
+#include <stdint.h>
+
/**
* Initialize the Interrupt Descriptor Table with 256 entries
*/
@@ -21,6 +23,16 @@ void idt_set_gate(unsigned char num, unsigned long base, unsigned short sel, uns
void isrs_install();
/**
+ * Ignore interrupt
+ */
+void isr_ignore(uint8_t int_no);
+
+/**
+ * Un-ignore interrupt
+ */
+void isr_remember(uint8_t int_no);
+
+/**
* Registers that get passed into an IRQ handler
*/
struct regs {
diff --git a/src/kernel/interrupts/isr.c b/src/kernel/interrupts/isr.c
index d03a6de..0893df7 100644
--- a/src/kernel/interrupts/isr.c
+++ b/src/kernel/interrupts/isr.c
@@ -69,6 +69,8 @@ extern void isr30();
extern void isr31();
+uint32_t ignored_isr[8] = {0};
+
// Install ISRs in IDT
void isrs_install() {
idt_set_gate(0, (unsigned) isr0, 0x08, 0x8E);
@@ -151,7 +153,7 @@ const char *exception_messages[] = {
// Master exception/interrupt/fault handler - halt via panic
void fault_handler(struct regs *r) {
- if (r->int_no < 32) {
+ if (r->int_no < 32 && !(ignored_isr[r->int_no / 32] & (1 << (r->int_no % 32)))) {
uint32_t faulting_address;
asm volatile("mov %%cr2, %0" : "=r" (faulting_address));
@@ -176,3 +178,8 @@ void fault_handler(struct regs *r) {
panic(message);
}
}
+
+
+void isr_ignore(uint8_t int_no) { ignored_isr[int_no / 32] |= 1 << (int_no % 32); }
+
+void isr_remember(uint8_t int_no) { ignored_isr[int_no / 32] &= ~(1 << (int_no % 32)); }
diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c
index 3bef5c6..eb75d32 100644
--- a/src/kernel/kernel.c
+++ b/src/kernel/kernel.c
@@ -6,15 +6,17 @@
#include <kernel/paging/paging.h>
#include <kernel/input/input.h>
#include <kernel/acpi/acpi.h>
-#include <kernel/fs/initrd.h>
#include <kernel/syscall/syscall.h>
#include <kernel/smbios/smbios.h>
+#include <kernel/fs/install.h>
+#include <kernel/lib/lib.h>
extern void switch_to_user();
void kernel_main() {
vga_log("Installing basic features of Melvix...", 0);
// Install features
+ // memory_init();
timer_install();
gdt_install();
init_serial();
@@ -37,6 +39,11 @@ void kernel_main() {
// Booting process complete - emulate newline key
vesa_keyboard_char('\n');
+ uint8_t boot_drive_id = (uint8_t) (*((uint8_t *) 0x9000));
+ if (boot_drive_id == 0xE0) {
+ install_melvix();
+ }
+
// Setup initial ramdisk
/*assert(mboot_ptr->mods_count > 0);
uint32_t initrd_location = *((uint32_t *) mboot_ptr->mods_addr);
diff --git a/src/kernel/lib/alloc.c b/src/kernel/lib/alloc.c
index 85ae7db..4266676 100644
--- a/src/kernel/lib/alloc.c
+++ b/src/kernel/lib/alloc.c
@@ -4,12 +4,12 @@
#include <kernel/paging/paging.h>
int liballoc_lock() {
- asm volatile ("cli");
+ // asm volatile ("cli");
return 0;
}
int liballoc_unlock() {
- asm volatile ("sti");
+ // asm volatile ("sti");
return 0;
}
diff --git a/src/kernel/lib/alloc.h b/src/kernel/lib/alloc.h
index 5658da7..6ed9efb 100644
--- a/src/kernel/lib/alloc.h
+++ b/src/kernel/lib/alloc.h
@@ -1,6 +1,8 @@
#ifndef MELVIX_ALLOC_H
#define MELVIX_ALLOC_H
+#include <stddef.h>
+
#define PREFIX(func) k ## func
int liballoc_lock();
diff --git a/src/kernel/lib/lib.h b/src/kernel/lib/lib.h
index 5cc3d1f..c431e1d 100644
--- a/src/kernel/lib/lib.h
+++ b/src/kernel/lib/lib.h
@@ -2,6 +2,7 @@
#define MELVIX_LIB_H
#include <stddef.h>
+#include <stdint.h>
/**
* Find the length of a string
@@ -67,4 +68,8 @@ void *memset(void *dest, char val, size_t count);
*/
int memcmp(const void *a_ptr, const void *b_ptr, size_t size);
+void memory_init();
+
+uint32_t memory_get_all();
+
#endif
diff --git a/src/kernel/lib/memory.c b/src/kernel/lib/memory.c
index a030c9a..3132e05 100644
--- a/src/kernel/lib/memory.c
+++ b/src/kernel/lib/memory.c
@@ -1,4 +1,7 @@
#include <stddef.h>
+#include <stdint.h>
+#include <kernel/paging/paging.h>
+#include <kernel/io/io.h>
void *memcpy(void *dest, const void *src, size_t count) {
const char *sp = (const char *) src;
@@ -23,4 +26,36 @@ int memcmp(const void *a_ptr, const void *b_ptr, size_t size) {
return 1;
}
return 0;
-} \ No newline at end of file
+}
+
+uint32_t total_memory;
+
+struct memory_entry {
+ uint64_t base;
+ uint64_t length;
+ uint32_t type;
+} __attribute__((packed));
+
+struct memory_entry *memory_get_entries() {
+ return (struct memory_entry *) 0xA000;
+}
+
+void memory_init() {
+ uint64_t maxbase = 0;
+ uint64_t maxlength = 0;
+ for (struct memory_entry *i = memory_get_entries(); i->type; i++) {
+ if (i->type == 1 && i->base > maxbase) {
+ maxbase = i->base;
+ maxlength = i->length;
+ }
+ }
+ total_memory = maxbase + maxlength;
+ total_memory /= 1024;
+ serial_write_dec(total_memory);
+}
+
+uint32_t memory_get_free() {
+ return (total_memory) - paging_get_used_pages() * 4;
+}
+
+uint32_t memory_get_all() { return total_memory; } \ No newline at end of file
diff --git a/src/kernel/paging/paging.c b/src/kernel/paging/paging.c
index a6bf5cc..fa0610e 100644
--- a/src/kernel/paging/paging.c
+++ b/src/kernel/paging/paging.c
@@ -1,6 +1,7 @@
#include <stdint.h>
#include <kernel/paging/paging.h>
#include <kernel/system.h>
+#include <kernel/lib/lib.h>
uint32_t page_directory[1024] __attribute__((aligned(4096)));
uint32_t page_tables[1024][1024] __attribute__((aligned(4096)));
@@ -17,6 +18,7 @@ void paging_install() {
}
// TODO: Calculate max memory
+ // paging_set_present(0, memory_get_all() >> 2);
paging_set_present(0, 0x1000000);
paging_set_used(0, ((uint32_t) ASM_KERNEL_END >> 12) + 1);
diff --git a/src/kernel/timer/timer.c b/src/kernel/timer/timer.c
index 90a74cf..0e10c07 100644
--- a/src/kernel/timer/timer.c
+++ b/src/kernel/timer/timer.c
@@ -2,7 +2,7 @@
#include <kernel/io/io.h>
#include <kernel/system.h>
-static unsigned long timer_ticks = 0;
+unsigned long timer_ticks = 0;
void timer_phase(int hz) {
int divisor = (int) (3579545.0 / 3.0 / (double) hz);