diff --git a/boot/bootsect.s b/boot/bootsect.s new file mode 100644 index 0000000..6bd870e --- /dev/null +++ b/boot/bootsect.s @@ -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' + diff --git a/boot/disk.s b/boot/disk.s new file mode 100644 index 0000000..c3a5a68 --- /dev/null +++ b/boot/disk.s @@ -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 + diff --git a/boot/gdt.s b/boot/gdt.s new file mode 100644 index 0000000..af8234b --- /dev/null +++ b/boot/gdt.s @@ -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 + diff --git a/boot/linker.ld b/boot/linker.ld deleted file mode 100644 index e6feb9b..0000000 --- a/boot/linker.ld +++ /dev/null @@ -1,18 +0,0 @@ -/* Third stage "prekernel" */ -OUTPUT_FORMAT("binary") - -SECTIONS { - .text 0x50000 : { - *(entry); - *(.text*); - } - .data : { - *(.data*); - } - .rodata : { - *(.rodata*); - } - .bss : { - *(.bss*); - } -} diff --git a/boot/makefile b/boot/makefile deleted file mode 100644 index 6fe311d..0000000 --- a/boot/makefile +++ /dev/null @@ -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) - diff --git a/boot/stage1.s b/boot/stage1.s deleted file mode 100644 index dbcfb77..0000000 --- a/boot/stage1.s +++ /dev/null @@ -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 - diff --git a/boot/stage2.s b/boot/stage2.s deleted file mode 100644 index fbcb3e9..0000000 --- a/boot/stage2.s +++ /dev/null @@ -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 - diff --git a/boot/stage3.c b/boot/stage3.c deleted file mode 100644 index 11be2a7..0000000 --- a/boot/stage3.c +++ /dev/null @@ -1,138 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -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)); -} - -