diff --git a/Makefile b/Makefile index 02d31dc..dfd3afe 100644 --- a/Makefile +++ b/Makefile @@ -24,12 +24,12 @@ filesystem: bootloader kernel $(C_FILES) $(FONTS) @dd if=/dev/zero of=kern.iso bs=512 count=2880 status=none # TODO: Make this not so manual @dd if=$(BUILD)/boot.bin of=kern.iso bs=512 seek=0 conv=notrunc status=none - @dd if=$(BUILD)/filetable.bin of=kern.iso bs=512 seek=5 conv=notrunc status=none - @dd if=$(BUILD)/kernel.bin of=kern.iso bs=512 seek=6 conv=notrunc status=none - @dd if=$(BUILD)/term16n.bin of=kern.iso bs=512 seek=46 conv=notrunc status=none - @dd if=$(BUILD)/testfont.bin of=kern.iso bs=512 seek=50 conv=notrunc status=none - @dd if=$(SRC)/fs/test.txt of=kern.iso bs=512 seek=54 conv=notrunc status=none - @dd if=$(BUILD)/calc.bin of=kern.iso bs=512 seek=55 conv=notrunc status=none + @dd if=$(BUILD)/filetable.bin of=kern.iso bs=512 seek=15 conv=notrunc status=none + @dd if=$(BUILD)/kernel.bin of=kern.iso bs=512 seek=16 conv=notrunc status=none + @dd if=$(BUILD)/term16n.bin of=kern.iso bs=512 seek=56 conv=notrunc status=none + @dd if=$(BUILD)/testfont.bin of=kern.iso bs=512 seek=60 conv=notrunc status=none + @dd if=$(SRC)/fs/test.txt of=kern.iso bs=512 seek=64 conv=notrunc status=none + @dd if=$(BUILD)/calc.bin of=kern.iso bs=512 seek=65 conv=notrunc status=none $(BUILD): @[ -d $(BUILD) ] || mkdir $(BUILD) @@ -41,14 +41,18 @@ bootloader: $(SRC)/stage1.asm $(SRC)/stage2.asm @$(AS) -fbin -o $(BUILD)/stage1.bin $(SRC)/stage1.asm @echo "Assembling $(SRC)/stage2.asm..." @$(AS) -fbin -o $(BUILD)/stage2.bin $(SRC)/stage2.asm - @cat $(BUILD)/stage1.bin $(BUILD)/stage2.bin > $(BUILD)/boot.bin + @echo "Compiling $(SRC)/stage3.c..." + @$(CC) $(CFLAGS) -Iinclude -o $(BUILD)/stage3.o -c $(SRC)/stage3.c + @$(LD) -T$(SRC)/stage3.ld -z notext --oformat binary -o $(BUILD)/stage3.bin $(BUILD)/stage3.o + @cat $(BUILD)/stage1.bin $(BUILD)/stage2.bin $(BUILD)/stage3.bin > $(BUILD)/boot.bin + @rm $(BUILD)/stage3.o # Kernel: This target is responsible for creating kernel.bin kernel: $(SRC)/kernel.c @echo "Compiling $(SRC)/kernel.c..." @$(CC) $(CFLAGS) -Iinclude -o $(BUILD)/kernel.o -c $(SRC)/kernel.c @$(LD) -T$(SRC)/kernel.ld -z notext --oformat binary -o $(BUILD)/kernel.bin $(BUILD)/kernel.o - @rm $(BUILD)/*.o + @rm $(BUILD)/kernel.o $(C_FILES): @echo "Compiling $(SRC)/$@.c..." diff --git a/README.md b/README.md index bc2a713..e3d415c 100644 --- a/README.md +++ b/README.md @@ -53,9 +53,10 @@ Graphics test: \ _These images may be outdated, Idk_ ## Known issues -- If you run kernel.bin from shell, it will clear the memory map so when you load anything it will override the kernel code +- If you run any of the bootloader stages or kernel form the shell, it will most likely break. (Maybe add an executable flag?) - fillCircle() in graphics.h is broken. No idea why, so no filled circles for you (i commented out the boundaryFill call in the function) - convertColor() doesn't work right, because i should be using floating point, but -mgeneral-regs-only doesn't let me :( +- The soundtest command is very likely to get stuck on a note and play it forever. (Maybe a Sleep() bug?) - Not really an issue, bit QEMU's PIT is really slow and inacurate ## [Old Version](https://github.com/Tom-on64/old-kern) diff --git a/include/disk/filesys.h b/include/disk/filesys.h index 235c219..201aa6f 100644 --- a/include/disk/filesys.h +++ b/include/disk/filesys.h @@ -48,14 +48,15 @@ void updateFiletable() { // TODO: Update the filetable by writing data from memory to disk! } -void readFile(char* filename, void* buffer) { // Hopefully the buffer is large enought :/ +uint8_t readFile(char* filename, void* buffer) { // Hopefully the buffer is large enought :/ fileEntry_t* file = findFile(filename); - if (file == NULL) { return; } // File doesn't exist! + if (file == NULL) { return 1; } // File doesn't exist! diskRead(file->startAddress, file->length, buffer); + return 0; // Success } -void writeFile(char* filename, void* buffer) { // TODO: Add length so we don't write too much/too little +uint8_t writeFile(char* filename, void* buffer) { // TODO: Add length so we don't write too much/too little fileEntry_t* file = findFile(filetable); if (file == NULL) { // File exists -> override // File doesn't exist -> create new file @@ -74,6 +75,7 @@ void writeFile(char* filename, void* buffer) { // TODO: Add length so we don't w } diskWrite(file->startAddress, file->length, buffer); // Write the file + return 0; // Success } void printFiletable(char* ft) { diff --git a/include/memory/addresses.h b/include/memory/addresses.h index 9eb0da7..68c5e57 100644 --- a/include/memory/addresses.h +++ b/include/memory/addresses.h @@ -1,10 +1,18 @@ #ifndef ADDRESSES_H #define ADDRESSES_H -#define MEMMAP_AREA 0x30000 -#define KERNEL_LOC 0x50000 -#define FILETABLE_LOC 0x7000 -#define SMAP_ENTRY_COUNT 0x8500 -#define SMAP_ENTRIES 0x8504 +// Locations +#define KERNEL_LOC 0x100000 +#define FILETABLE_LOC 0x7000 + +// Physical memory manager +#define MEMMAP_AREA 0x30000 +#define SMAP_ENTRY_COUNT 0x8500 +#define SMAP_ENTRIES 0x8504 +#define PHYS_MEM_MAX_BLOCKS 0x1804 +#define PHYS_MEM_USED_BLOCKS 0x1808 + +// Virtual memory manager +#define CURRENT_PAGE_DIR_ADDR 0x1800 #endif diff --git a/src/filetable.asm b/src/filetable.asm index f1f991d..c1e211c 100644 --- a/src/filetable.asm +++ b/src/filetable.asm @@ -10,13 +10,15 @@ ;; filetable: - db "boot",0,0,0,0,0,0, "bin",0,0,5 - db "filetable",0, "tab",0,5,1 - db "kernel",0,0,0,0, "bin",0,6,40 - db "term16n",0,0,0, "fnt",0,46,4 - db "testfont",0,0, "fnt",0,50,4 - db "test",0,0,0,0,0,0, "txt",0,54,1 - db "calc",0,0,0,0,0,0, "bin",0,55,2 + db "boot",0,0,0,0,0,0, "bin",0,0,1 + db "stage2",0,0,0,0, "bin",0,1,4 + db "stage3",0,0,0,0, "bin",0,5,10 + db "filetable",0, "tab",0,15,1 + db "kernel",0,0,0,0, "bin",0,16,40 + db "term16n",0,0,0, "fnt",0,56,4 + db "testfont",0,0, "fnt",0,60,4 + db "test",0,0,0,0,0,0, "txt",0,64,1 + db "calc",0,0,0,0,0,0, "bin",0,65,2 times 512-($-$$) db 0 diff --git a/src/kernel.c b/src/kernel.c index 9576b9f..8f95254 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -29,7 +29,12 @@ void printPhysicalMemmap(); __attribute__ ((section("entry"))) void main() { - diskRead(5, 1, filetable); + // Retrieve global variables + currentPd = (pageDirectory_t*)*(uint32_t*)CURRENT_PAGE_DIR_ADDR; // Don't ask + memoryMap = (uint32_t*)MEMMAP_AREA; + maxBlocks = *(uint32_t*)PHYS_MEM_MAX_BLOCKS; + usedBlocks = *(uint32_t*)PHYS_MEM_USED_BLOCKS; + // Interrupt setup setupIdt(); setupExceptions(); @@ -42,40 +47,11 @@ void main() { setupTimer(); setupRtc(); setupKeyboard(); - - // Physical memory manager setup - uint32_t smapEntryCount = *(uint32_t*)SMAP_ENTRY_COUNT; - smapEntry_t* smapEntries = (smapEntry_t*)SMAP_ENTRIES; // After a unit32_t - uint32_t totalMemory = smapEntries[smapEntryCount - 1].baseAddress + smapEntries[smapEntryCount - 1].length - 1; - - setupPhysicalMemoryManager(MEMMAP_AREA, totalMemory); - - for (uint32_t i = 0; i < smapEntryCount; i++) { - if (smapEntries[i].type == 1) { - initMemoryRegion(smapEntries[i].baseAddress, smapEntries[i].length); - } - } - - deinitMemoryRegion(0x1000, 0x9000); // Reserve kernel memory (under 0xa000) - deinitMemoryRegion(MEMMAP_AREA, maxBlocks / BLOCKS_PER_BYTE); - - // Virtual memory manager setup - setupVirtualMemoryManager(); // TODO: Check if it succeeds - - // Identity map VBE framebuffer - uint32_t fbSize = (gfxMode->yRes * gfxMode->linearBytesPerScanline) / PAGE_SIZE; - if (fbSize % PAGE_SIZE > 0) { fbSize++; } - fbSize *= 2; // Double for hardware - for (uint32_t i = 0, fbStart = gfxMode->physicalBasePtr; i < fbSize; i++, fbStart += PAGE_SIZE) { - mapPage((void*)fbStart, (void*)fbStart); - } - deinitMemoryRegion(gfxMode->physicalBasePtr, fbSize * BLOCK_SIZE); - + // Screen setup readFile("term16n.fnt", font); clear(); print("kern.\n\n"); - // Run Interactive Shell Program // TODO: Make it in another file diff --git a/src/kernel.ld b/src/kernel.ld index d96c31e..3eb2768 100644 --- a/src/kernel.ld +++ b/src/kernel.ld @@ -1,5 +1,5 @@ SECTIONS { - .text 0x50000 : { + .text 0xC0000000 : { *(entry); *(.text*); } diff --git a/src/stage1.asm b/src/stage1.asm index 9d881a0..611d9c9 100644 --- a/src/stage1.asm +++ b/src/stage1.asm @@ -3,8 +3,7 @@ [global start] %define VIDMEM 0xb800 -%define FILETAB_LOC 0x7000 ; TODO: Read kernel size and location from ft -%define KERNEL_SIZE 40 ; 20kB +%define FILETAB_LOC 0x7000 start: mov [driveNum], dl ; Store the drive number @@ -37,7 +36,7 @@ start: mov ah, 2 ; Read from disk int 0x13 ; Read interrupt - jnc loadKernel + jnc loadPrekernel dec byte [counter] jnz .read @@ -58,20 +57,20 @@ diskErr: cli hlt -loadKernel: +loadPrekernel: mov byte [counter], 3 .read: ; Location - mov ax, 0x5000 ; Making es 0x5000 will load the kernel at 0x50000 + mov ax, 0x5000 ; Making es 0x5000 will load the prekernel at 0x50000 mov es, ax xor bx, bx ; CHS Location - mov al, KERNEL_SIZE + mov al, 10 ; Prekernel size mov ch, 0 ; Cylinder mov dh, 0 ; Head - mov cl, 7 ; Sector + mov cl, 6 ; Sector mov dl, [driveNum] mov ah, 2 ; Read from disk diff --git a/src/stage2.asm b/src/stage2.asm index f8c3dd0..df88724 100644 --- a/src/stage2.asm +++ b/src/stage2.asm @@ -1,7 +1,7 @@ [bits 16] [org 0x7e00] -%define KERNEL_LOC 0x50000 +%define STAGE3_LOC 0x50000 %define VIDMEM 0xb800 start: @@ -324,7 +324,7 @@ protected_start: rep movsd ; Perform The far jump - jmp CODE_SEG:KERNEL_LOC + jmp CODE_SEG:STAGE3_LOC ;; Data driveNum: db 0 diff --git a/src/stage3.c b/src/stage3.c new file mode 100644 index 0000000..88f29d1 --- /dev/null +++ b/src/stage3.c @@ -0,0 +1,62 @@ +#include +#include +#include +#include +#include +#include + +__attribute__ ((section("entry"))) +void main() { + diskRead(15, 1, filetable); // Load filetable into memory; TODO: Make a filetableUpdate() function that just keeps the stored and memory verisons in sync + + // Physical memory manager setup + uint32_t smapEntryCount = *(uint32_t*)SMAP_ENTRY_COUNT; + smapEntry_t* smapEntries = (smapEntry_t*)SMAP_ENTRIES; // After a unit32_t + uint32_t totalMemory = smapEntries[smapEntryCount - 1].baseAddress + smapEntries[smapEntryCount - 1].length - 1; + + setupPhysicalMemoryManager(MEMMAP_AREA, totalMemory); + + for (uint32_t i = 0; i < smapEntryCount; i++) { + if (smapEntries[i].type == 1) { + initMemoryRegion(smapEntries[i].baseAddress, smapEntries[i].length); + } + } + + deinitMemoryRegion(0x1000, 0x9000); // Reserve kernel memory (under 0xa000) + deinitMemoryRegion(MEMMAP_AREA, maxBlocks / BLOCKS_PER_BYTE); + + // Load kernel into memory + if (readFile("kernel.bin", (void*)KERNEL_LOC) != 0) { // Check if kernel.bin was loaded + // TODO: Add error messages + while (1); + } + + // Virtual memory manager setup + if (setupVirtualMemoryManager() != 0) { + while (1); + } + + // Identity map VBE framebuffer + uint32_t fbSize = (gfxMode->yRes * gfxMode->linearBytesPerScanline) / PAGE_SIZE; + if (fbSize % PAGE_SIZE > 0) { fbSize++; } + fbSize *= 2; // Double for hardware + for (uint32_t i = 0, fbStart = gfxMode->physicalBasePtr; i < fbSize; i++, fbStart += PAGE_SIZE) { + mapPage((void*)fbStart, (void*)fbStart); + } + deinitMemoryRegion(gfxMode->physicalBasePtr, fbSize * BLOCK_SIZE); + + *(uint32_t*)PHYS_MEM_MAX_BLOCKS = maxBlocks; + *(uint32_t*)PHYS_MEM_USED_BLOCKS = usedBlocks; + + for (uint32_t virt = KERNEL_LOC; virt < 0x400000; virt += PAGE_SIZE) { + unmapPage((void*)virt); + } + + __asm__ volatile ("movl %cr3, %ecx; movl %ecx, %cr3"); + + *(uint32_t*)CURRENT_PAGE_DIR_ADDR = (uint32_t)currentPd; + + // Call/jump to kernel + ((void(*)(void))0xC0000000)(); +} + diff --git a/src/stage3.ld b/src/stage3.ld new file mode 100644 index 0000000..4d10518 --- /dev/null +++ b/src/stage3.ld @@ -0,0 +1,16 @@ +/* Third stage "prekernel" */ +SECTIONS { + .text 0x50000 : { + *(entry); + *(.text*); + } + .data : { + *(.data*); + } + .rodata : { + *(.rodata*); + } + .bss : { + *(.bss*); + } +}