Some file restructuring

This commit is contained in:
2024-10-10 10:03:58 +02:00
parent 886a802cc1
commit 63ecaec569
16 changed files with 3228 additions and 11 deletions
+167
View File
@@ -0,0 +1,167 @@
[bits 16]
[org 0x7c00]
%define SUPERBLOCK 0x8c00
%define FIRST_INODE_BLOCK (SUPERBLOCK) + 18
%define STAGE3_INODE 0xb000 + (2 * 64)
%define EXTENT0 (STAGE3_INODE) + 14 ; Offset of extent[0] in inode_t
start:
xor ax, ax
mov es, ax
mov ds, ax
mov byte [driveNum], dl
; Clear screen
mov ax, 0x03
int 0x10
;; Read in the boot block and the superblock to memory for 2nd stage bootloader
mov al, 15 ; 8 - 1 for boot block - bootsector & 8 for super block
mov bl, al
dec bl ; Number of sectors - 1
mov di, 0x7E00 ; Destination 0x7c00-0x8c00 = boot block, 0x8c00-0x9c00 = superblock
mov dx, 0x1F6 ; flags
mov al, 0xE0 ; 0b0111 0000, bits: 0-3 = LBA bits 24-27, 4 = drive, 5 = always set, 6 = set for LBA, 7 = always set
out dx, al
mov dx, 0x1F2 ; Sector count port
mov al, 15 ; number of sectors to read
out dx, al
inc dx ; 0x1F3 - LBA low
mov al, 1 ; LBA 1 = 2nd disk sector (0-based), bits 0-7 of LBA
out dx, al
inc dx ; 0x1F4 - LBA mid
xor ax, ax ; bits 8-15 of LBA
out dx, al
inc dx ; 0x1F5 - LBA high
; xor ax, ax ; bits 16-23 of LBA
out dx, al
inc dx
inc dx ; 0x1F7 - Command port
mov al, 0x20 ; Read with retry
out dx, al
call loadSectorLoop
;; Parse superblock for first inode block, offset to reserved bootloader
;; Read first inode block to memory
;; Each disk block is 4KB or 8 sectors of 512 bytes
imul cx, [FIRST_INODE_BLOCK], 8 ; CX = disk sector/LBA of first inode block
mov bl, 7 ; 8 sectors for a block - 1
mov di, 0xb000 ; Address to read into, first inode block = 0xB000-0xC000
mov dx, 0x1F6 ; flags
mov al, 0xE0
out dx, al
mov dx, 0x1F2
mov al, 8
out dx, al
inc dx
mov al, cl
out dx, al
inc dx
mov al, ch
out dx, al
inc dx
xor ax, ax
out dx, al
inc dx
inc dx
mov al, 0x20
out dx, al
call loadSectorLoop
;; Read boot loader inode to memory
;; inode 2, each inode is 64 bytes in size
imul ecx, [EXTENT0], 8 ; first_block translated to disk sector/LBA
imul ebx, [EXTENT0+4], 8 ; length_blocks translated to disk sectors/LBAs
mov dx, 0x1F2
mov al, bl
out dx, al
inc dx
mov al, cl
out dx, al
inc dx
mov al, ch
out dx, al
inc dx
shr ecx, 16
mov al, cl
out dx, al
inc dx
and ch, 0x0F
mov al, ch
or al, 0xE0
out dx, al
inc dx
mov al, 0x20
out dx, al
dec bl
mov ax, 0x5000
mov es, ax
xor di, di
call loadSectorLoop
xor ax, ax
mov es, ax ; ES = 0x0000
;; Jump to 2nd stage bootloader here, does not return
mov dl, [driveNum]
jmp 0x0000:0x7E00
;; Poll status port after reading 1 sector
loadSectorLoop:
in al, dx ; Status register (reading port 1F7h)
test al, 8 ; Sector buffer requires servicing
je loadSectorLoop ; Keep trying until sector buffer is ready
mov cx, 256 ; # of words to read for 1 sector
mov dx, 0x1F0 ; Data port, reading
rep insw ; Read bytes from DX port # into DI, CX # of times
;; 400ns delay - Read alternate status register
mov dx, 0x3F6
in al, dx
in al, dx
in al, dx
in al, dx
cmp bl, 0 ; Sector # to still read
je .return
dec bl
mov dx, 0x1F7
jmp loadSectorLoop
.return:
ret
;; VARIABLES
driveNum: db 0
;; Boot sector magic
times 510-($-$$) db 0 ; Padding
dw 0xaa55
+472
View File
@@ -0,0 +1,472 @@
[bits 16]
[org 0x7e00]
%define STAGE3_LOC 0x50000
%define MODE_INFO_BLOCK_LOC 0x6000
start:
mov [driveNum], dl
; Physical memory map setup
xor ax, ax
mov es, ax
memMapEntries equ 0x7000
getMemoryMap:
mov di, memMapEntries + 4 ; 4 bytes after memMapEntries
xor ebx, ebx
xor bp, bp
mov edx, "PAMS" ; SMAP in little endian
mov eax, 0xe820
mov dword [es:di+20], 1 ; Force valid ACPI 3.X entry
mov ecx, 24
int 0x15
jc .error
cmp eax, "PAMS"
jne .error
test ebx, ebx
jnz .start
.error:
stc
jmp inputGfx
.nextEntry:
mov edx, "PAMS" ; In case BIOS messes with edx
mov ecx, 24
mov eax, 0xe820
int 0x15
.start:
jcxz .skipEntry
mov ecx, [es:di+8] ; Low 32 bits of length
or ecx, [es:di+12] ; High 32 bits of length
jz .skipEntry
; Valid entry
inc bp
add di, 24 ; Next entry
.skipEntry:
test ebx, ebx
jz .done
jmp .nextEntry
.done:
mov [memMapEntries], bp
clc
;; Get graphics values from user (resolution etc.)
inputGfx:
xor ecx, ecx
cmp word [width], 0 ; Values already set
jne vbeSetup
mov si, gfxChooseMsg
call print
call getNumber ; Stores input value in bx
mov [width], bx
mov si, gfxHeightMsg
call print
call getNumber
mov [height], bx
mov si, gfxBppMsg
call print
call getNumber
mov [bpp], bx
vbeSetup:
; Setup VBE info
xor ax, ax
mov es, ax
mov ax, 0x4f00
mov di, vbeInfoBlock
int 0x10
cmp ax, 0x4f
jne error
mov ax, word [vbeInfoBlock.videoModePtr]
mov [offset], ax
mov ax, word [vbeInfoBlock.videoModePtr+2]
mov [_segment], ax
mov fs, ax
mov si, [offset]
;; Get next VBE mode
.findMode:
mov dx, [fs:si]
inc si
inc si
mov [offset], si
mov [mode], dx
cmp dx, 0xffff ; Indicates end of modes
je .endOfModes
mov ax, 0x4f01 ; Get VBE mode info
mov cx, [mode]
mov di, modeInfoBlock
int 0x10
cmp ax, 0x4f
jne error
; Print values (Debug)
; mov ax, [modeInfoBlock.xRes]
; ror ax, 8
; call printHex
; ror ax, 8
; call printHex
; mov ax, 0x0e20
; int 0x10
; mov ax, [modeInfoBlock.yRes]
; ror ax, 8
; call printHex
; ror ax, 8
; call printHex
; mov ax, 0x0e20
; int 0x10
; xor ax, ax
; mov al, [modeInfoBlock.bpp]
; call printHex
; mov ax, 0x0e20
; int 0x10
; mov al, 0x0a
; int 0x10
; mov al, 0x0d
; int 0x10
; Check if it is the right mode
mov ax, [width]
cmp ax, [modeInfoBlock.xRes]
jne .nextMode
mov ax, [height]
cmp ax, [modeInfoBlock.yRes]
jne .nextMode
mov al, [bpp]
cmp al, [modeInfoBlock.bpp]
jne .nextMode
; Set VBE mode
mov ax, 0x4f02
mov bx, [mode]
or bx, 0x4000 ; Set 14th bit to 1
xor di, di
int 0x10
cmp ax, 0x4f
jne error
jmp loadGDT
.nextMode:
mov ax, [_segment]
mov fs, ax
mov si, [offset]
jmp .findMode
.endOfModes:
mov ax, 0x03
int 0x10 ; Clear screen
mov si, gfxModeNotFoundErr
call print
mov word [width], 0 ; Unset values
jmp inputGfx
error:
mov si, vbeErr
call print
cli
hlt
;; Load the global descriptor table (GDT)
loadGDT:
cli
lgdt [GDT_Descriptor]
; Enable protected mode
mov eax, cr0
or eax, 1
mov cr0, eax
; Far jump to 32 bit mode!!
jmp CODE_SEG:protected_start
;;
;; Prints a hex byte
;; al - value to print
;;
printHex:
push ax
push bx
mov bh, 2
mov bl, al
and al, 0xf0
ror al, 4
mov ah, 0x0e ; For printing
.printNibble:
cmp al, 10
jl .print
add al, 39
.print:
add al, 48 ; ASCII Char
int 0x10
dec bh
jz .done
mov al, bl
and al, 0x0f
jmp .printNibble
.done:
pop bx
pop ax
ret
;;
;; Prints a null terminated string
;; si - pointer to string
;;
print:
push ax
mov ah, 0x0e
.loop:
lodsb ; mov al, [si] inc si
cmp al, 0
je .done
int 0x10
jmp .loop
.done:
pop ax
ret
;;
;; Reads a base 10 number as input from user
;; Returns:
;; bx - number read
;;
getNumber: ; TODO: if user enters a number that overflows (n > 0xffff) shit breaks
push cx
push ax
push dx
xor bx, bx
mov cx, 10
.nextDigit:
xor ah, ah
int 0x16
mov ah, 0x0e
cmp al, 0x08 ; Backspace
je .backspace
cmp al, 0x0d ; Enter
je .enter
cmp al, '0' ; Make sure user entered a number
jl .nextDigit
cmp al, '9'
jg .nextDigit
int 0x10 ; Print the digit
sub al, '0' ; Convert to integer
mov ah, 0
imul bx, bx, 10 ; bx *= 10
add bx, ax ; bx += ax
jmp .nextDigit
.backspace:
cmp bx, 0 ; Check if we can backspace
je .nextDigit
int 0x10 ; go back one space
mov ax, bx
xor dx, dx
div cx ; dx:ax / cx -> ax = result, dx = remainder
mov bx, ax
mov ah, 0x0e
mov al, ' '
int 0x10
mov al, 0x08
int 0x10
jmp .nextDigit
.enter:
pop dx
pop ax
pop cx
ret
;; 32 Bit entry code
[bits 32]
protected_start:
; Set up data and stack segments
mov ax, DATA_SEG
mov ds, ax
mov ss, ax
mov es, ax
mov fs, ax
mov gs, ax
; Set up the stack pointer in protected mode
mov ebp, 0x90000
mov esp, ebp
; Store VBE Mode Info Block in memory
mov esi, modeInfoBlock
mov edi, MODE_INFO_BLOCK_LOC ; Destination
mov ecx, 64 ; 64 * 4 = 256B (size of modeInfoBlock)
rep movsd
; Perform The far jump
jmp CODE_SEG:STAGE3_LOC
;; Data
driveNum: db 0
vbeErr: db "VBE Error!", 0
acpiFuncErr: db "ACPI Function not supported!", 0
gfxChooseMsg: db "Please enter desired values" ; No NULL terminator, we want to print gfxWidthMsg right after anyway
gfxWidthMsg: db 0x0a, 0x0d, "Width: ", 0
gfxHeightMsg: db 0x0a, 0x0d, "Height: ", 0
gfxBppMsg: db 0x0a, 0x0d, "Bits Per Pixel: ", 0
gfxModeNotFoundErr: db "Mode not found! ", 0
;; GDT
GDT:
.start:
.nullDescriptor: ; No clue why this exists
dd 0
dd 0
.codeDescriptor: ; Memory for code
dw 0xffff ; First 16 bits of limit
dw 0 ; 16 bits +
db 0 ; + 8 bits = 24 bits
db 0b10011010 ; p, dpl, s, type flags
db 0b11001111 ; Other flags, last 4 bits of limit
db 0 ; Base
.dataDescriptor: ; Memory for data
dw 0xffff ; First 16 bits of limit
dw 0 ; 16 bits +
db 0 ; + 8 bits = 24 bits
db 0b10010010 ; p, dpl, s, type flags
db 0b11001111 ; Other flags, last 4 bits of limit
db 0 ; Base
.end:
GDT_Descriptor:
dw GDT.end - GDT.start - 1 ; Size
dd GDT.start ; GDT Pointer
CODE_SEG equ GDT.codeDescriptor - GDT.start
DATA_SEG equ GDT.dataDescriptor - GDT.start
;; VBE Stuff
; Default width
%ifndef DEF_W
%define DEF_W 0
%endif
; Default height
%ifndef DEF_H
%define DEF_H 0
%endif
; Default bpp
%ifndef DEF_BPP
%define DEF_BPP 0
%endif
; Use defaults
%ifdef DEF_RES
width: dw DEF_W
%else
width: dw 0
%endif
height: dw DEF_H
bpp: db DEF_BPP
offset: dw 0
_segment: dw 0 ; segment is a keyword
mode: dw 0
times (512*2)-($-$$) db 0 ; End Sector 2
;; Sector 2
vbeInfoBlock:
.vbeSigniture: db "VBE2"
.vbeVersion: dw 0x0300 ; BCD Version
.oemStringPtr: dd 0
.capibilities: dd 0
.videoModePtr: dd 0
.totalMemory: dw 0
.oemSoftwareRev: dw 0
.oemVendorNamePtr: dd 0
.oemProductNamePtr: dd 0
.oemProductRevisionPtr: dd 0
.reserved: times 222 db 0
.oemData: times 256 db 0
;; Sector 3
modeInfoBlock:
;; Required by all VBE revisions
.modeAttr: dw 0
.windowAAtrr: db 0
.windowBAttr: db 0
.windowGranularity: dw 0
.windowSize: dw 0
.windowASegment: dw 0
.windowBSegment: dw 0
.windowFunctionPtr: dd 0
.bytesPerScanline: dw 0
;; Required by VBE 1.2+
.xRes: dw 0
.yRes: dw 0
.xCharSize: db 0
.yCharSize: db 0
.planeCount: db 0
.bpp: db 0
.bankCount: db 0
.memoryModel: db 0
.bankSize: db 0
.imagePageCount: db 0
.reserved1: db 1
;; Direct color fields
.redMaskSize: db 0
.redFieldPos: db 0
.greenMaskSize: db 0
.greenFieldPos: db 0
.blueMaskSize: db 0
.blueFieldPos: db 0
.reservedMaskSize: db 0
.reservedFieldPos: db 0
.directColorModeInfo: db 0
;; Required by VBE 2.0+
.physicalBasePtr: dd 0
.reserved2: dd 0
.reserved3: dw 0
;; Required by VBE 3.0+
.linearBytesPerScanline: dw 0
.bankImagePageCount: db 0
.linearImagePageCount: db 0
.linearRedMaskSize: db 0
.linearRedFieldPos: db 0
.linearGreenMaskSize: db 0
.linearGreenFieldPos: db 0
.linearBlueMaskSize: db 0
.linearBlueFieldPos: db 0
.linearReservedMaskSize: db 0
.linearReservedFieldPos: db 0
.maxPixelClock: dd 0
.reserved4: times 190 db 0
times (512*4)-($-$$) db 0
+83
View File
@@ -0,0 +1,83 @@
#include <memory/physical.h>
#include <memory/virtual.h>
#include <memory/addresses.h>
#include <screen/gfxmode.h>
#include <screen/text.h>
#include <error/bigerr.h>
#include <disk/disk.h>
#include <fs/impl.h>
#include <fs/fs.h>
#include <stdio.h>
__attribute__ ((section("entry")))
void main() {
// Physical memory manager setup
uint32_t smapEntryCount = *(uint32_t*)SMAP_ENTRY_COUNT;
smapEntry_t* smapEntries = (smapEntry_t*)SMAP_ENTRIES;
smapEntries += smapEntryCount - 1;
uint32_t totalMemory = smapEntries->baseAddress + smapEntries->length - 1;
setupPhysicalMemoryManager(MEMMAP_AREA, totalMemory);
smapEntries = (smapEntry_t*)SMAP_ENTRIES;
for (uint32_t i = 0; i < smapEntryCount; i++) {
if (smapEntries[i].type == 1) {
initMemoryRegion(smapEntries[i].baseAddress, smapEntries[i].length);
}
}
deinitMemoryRegion(0x1000, 0x11fff); // Reserve kernel memory (under 0x12000)
deinitMemoryRegion(MEMMAP_AREA, maxBlocks / BLOCKS_PER_BYTE);
// Load root dir, find kernel INode and parse it
superblock_t* sb = (superblock_t*)SUPERBLOCK_LOC;
sb->rootInodePtr = BOOT_FIRST_INODE_LOC + sizeof(inode_t);
inode_t* root = (inode_t*)sb->rootInodePtr;
loadFile(root, (void*)SCRATCH_BLOCK_LOC);
inode_t* inode;
if ((inode = getInode("kernel.bin", (dirEntry_t*)SCRATCH_BLOCK_LOC)) == NULL) {
// kernel.bin doesn't exist??? very bad -> error
bigError(0xDEAD);
} else { loadFile(inode, (void*)KERNEL_LOC); }
font_t* font = (font_t*)FONT_LOC;
if ((inode = getInode("term16n.fnt", (dirEntry_t*)SCRATCH_BLOCK_LOC)) != NULL) {
loadFile(inode, font);
} else if ((inode = getInode("testfont.fnt", (dirEntry_t*)SCRATCH_BLOCK_LOC)) != NULL) {
loadFile(inode, font);
} else {
// No font found, bad.
bigError(0xBeef);
}
// Virtual memory manager setup
if (setupVirtualMemoryManager() != 0) {
bigError(0xCafe);
}
// 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)();
bigError(0xffffffff);
}
+16
View File
@@ -0,0 +1,16 @@
/* Third stage "prekernel" */
SECTIONS {
.text 0x50000 : {
*(entry);
*(.text*);
}
.data : {
*(.data*);
}
.rodata : {
*(.rodata*);
}
.bss : {
*(.bss*);
}
}