diff options
33 files changed, 1382 insertions, 235 deletions
@@ -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, ®s); + 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); |