Began work on new bootloader (KBOOT)

This commit is contained in:
2024-12-26 23:08:06 +01:00
parent bad812554d
commit 12b07a9f70
8 changed files with 246 additions and 870 deletions
+137
View File
@@ -0,0 +1,137 @@
; KBOOT - Kern Bootloader
; Most of the code is taken from Limine (https://github.com/limine-bootloader/limine)
; I tried to add more documentation than the Limine code had, but it's not everything
; Any of my code is pretty bad, so i recommend using an existing bootloader
[org 0x7c00]
[bits 16]
start:
jmp .bpb_end
; Some BIOSes will override the FAT BPB area,
; so we just fill it out to avoid pottentially
; overriding bootloader code.
; Source: https://github.com/limine-bootloader/limine/blob/trunk/stage1/hdd/bootsect.asm
.bpb:
times 3-($-$$) db 0
.bpb_oem_id: db "KBOOT "
.bpb_sector_size dw 512
.bpb_sects_per_clust: db 0
.bpb_reserved_sects: dw 0
.bpb_fat_count: db 0
.bpb_root_dir_entries: dw 0
.bpb_sector_count: dw 0
.bpb_media_type: db 0
.bpb_sects_per_fat: dw 0
.bpb_sects_per_track: dw 18
.bpb_heads_count: dw 2
.bpb_hidden_sects: dd 0
.bpb_sect_count_big: dd 0
.bpb_drive_num: db 0
.bpb_reserved: db 0
.bpb_signature: db 0
.bpb_volume_id: dd 0
.bpb_volume_label: db "KBOOT "
.bpb_filesystem_type: times 8 db 0
.bpb_end:
cli
cld
jmp 0x0000:.init_codeseg ; Long jump to set CS = 0
; Zero out segment regs (Because segmentation is shit)
.init_codeseg:
xor si, si ; We cannot change segment regs directly
mov ds, si ; Data Segment
mov es, si ; Extra Segment
mov ss, si ; Stack Segment
mov sp, 0x7c00 ; Set Stack Pointer
sti
; We probably won't be booting from a floppy, so
; ignore if boot drive is < 0x80 and assume an error
cmp dl, 0x80
jl err.0
; Also anything above 0x8f is "dubious" so we also
; just assume an error
cmp dl, 0x8f
jg err.1
; Check that int 13h extensions are supported
.int13chk:
mov ah, 0x41
mov bx, 0x55aa ; Expects bx to be this magic value
int 0x13 ; Will se CF if unsupported
jc err.2
cmp bx, 0xaa55 ; Also sets bx to this magic
jne err.3
; Load the stage 2 bootloader code to 0x70000
.load_stage2:
push 0x7000
pop es ; ES = 0x7000
xor bx, bx ; ES:BX = 0x70000
mov eax, 512
xor ebp, ebp
mov ecx, 512
call read_sectors
jc err.4 ; CF was set -> failed to read from disk
.enable_protected:
; Load GDT Pointer
lgdt [gdtp]
; Set PE (Protected mode Enable) flag
cli
mov eax, cr0
or eax, 1 ; Bit 1 - PE
mov cr0, eax
; Far jump to protected mode
jmp code_seg:vector
%include "disk.s" ; Disk I/O helper functions
%include "gdt.s" ; Global Descriptor Table
; Handles an error
err:
; Error codes
.4: inc si ; Failed to read stage2 from disk
.3: inc si ; Int 13h extensions unsupported (BX wasn't magic)
.2: inc si ; Int 13h extensions unsupported (CF was set)
.1: inc si ; Invalid boot drive number (> 0x8f)
.0: ; Invalid boot drive number (< 0x80)
; Common error handler
add si, '0' | (0x4f << 8) ; Store error code number char in SI, white on red
push 0xb800 ; VGA Text mode video memory
pop es ; ES = 0xb800
mov word [es:0], si ; Write character
; Hang
sti
.h: hlt
jmp .h
[bits 32]
; Protected mode entry vector
vector:
mov eax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
and edx, 0xff
; Call stage 2 bootloader
call 0x70000
; Padding and boot signature
times 510-($-$$) db 0
dw 0xaa55
; === STAGE 2 ===
align 16
incbin 'stage2.bin'
+80
View File
@@ -0,0 +1,80 @@
; Reads sectors from disk
; Args:
; eax - LBA low 32 bits
; ebp - LBA high 32 bits
; dl - Drive number
; es - Destination segment
; bx - Destination offset
; ecx - Byte count
; Rets:
; CF - Set on error
read_sectors:
pusha
; Fill out Disk Address Packet
mov si, .da_packet
mov word [si], 0x10 ; Packet Size and Unused
mov word [si+2], 1 ; Sector count
mov word [si+4], bx ; Dest. offset
mov word [si+6], es ; Dest. segment
; Store some regs for later
push dx
push si
push eax
push ebp
; Get bytes per sector
mov ah, 0x48 ; Extended read drive parameters
mov si, .drive_params ; DS:SI - result buffer
mov word [si], 0x1e ; Buffer size
int 0x13
jc .done ; CF set - error; we never pop ebp, eax, si & dx! (could cause issues)
mov bp, word [si+24] ; Bytes per sector
; Convert byte count in ECX to sector count in CX
mov ax, cx ; Low word
shr ecx, 16 ; Shift high word into low word of ECX (therefore just CX)
mov dx, cx ; High word
xor cx, cx ; Clear CX
div bp ; Divide byte count in ax (low word) by bytes per sector
test dx, dx ; DX will contain remainder
setnz cl ; (dx != 0) ? cl = 1 : cl = 0
add cx, ax ; Add remaining sectors to cx
pop edx ; Restore pushed EBP to EDX
pop eax ; Restore EAX
pop si ; Restore SI
; Calculate destination LBA
div ebp ; Divide EAX by EBP
mov dword [si+8], eax ; LBA low
mov dword [si+12], 0 ; LBA high
pop dx ; Restore DX
; Read sectors one by one
.loop:
mov ah, 0x42 ; Extended read
clc ; Clear CF
int 0x13
jc .done ; Error
add word [si+4], bp ; Increment destination by sector byte count
xor ebx, ebx ; EBX = 0
inc dword [si+8] ; Increment LBA low
seto bl ; Will set BL to 1 in case of overflow
add dword [si+12], ebx ; Increment LBA high
loop .loop ; dec cx; jnz .loop
.done:
popa
ret
; Disk Address Packet
.da_packet: equ 0x8000
; Drive Parameters from int 13h, ah = 0x48
.drive_params: equ 0x8010
+29
View File
@@ -0,0 +1,29 @@
; Global Descriptor Table
gdt:
.null_desc: ; Just zeros, no clue why it even exists
dq 0
.code_desc: ; 32-bit code
dw 0xffff ; Limit (low 16-bits)
dw 0x0000 ; Base (low 16 bits)
db 0x00 ; Base (mid 8 bits)
db 0b10011011 ; Access flags
db 0b11001111 ; Low 4 bits - Granularity, High 4 bits - Limit (high 4 bits)
db 0x00 ; Base (high 8 bits)
.data_desc: ; 32-bit data
dw 0xffff ; Limit (low 16-bits)
dw 0x0000 ; Base (low 16 bits)
db 0x00 ; Base (mid 8 bits)
db 0b10010011 ; Access flags
db 0b11001111 ; Low 4 bits - Granularity, High 4 bits - Limit (high 4 bits)
db 0x00 ; Base (high 8 bits)
.end:
; GDT Pointer
gdtp:
dw gdt.end - gdt - 1 ; Size
dd gdt ; Pointer
; Segments
code_seg equ gdt.code_desc - gdt
data_seg equ gdt.data_desc - gdt
-18
View File
@@ -1,18 +0,0 @@
/* Third stage "prekernel" */
OUTPUT_FORMAT("binary")
SECTIONS {
.text 0x50000 : {
*(entry);
*(.text*);
}
.data : {
*(.data*);
}
.rodata : {
*(.rodata*);
}
.bss : {
*(.bss*);
}
}
-29
View File
@@ -1,29 +0,0 @@
#
# Bootloader
#
include make.defaults
STAGE1 = $(BIN)/stage1.bin
STAGE2 = $(BIN)/stage2.bin
STAGE3 = $(BIN)/stage3.bin
STAGE1_SRC = $(BOOT_DIR)/stage1.s
STAGE2_SRC = $(BOOT_DIR)/stage2.s
STAGE3_SRC = $(BOOT_DIR)/stage3.c
STAGE3_OBJ = $(BIN)/boot/stage3.o
bootloader: $(STAGE1) $(STAGE2) $(STAGE3)
$(STAGE1): $(STAGE1_SRC)
@echo "Assembling $<..."
$(AS) -fbin -o $@ $< $(ASFLAGS)
$(STAGE2): $(STAGE2_SRC)
@echo "Assembling $<..."
$(AS) -fbin -o $@ $< $(ASFLAGS)
$(STAGE3): $(STAGE3_SRC)
@echo "Compiling $(STAGE3_SRC)..."
$(CC) $(CFLAGS) -I$(LIBK_INC) -I$(LIBC_INC) -o $(STAGE3_OBJ) -c $<
$(LD) $(LDFLAGS) -T$(BOOT_DIR)/linker.ld -o $@ $(STAGE3_OBJ) $(LIBK)
-167
View File
@@ -1,167 +0,0 @@
[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
-518
View File
@@ -1,518 +0,0 @@
[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 checkA20
.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
;; Enables the A20 line
enableA20:
in al, 0x92
or al, 2
out 0x92, al
;; Check if the A20 line is enabled
checkA20:
push ds
push es
push di
push si
cli
xor ax, ax ; ax = 0
mov es, ax ; es = 0
not ax ; ax = 0xffff
mov ds, ax ; ds = 0xffff
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
jne enableA20
pop si
pop di
pop es
pop ds
;; 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
-138
View File
@@ -1,138 +0,0 @@
#include <memory/physical.h>
#include <memory/virtual.h>
#include <memory/addresses.h>
#include <screen/gfxmode.h>
#include <screen/text.h>
#include <drivers/disk.h>
#include <fs/kernfs.h>
#include <fs/fs.h>
void bigError(uint32_t err);
__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);
}
void rect(uint32_t c, uint16_t x, uint16_t y, uint16_t w, uint16_t h) {
uint8_t* vidmem = (uint8_t*)gfxMode->physicalBasePtr;
uint8_t bytesPerPx = gfxMode->bpp / 8;
uint32_t convColor = convertColor(c);
for (uint32_t dx = 0; dx < w; dx++) {
for (uint32_t dy = 0; dy < h; dy++) {
uint32_t offset = (((y + dy) * gfxMode->xRes) + (x + dx)) * bytesPerPx;
for (uint8_t i = 0; i < gfxMode->bpp; i++) {
vidmem[offset + i] = (uint8_t)(convColor >> (i*8));
}
}
}
}
void bigError(uint32_t err) {
// Red BG
rect(0x00ff0000, 0, 0, gfxMode->xRes, gfxMode->yRes);
// E
rect(0x00ffffff, 20, 10, 10, 50);
rect(0x00ffffff, 30, 10, 30, 10);
rect(0x00ffffff, 30, 30, 30, 10);
rect(0x00ffffff, 30, 50, 30, 10);
// R
rect(0x00ffffff, 70, 10, 10, 50);
rect(0x00ffffff, 70, 10, 30, 10);
rect(0x00ffffff, 70, 30, 30, 10);
rect(0x00ffffff, 90, 10, 10, 30);
rect(0x00ffffff, 80, 40, 10, 10);
rect(0x00ffffff, 90, 50, 10, 10);
// R
rect(0x00ffffff, 110, 10, 10, 50);
rect(0x00ffffff, 110, 10, 30, 10);
rect(0x00ffffff, 110, 30, 30, 10);
rect(0x00ffffff, 130, 10, 10, 30);
rect(0x00ffffff, 120, 40, 10, 10);
rect(0x00ffffff, 130, 50, 10, 10);
// O
rect(0x00ffffff, 150, 10, 10, 50);
rect(0x00ffffff, 170, 10, 10, 50);
rect(0x00ffffff, 150, 10, 30, 10);
rect(0x00ffffff, 150, 50, 30, 10);
// R
rect(0x00ffffff, 190, 10, 10, 50);
rect(0x00ffffff, 190, 10, 30, 10);
rect(0x00ffffff, 190, 30, 30, 10);
rect(0x00ffffff, 210, 10, 10, 30);
rect(0x00ffffff, 200, 40, 10, 10);
rect(0x00ffffff, 210, 50, 10, 10);
__asm__ volatile ("cli; hlt" :: "a"(err));
}