...
This commit is contained in:
204
src/boot.asm
204
src/boot.asm
@@ -1,204 +0,0 @@
|
||||
%define MAGIC 0xe85250d6
|
||||
%define ARCH 0
|
||||
%define LEN header_end - header_start
|
||||
%define CHECKSUM -(MAGIC + ARCH + LEN)
|
||||
|
||||
section .multiboot2
|
||||
header_start:
|
||||
align 4
|
||||
dd MAGIC
|
||||
dd ARCH
|
||||
dd LEN
|
||||
dd CHECKSUM
|
||||
dw 0
|
||||
dd 8
|
||||
header_end:
|
||||
|
||||
section .bss
|
||||
align 16
|
||||
resb 16384
|
||||
stack_top:
|
||||
|
||||
align 4096
|
||||
pml4_table:
|
||||
resb 4096
|
||||
pdp_table:
|
||||
resb 4096
|
||||
pd_table:
|
||||
resb 4096
|
||||
|
||||
section .text
|
||||
bits 32
|
||||
global _start
|
||||
_start:
|
||||
cli
|
||||
mov esp, stack_top
|
||||
|
||||
; Check if CPU supports 64-bit mode
|
||||
call check_multiboot
|
||||
call check_cpuid
|
||||
call check_long_mode
|
||||
|
||||
; Set up paging for 64-bit mode
|
||||
call set_up_page_tables
|
||||
call enable_paging
|
||||
|
||||
; Load GDT and jump to 64-bit mode
|
||||
lgdt [gdt64.pointer]
|
||||
jmp gdt64.code:long_mode_start
|
||||
|
||||
check_multiboot:
|
||||
cmp eax, 0x36d76289
|
||||
jne .no_multiboot
|
||||
ret
|
||||
|
||||
.no_multiboot:
|
||||
mov al, 'M'
|
||||
jmp error
|
||||
|
||||
check_cpuid:
|
||||
; Copy flags to eax through the stack
|
||||
pushfd
|
||||
pop eax
|
||||
|
||||
; Copy flags to ecx for a later comparison
|
||||
mov ecx, eax
|
||||
|
||||
; Flit the cpuid bit
|
||||
xor eax, 1 << 21
|
||||
|
||||
; Copy eax (with the flipped cpuid bit) back to flags
|
||||
push eax
|
||||
popfd
|
||||
|
||||
; Copy flags back to eax. The cpiuid bit will be flipped if cpuid is supported
|
||||
pushfd
|
||||
pop eax
|
||||
|
||||
; Restore flags from the original flags stored in ecx
|
||||
push ecx
|
||||
popfd
|
||||
|
||||
; Compare eax and ecx. If thry are equal, cpuid is not supported
|
||||
cmp eax, ecx
|
||||
je .no_cpuid
|
||||
ret
|
||||
|
||||
.no_cpuid:
|
||||
mov al, 'I'
|
||||
jmp error
|
||||
|
||||
check_long_mode:
|
||||
; Test if extended processor info is available
|
||||
mov eax, 0x80000000
|
||||
cpuid
|
||||
cmp eax, 0x80000001
|
||||
jb .no_long_mode
|
||||
|
||||
; Test if long mode is available
|
||||
mov eax, 0x80000001
|
||||
cpuid
|
||||
test edx, 1 << 29
|
||||
jz .no_long_mode
|
||||
ret
|
||||
|
||||
.no_long_mode:
|
||||
mov al, 'L'
|
||||
jmp error
|
||||
|
||||
; todo(nub): This is copy pasted. I will research hat it does later
|
||||
set_up_page_tables:
|
||||
; Map first PML4 entry to PDP table
|
||||
mov eax, pdp_table
|
||||
or eax, 0b11 ; present + writable
|
||||
mov [pml4_table], eax
|
||||
|
||||
; Map first PDP entry to PD table
|
||||
mov eax, pd_table
|
||||
or eax, 0b11 ; present + writable
|
||||
mov [pdp_table], eax
|
||||
|
||||
; Map each PD entry to a huge 2MiB page
|
||||
mov ecx, 0 ; counter variable
|
||||
.map_pd_table:
|
||||
; Map ecx-th PD entry to a huge page that starts at address (2MiB * ecx)
|
||||
mov eax, 0x200000 ; 2MiB
|
||||
mul ecx ; Start address of ecx-th page
|
||||
or eax, 0b10000011 ; present + writable + huge
|
||||
mov [pd_table + ecx * 8], eax ; Map ecx-th entry
|
||||
|
||||
inc ecx ; Increase counter
|
||||
cmp ecx, 512 ; If counter == 512, the whole PD table is mapped
|
||||
jne .map_pd_table ; Else map the next entry
|
||||
|
||||
ret
|
||||
|
||||
; todo(nub): This is copy pasted. I will research hat it does later
|
||||
enable_paging:
|
||||
; Load PML4 to cr3 register (cpu uses this to access the PML4 table)
|
||||
mov eax, pml4_table
|
||||
mov cr3, eax
|
||||
|
||||
; Enable PAE-flag in cr4 (Physical Address Extension)
|
||||
mov eax, cr4
|
||||
or eax, 1 << 5
|
||||
mov cr4, eax
|
||||
|
||||
; Set the long mode bit in the EFER MSR (model specific register)
|
||||
mov ecx, 0xC0000080
|
||||
rdmsr
|
||||
or eax, 1 << 8
|
||||
wrmsr
|
||||
|
||||
; Enable paging in the cr0 register
|
||||
mov eax, cr0
|
||||
or eax, 1 << 31
|
||||
mov cr0, eax
|
||||
|
||||
ret
|
||||
|
||||
error:
|
||||
mov byte [0xb8000], '['
|
||||
mov byte [0xb8002], ' '
|
||||
mov byte [0xb8004], 'E'
|
||||
mov byte [0xb8005], 4
|
||||
mov byte [0xb8006], 'R'
|
||||
mov byte [0xb8007], 4
|
||||
mov byte [0xb8008], 'R'
|
||||
mov byte [0xb8009], 4
|
||||
mov byte [0xb800a], ' '
|
||||
mov byte [0xb800c], ']'
|
||||
mov byte [0xb800e], ':'
|
||||
mov byte [0xb8010], ' '
|
||||
mov byte [0xb8012], al
|
||||
cli
|
||||
.hang:
|
||||
hlt
|
||||
jmp .hang
|
||||
|
||||
section .rodata
|
||||
gdt64:
|
||||
dq 0
|
||||
.code: equ $ - gdt64
|
||||
dq (1<<43) | (1<<44) | (1<<47) | (1<<53)
|
||||
.pointer:
|
||||
dw $ - gdt64 - 1
|
||||
dq gdt64
|
||||
|
||||
section .text
|
||||
bits 64
|
||||
long_mode_start:
|
||||
mov ax, 0
|
||||
mov ss, ax
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
|
||||
extern kernel_main
|
||||
call kernel_main
|
||||
|
||||
cli
|
||||
.hang:
|
||||
hlt
|
||||
jmp .hang
|
||||
28
src/boot.ld
28
src/boot.ld
@@ -1,28 +0,0 @@
|
||||
ENTRY(_start)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = 2M;
|
||||
|
||||
.text BLOCK(4K) : ALIGN(4K)
|
||||
{
|
||||
*(.multiboot2)
|
||||
*(.text)
|
||||
}
|
||||
|
||||
.rodata BLOCK(4K) : ALIGN(4K)
|
||||
{
|
||||
*(.rodata)
|
||||
}
|
||||
|
||||
.data BLOCK(4K) : ALIGN(4K)
|
||||
{
|
||||
*(.data)
|
||||
}
|
||||
|
||||
.bss BLOCK(4K) : ALIGN(4K)
|
||||
{
|
||||
*(COMMON)
|
||||
*(.bss)
|
||||
}
|
||||
}
|
||||
37
src/boot.s
Normal file
37
src/boot.s
Normal file
@@ -0,0 +1,37 @@
|
||||
.intel_syntax noprefix
|
||||
|
||||
.set ALIGN, 1<<0
|
||||
.set MEMINFO, 1<<1
|
||||
.set FLAGS, ALIGN | MEMINFO
|
||||
.set MAGIC, 0x1BADB002
|
||||
.set CHECKSUM, -(MAGIC + FLAGS)
|
||||
|
||||
.section .multiboot
|
||||
.align 4
|
||||
.long MAGIC
|
||||
.long FLAGS
|
||||
.long CHECKSUM
|
||||
|
||||
.section .bss
|
||||
.align 16
|
||||
stack_bottom:
|
||||
.skip 16384
|
||||
stack_top:
|
||||
|
||||
.set BOOTLOADER_MAGIC, 0x2BADB002
|
||||
|
||||
.section .text
|
||||
.global _start
|
||||
_start:
|
||||
mov stack_top, esp
|
||||
|
||||
cmp eax, BOOTLOADER_MAGIC
|
||||
jne hang
|
||||
|
||||
push ebx
|
||||
call kernel_main
|
||||
add esp, 4
|
||||
hang:
|
||||
cli
|
||||
hlt
|
||||
jmp hang
|
||||
24
src/kernel.c
24
src/kernel.c
@@ -1,35 +1,17 @@
|
||||
#include "kernel.h"
|
||||
#include "idt.h"
|
||||
#include "keyboard.h"
|
||||
#include "multiboot.h"
|
||||
#include "vga.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void keyboard_handler(const keyboard_event_t* event)
|
||||
{
|
||||
if (event->pressed && event->ascii)
|
||||
{
|
||||
vga_print_char(event->ascii);
|
||||
}
|
||||
}
|
||||
|
||||
void kernel_main(void)
|
||||
void kernel_main(multiboot_info_t* multiboot_info)
|
||||
{
|
||||
vga_clear();
|
||||
vga_print_success();
|
||||
vga_print(" VGA intialzied\n");
|
||||
|
||||
init_idt();
|
||||
vga_print_success();
|
||||
vga_print(" IDT intialzied\n");
|
||||
|
||||
init_keyboard();
|
||||
vga_print_success();
|
||||
vga_print(" Keyboard driver intialzied\n");
|
||||
|
||||
vga_print("\nWelcome to nub OS\n");
|
||||
|
||||
register_keypress_handler(keyboard_handler);
|
||||
|
||||
while (true)
|
||||
{
|
||||
}
|
||||
|
||||
58
src/multiboot.h
Normal file
58
src/multiboot.h
Normal file
@@ -0,0 +1,58 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct multiboot_info
|
||||
{
|
||||
uint32_t flags; // required
|
||||
|
||||
// Available if flags[0] is set
|
||||
uint32_t mem_lower;
|
||||
uint32_t mem_upper;
|
||||
|
||||
// Available if flags[1] is set
|
||||
uint32_t boot_device;
|
||||
|
||||
// Available if flags[2] is set
|
||||
uint32_t cmdline;
|
||||
|
||||
// Available if flags[3] is set
|
||||
uint32_t mods_count;
|
||||
uint32_t mods_addr;
|
||||
|
||||
// Available if flags[4] or flags[5] is set
|
||||
uint8_t syms[16]; // 28 - 40 bytes, exact layout may differ depending on a.out or ELF
|
||||
|
||||
// Available if flags[6] is set
|
||||
uint32_t mmap_length;
|
||||
uint32_t mmap_addr;
|
||||
|
||||
// Available if flags[7] is set
|
||||
uint32_t drives_length;
|
||||
uint32_t drives_addr;
|
||||
|
||||
// Available if flags[8] is set
|
||||
uint32_t config_table;
|
||||
|
||||
// Available if flags[9] is set
|
||||
uint32_t boot_loader_name;
|
||||
|
||||
// Available if flags[10] is set
|
||||
uint32_t apm_table;
|
||||
|
||||
// Available if flags[11] is set
|
||||
uint32_t vbe_control_info;
|
||||
uint32_t vbe_mode_info;
|
||||
uint16_t vbe_mode;
|
||||
uint16_t vbe_interface_seg;
|
||||
uint16_t vbe_interface_off;
|
||||
uint16_t vbe_interface_len;
|
||||
|
||||
// Available if flags[12] is set
|
||||
uint64_t framebuffer_addr; // 64-bit for large memory addresses
|
||||
uint32_t framebuffer_pitch;
|
||||
uint32_t framebuffer_width;
|
||||
uint32_t framebuffer_height;
|
||||
uint8_t framebuffer_bpp;
|
||||
uint8_t framebuffer_type;
|
||||
uint8_t color_info[6]; // 110-115 bytes
|
||||
} __attribute__((packed)) multiboot_info_t;
|
||||
10
src/string.c
10
src/string.c
@@ -26,7 +26,7 @@ void reverse(char* str, size_t length)
|
||||
}
|
||||
}
|
||||
|
||||
int uitoa(uint64_t value, char* buffer)
|
||||
int uitoa(uint32_t value, char* buffer)
|
||||
{
|
||||
int i = 0;
|
||||
if (value == 0)
|
||||
@@ -47,7 +47,7 @@ int uitoa(uint64_t value, char* buffer)
|
||||
return i;
|
||||
}
|
||||
|
||||
int itoa(int64_t value, char* buffer)
|
||||
int itoa(int32_t value, char* buffer)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
@@ -59,16 +59,16 @@ int itoa(int64_t value, char* buffer)
|
||||
}
|
||||
|
||||
bool negative = false;
|
||||
uint64_t v;
|
||||
uint32_t v;
|
||||
|
||||
if (value < 0)
|
||||
{
|
||||
negative = true;
|
||||
v = (uint64_t)(-value);
|
||||
v = (uint32_t)(-value);
|
||||
}
|
||||
else
|
||||
{
|
||||
v = (uint64_t)value;
|
||||
v = (uint32_t)value;
|
||||
}
|
||||
|
||||
while (v > 0)
|
||||
|
||||
@@ -5,5 +5,5 @@
|
||||
|
||||
int strcmp(const char* a, const char* b);
|
||||
void reverse(char* str, size_t length);
|
||||
int uitoa(uint64_t value, char* buffer);
|
||||
int itoa(int64_t value, char* buffer);
|
||||
int uitoa(uint32_t value, char* buffer);
|
||||
int itoa(int32_t value, char* buffer);
|
||||
@@ -138,14 +138,14 @@ void vga_print_error(void)
|
||||
vga_print(" ]");
|
||||
}
|
||||
|
||||
void vga_print_uint(uint64_t value)
|
||||
void vga_print_uint(uint32_t value)
|
||||
{
|
||||
char buffer[11];
|
||||
uitoa(value, buffer);
|
||||
vga_print(buffer);
|
||||
}
|
||||
|
||||
void vga_print_int(int64_t value)
|
||||
void vga_print_int(int32_t value)
|
||||
{
|
||||
char buffer[12];
|
||||
itoa(value, buffer);
|
||||
|
||||
@@ -30,8 +30,8 @@ void vga_print_colored(const char* string, vga_color_t color);
|
||||
void vga_print_success(void);
|
||||
void vga_print_error(void);
|
||||
|
||||
void vga_print_uint(uint64_t value);
|
||||
void vga_print_int(int64_t value);
|
||||
void vga_print_uint(uint32_t value);
|
||||
void vga_print_int(int32_t value);
|
||||
|
||||
static inline vga_color_t vga_color(vga_color_t fg_color, vga_color_t bg_color)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user