Compare commits

..

1 commit

21 changed files with 140 additions and 467 deletions

View file

@ -1,5 +1,5 @@
###CONFIGURATION ###CONFIGURATION
ARCH := i686 ARCH := i386
CROSS := $(ARCH)-elf- CROSS := $(ARCH)-elf-
AS := nasm AS := nasm
CC := $(CROSS)gcc CC := $(CROSS)gcc

View file

@ -3,3 +3,4 @@
i686-elf-gdb build/ukern.elf \ i686-elf-gdb build/ukern.elf \
-ex "target remote localhost:1234" \ -ex "target remote localhost:1234" \
-ex "break start" \ -ex "break start" \
-ex "continue"

View file

@ -1,32 +1,16 @@
/** /* asm.h
* @file asm.h * Assembly wrappers
* @brief Assembly wrappers *
* @author Jake "lordtet" Holtham * Wrapper functions for using assembly files.
* @date 2025 */
* Wrapper functions for using assembly files.
*/
#ifndef ASM_H #ifndef ASM_H
#define ASM_H #define ASM_H
#include <stdint.h> #include <stdint.h>
/** #define COM1 0x3F8
* @brief Wrapper for asm instruction `out` that feeds a byte. #define COM2 0x2F8
* @param port I/O Address for the port to send to
* @param data Data to send
*/
void outb(uint16_t port, uint8_t data);
/** void outb(uint16_t port, uint8_t data);
* @brief Wrapper for asm instruction "in" that receives bytewise.
* @param port I/O Address for the port to listen from
* @return (uint8_t) The received byte.
*/
uint8_t inb(uint16_t port); uint8_t inb(uint16_t port);
/**
* @brief Refresh the CR3 register.
* Moves CR3 into a scratch register and back into CR3. Usually used to nuke the TLB.
*/
void cr3_reload();
#endif #endif

View file

@ -1,62 +1,32 @@
/** /* IDT.h
* @file idt.h * Interrupt Descriptor Table
* @brief Interrupt Descriptor Table *
* @author Jake "lordtet" Holtham * IDT related structures, globals and functions
* @date 2025 */
* IDT related structures, globals and functions
*/
#ifndef IDT_H #ifndef IDT_H
#define IDT_H #define IDT_H
#include <stdint.h> #include <stdint.h>
/**
* @brief IDT Entry
*/
typedef struct InterruptDescriptor_s { typedef struct InterruptDescriptor_s {
uint16_t offset_lo; /**< Lower 16 bits of ISR ptr */ uint16_t offset_lo;
uint16_t selector; /**< */ uint16_t selector;
uint8_t reserved; /**< Nothing */ uint8_t reserved;
uint8_t attributes; /**< */ uint8_t attributes;
uint16_t offset_hi; /**< Upper 16 bits of ISR ptr */ uint16_t offset_hi;
} InterruptDescriptor_t; } InterruptDescriptor_t;
/**
* @brief
*/
typedef struct IDTR_s { typedef struct IDTR_s {
uint16_t size; /**< IDT Length */ uint16_t size;
InterruptDescriptor_t* IDT; /**< Pointer to the IDT Entry array */ InterruptDescriptor_t* IDT;
} __attribute__((packed)) IDTR_t; } __attribute__((packed)) IDTR_t;
/**
* @brief The IDTR in memory.
*/
extern IDTR_t idtr; extern IDTR_t idtr;
/**
* @brief First IDT Entry
*/
extern InterruptDescriptor_t idt_start; extern InterruptDescriptor_t idt_start;
/**
* @brief Amount of ISRs implemented
*/
extern unsigned char num_interrupts; extern unsigned char num_interrupts;
/**
* @brief Call setup and write to construct and load the IDT.
*/
void setup_idt(); void setup_idt();
/**
* @brief Write the IDT and IDTR
*/
void write_descriptors(); void write_descriptors();
/**
* @brief LIDT call
*/
extern void load_idt(); extern void load_idt();
#endif #endif

View file

@ -1,31 +1,21 @@
/** /* interrupt_handlers.h
* @file interrupt_handlers.h * Interrupt Handlers
* @brief Interrupt Handlers *
* @details Functions and structs for the C side of handling interrupts. * Functions and structs for the C side of handling interrupts.
*/ */
#ifndef INTERRUPTHANDLERS_H #ifndef INTERRUPTHANDLERS_H
#define INTERRUPTHANDLERS_H #define INTERRUPTHANDLERS_H
#include <stdint.h> #include <stdint.h>
/**
* @brief
*/
extern void (*isr_ptrs[])(void); extern void (*isr_ptrs[])(void);
/** //Struct is built "backwards" since it is pushed in this order.
* @brief
* @details Struct is built "backwards" since it is pushed in this order.
*/
typedef struct StateSnapshot_s { typedef struct StateSnapshot_s {
uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax; /**< @brief */ uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax;
uint32_t interrupt_id, error_code; /**< @brief */ uint32_t interrupt_id, error_code;
uint32_t eip, cs, eflags; /**< @brief */ uint32_t eip, cs, eflags;
} StateSnapshot_t; } StateSnapshot_t;
/**
* @brief
* @param cpu_state
*/
void generic_isr_handler(StateSnapshot_t* cpu_state); void generic_isr_handler(StateSnapshot_t* cpu_state);
#endif #endif

View file

@ -1,78 +1,26 @@
/** /* io.h
* @file io.h * In/Out
* @brief In/Out *
* @details Common library for handling user i/o. Aims to be mechanic agnostic, and instead * Common library for handling user i/o. Aims to be mechanic agnostic, and instead
* focus on implementing generic functions to format and manipulate data. * focus on implementing generic functions to format and manipulate data.
*/ */
#ifndef IO_H #ifndef IO_H
#define IO_H #define IO_H
#include <stdint.h> #include <stdint.h>
/**
* @brief
*/
typedef struct char_writer_s char_writer_t; typedef struct char_writer_s char_writer_t;
/**
* @brief
*/
struct char_writer_s { struct char_writer_s {
int (*putChar)(void* ctx, char out); /**< @brief */ int (*putChar)(void* ctx, char out);
void* ctx; /**< @brief */ void* ctx;
}; };
/**
* @brief
*/
extern char_writer_t* default_output; extern char_writer_t* default_output;
/**
* @brief
* @param
* @param
* @return int
*/
int putc(char_writer_t*, char); int putc(char_writer_t*, char);
/**
* @brief
* @param
* @param
* @return int
*/
int print(char_writer_t*, const char*); int print(char_writer_t*, const char*);
/**
* @brief
* @param
* @param
* @return int
*/
int println(char_writer_t*, const char*); int println(char_writer_t*, const char*);
/**
* @brief
* @param
* @param
* @return int
*/
int printhex(char_writer_t*, uint64_t); int printhex(char_writer_t*, uint64_t);
/**
* @brief
* @param
* @param out
* @return int
*/
int prindec(char_writer_t*, uint64_t out); int prindec(char_writer_t*, uint64_t out);
/**
* @brief
* @param
* @param fmt
* @param ...
* @return int
*/
int printf(char_writer_t*, const char* fmt, ...); int printf(char_writer_t*, const char* fmt, ...);
#endif #endif

View file

@ -1,47 +1,35 @@
/** /* kmultiboot.h
* @file kmultiboot.h * Kernel Multiboot
* @brief Kernel Multiboot *
* @details Data needed for multiboot compatibility. * Data needed for multiboot compatibility.
*/ */
#ifndef KMULTIBOOT_H #ifndef KMULTIBOOT_H
#define KMULTIBOOT_H #define KMULTIBOOT_H
#include <stdint.h> #include <stdint.h>
/**
* @brief
*/
typedef struct multiboot_mmap_entry { typedef struct multiboot_mmap_entry {
uint32_t entry_size; /**< @brief size of this struct entry */ uint32_t entry_size; //size of this struct entry
uint64_t addr; /**< @brief physical location of memory */ uint64_t addr; //physical location of memory
uint64_t mem_size; /**< @brief size of the memory block */ uint64_t mem_size; //size of the memory block
uint32_t type; /**< @brief */ uint32_t type;
} __attribute__((packed)) mb_mmap_entry_t; } __attribute__((packed)) mb_mmap_entry_t;
/**
* @brief
*/
typedef struct mb_info_s { typedef struct mb_info_s {
uint32_t flags; /**< @brief */ uint32_t flags;
uint32_t mem_lower; /**< @brief */ uint32_t mem_lower;
uint32_t mem_upper; /**< @brief */ uint32_t mem_upper;
uint32_t boot_device; /**< @brief */ uint32_t boot_device;
uint32_t cmdline; /**< @brief */ uint32_t cmdline;
uint32_t mods_count; /**< @brief */ uint32_t mods_count;
uint32_t mods_addr; /**< @brief */ uint32_t mods_addr;
uint32_t syms[4]; /**< @brief */ uint32_t syms[4];
uint32_t mmap_length; /**< @brief */ uint32_t mmap_length;
uint32_t mmap_addr; /**< @brief */ uint32_t mmap_addr;
} mb_info_t; } mb_info_t;
/**
* @brief
*/
extern uint8_t _kernel_start;
/** extern uint8_t _kernel_start;
* @brief
*/
extern uint8_t _kernel_end; extern uint8_t _kernel_end;
#endif #endif

View file

@ -1,8 +1,8 @@
/** /* kttools.h
* @file kttools.h * Kernel Type Tools
* @brief Kernel Type Tools *
* @details Library for converting types and transcribing data. * Library for converting types and transcribing data.
*/ */
#ifndef KTTOOLS_H #ifndef KTTOOLS_H
#define KTTOOLS_H #define KTTOOLS_H
#include <stdint.h> #include <stdint.h>

View file

@ -1,29 +1,11 @@
/**
* @file physmem.h
* @brief
* @details
*/
#ifndef PHYSMEM_H #ifndef PHYSMEM_H
#define PHYSMEM_H #define PHYSMEM_H
#include <stdint.h> #include <stdint.h>
#include "kmultiboot.h" #include "kmultiboot.h"
/**
* @brief
*/
#define PAGE_SIZE 0x1000 #define PAGE_SIZE 0x1000
/**
* @brief
*/
extern uint8_t* pmem_bitmap; extern uint8_t* pmem_bitmap;
/**
* @brief
* @param mmap
* @param mmap_size
* @return unsigned int
*/
unsigned int build_bitmap(mb_mmap_entry_t* mmap, int mmap_size); unsigned int build_bitmap(mb_mmap_entry_t* mmap, int mmap_size);
#endif #endif

View file

@ -9,11 +9,6 @@
#include "io.h" #include "io.h"
#include <stdint.h> #include <stdint.h>
#define COM1 0x3F8
#define COM2 0x2F8
typedef struct serial_ctx_s { typedef struct serial_ctx_s {
uint16_t port; uint16_t port;
} serial_ctx_t; } serial_ctx_t;

View file

@ -1,64 +1,44 @@
/** /* tss.h
* @file tss.h * Task State Segment
* @brief Task State Segment (TSS) definitions and structures *
* @author Jake Holtham * Structure definitions for the TSS
* @date 2025
*
* This header file contains the structure definitions for the x86 Task State Segment (TSS).
*/ */
#ifndef TSS_H #ifndef TSS_H
#define TSS_H #define TSS_H
#include <stdint.h> #include <stdint.h>
/** // TSS
* @brief Task State Segment structure
*
* Data structure that contains information about a task,
* including the state of the processor registers, stack pointers, and other task-specific
* information. It is used by the x86 architecture for task switching and interrupt handling.
*
* Packed to make sure it's aligned and the correct size.
*
* @note This structure must be aligned on a 4byte boundary
*/
typedef struct tss_s { typedef struct tss_s {
uint32_t LINK; /**< Previous TSS selector*/ uint32_t LINK;
uint32_t ESP0; /**< Stack pointer for privilege level0*/ uint32_t ESP0;
uint32_t SS0; /**< Stack segment for privilege level0*/ uint32_t SS0;
uint32_t ESP1; /**< Stack pointer for privilege level1*/ uint32_t ESP1;
uint32_t SS1; /**< Stack segment for privilege level1*/ uint32_t SS1;
uint32_t ESP2; /**< Stack pointer for privilege level2*/ uint32_t ESP2;
uint32_t SS2; /**< Stack segment for privilege level2*/ uint32_t SS2;
uint32_t CR3; /**< Page Directory register */ uint32_t CR3;
uint32_t EIP; /**< Instruction pointer */ uint32_t EIP;
uint32_t EFLAGS; /**< Flags register */ uint32_t EFLAGS;
uint32_t EAX; /**< General purpose */ uint32_t EAX;
uint32_t ECX; /**< General purpose */ uint32_t ECX;
uint32_t EDX; /**< General purpose */ uint32_t EDX;
uint32_t EBX; /**< General purpose */ uint32_t EBX;
uint32_t ESP; /**< Stack pointer */ uint32_t ESP;
uint32_t ESI; /**< Source index register */ uint32_t ESI;
uint32_t EDI; /**< Destination index register */ uint32_t EDI;
uint32_t ES; /**< Extra segment register */ uint32_t ES;
uint32_t CS; /**< Code segment register */ uint32_t CS;
uint32_t SS; /**< Stack segment register */ uint32_t SS;
uint32_t DS; /**< Data segment register */ uint32_t DS;
uint32_t FS; /**< Extra segment register FS */ uint32_t FS;
uint32_t GS; /**< Extra segment register GS */ uint32_t GS;
uint32_t LDTR; /**< Local descriptor table register */ uint32_t LDTR;
uint32_t IOPB; /**< I/O permission bitmap offset */ uint32_t IOPB;
uint32_t SSP; /**< Stack segment pointer */ uint32_t SSP;
} __attribute__((packed)) tss_t; } __attribute__((packed)) tss_t;
/**
* @brief Global TSS instance
*
* This is the main TSS instance used by the kernel for task management.
* It contains the current task's state information.
* Defined in assembly.
*/
extern tss_t tss; extern tss_t tss;
#endif /* TSS_H */
#endif

View file

@ -1,71 +1,42 @@
/** /* vga.h
* @file vga.h * VGA
* @brief VGA *
* @details Responsible for VGA buffer control. * Responsible for VGA buffer control.
*/ */
#ifndef VGA_H #ifndef VGA_H
#define VGA_H #define VGA_H
/**
* @brief
*/
#define VGA_GRID_COLS 80 #define VGA_GRID_COLS 80
/**
* @brief
*/
#define VGA_GRID_ROWS 25 #define VGA_GRID_ROWS 25
/**
* @brief
*/
#define DEFAULT_ATTRIBUTES 0x0F00 #define DEFAULT_ATTRIBUTES 0x0F00
#include <stdint.h> #include <stdint.h>
#include <stdarg.h> #include <stdarg.h>
#include "io.h" #include "io.h"
/*
/** * CONSTANTS AND VARIABLES
* @brief Information on the VGA buffer
*/ */
//Information on the VGA buffer
extern volatile uint16_t* const vga_buffer; extern volatile uint16_t* const vga_buffer;
/**
* @brief
*/
typedef struct vga_ctx_s { typedef struct vga_ctx_s {
int cursor_col; /**< @brief */ int cursor_col;
int cursor_row; /**< @brief */ int cursor_row;
uint16_t attributes; /**< @brief */ uint16_t attributes;
} vga_ctx_t; } vga_ctx_t;
/** //grid is top left origin. This is our cursor!
* @brief grid is top left origin. This is our cursor! Black background, White foreground extern uint16_t vga_attributes; // Black background, White foreground
*/
extern uint16_t vga_attributes;
/**
* @brief
*/
extern char_writer_t* default_vga; extern char_writer_t* default_vga;
/** /*
* @brief Clear the VGA buffer, context optional * Functions
* @param ctx
*/ */
//Clear the VGA buffer, context optional
void vga_clear_ctx(vga_ctx_t* ctx); void vga_clear_ctx(vga_ctx_t* ctx);
/**
* @brief
*/
void vga_clear(); void vga_clear();
//Write character c to cursor
/** //Implements IO generic ASCII output
* @brief Write character c to cursor. Implements IO generic ASCII output
* @param ctx
* @param c
* @return int
*/
int vga_out(void* ctx, char c); int vga_out(void* ctx, char c);

View file

@ -1,40 +0,0 @@
/**
* @file virtmem.h
* @brief
* @details
*/
#ifndef VIRTMEM_H
#define VIRTMEM_H
#include <stdint.h>
/**
* @brief
*/
extern uint32_t global_page_dir;
/**
* @brief
*/
extern uint32_t kernel_pagetable;
/**
* @brief
* @param page_dir
* @param phys_loc
* @param virtual_loc
* @param page_opts
* @return int
*/
int map(uint32_t* page_dir, uint32_t phys_loc, uint32_t virtual_loc, uint8_t page_opts);
/**
* @brief
* @param phys_loc
* @param virtual_loc
* @param page_opts
* @return int
*/
int kmap(uint32_t phys_loc, uint32_t virtual_loc, uint8_t page_opts);
#endif

View file

@ -6,31 +6,19 @@ SECTIONS
/*start me at 1Mb because below that is x86 essential stuff, which we dont want to be written on top of.*/ /*start me at 1Mb because below that is x86 essential stuff, which we dont want to be written on top of.*/
. = 1M; . = 1M;
_kernel_start = .;
/* we're going to maintain 4K alignment - apparently useful for paging, and i'm not complaining about the lost space anyway. */ /* we're going to maintain 4K alignment - apparently useful for paging, and i'm not complaining about the lost space anyway. */
/*our multiboot header from start.s - has to go at the beginning of the executable so the bootloader knows we're loadable.*/ /*our multiboot header from start.s - has to go at the beginning of the executable so the bootloader knows we're loadable.*/
/*executable section*/ /*executable section*/
.mb_sect : .text BLOCK(4K) : ALIGN(4K)
{
*(.multiboot)
}
.lower_text :
{
*(.lower_text)
}
/* Higher half addressing! We'll have to also specify that we want to be physically placed at 1MB.*/
. += 0xC0000000;
_kernel_start = .;
.text ALIGN (4K) : AT (ADDR (.text) - 0xC0000000)
{ {
*(.multiboot)
*(.text) *(.text)
} }
/*general read only data*/ /*general read only data*/
.rodata ALIGN (4K) : AT(ADDR(.rodata) - 0xC0000000) .rodata BLOCK(4K) : ALIGN(4K)
{ {
*(.rodata*) *(.rodata*)
*(.gdt_sect) *(.gdt_sect)
@ -38,18 +26,16 @@ SECTIONS
} }
/*initialized rw data. */ /*initialized rw data. */
.data ALIGN (4K) : AT(ADDR(.data) - 0xC0000000) .data BLOCK(4K) : ALIGN(4K)
{ {
*(.data) *(.data)
} }
/*uninitialized data, and our stack as defined in start.s*/ /*uninitialized data, and our stack as defined in start.s*/
.bss ALIGN(4K) : AT(ADDR(.bss) - 0xC0000000) .bss BLOCK(4K) : ALIGN(4K)
{ {
*(COMMON) *(COMMON)
*(.bss) *(.bss)
*(.bootstrap_tables)
*(.tss)
*(.idt) *(.idt)
} }

View file

@ -1,4 +1,4 @@
global outb, inb, invlpg global outb, inb
section .text section .text
outb: outb:
mov dx, [esp+4] mov dx, [esp+4]
@ -11,8 +11,3 @@ section .text
mov dx, [esp+4] mov dx, [esp+4]
in al, dx in al, dx
ret ret
cr3_reload:
mov eax, cr3
mov cr3, eax
ret

View file

@ -55,5 +55,5 @@ section .gdt_sect
;size of the gdt ;size of the gdt
dw gdt_end - gdt - 1 dw gdt_end - gdt - 1
;location of the gdt ;location of the gdt
dd gdt - 0xC0000000 dd gdt

View file

@ -7,8 +7,6 @@
#include "idt.h" #include "idt.h"
#include "serial.h" #include "serial.h"
#include "physmem.h" #include "physmem.h"
void kern_main(uint32_t multiboot_magic, mb_info_t* multiboot_info) void kern_main(uint32_t multiboot_magic, mb_info_t* multiboot_info)
{ {
//Hello C! Let's get to work in cleaning up our environment a bit and creating some safety. //Hello C! Let's get to work in cleaning up our environment a bit and creating some safety.
@ -40,8 +38,6 @@ void kern_main(uint32_t multiboot_magic, mb_info_t* multiboot_info)
//AND OUR DEFAULT OUTPUT IS: //AND OUR DEFAULT OUTPUT IS:
default_output = default_COM; default_output = default_COM;
printf(default_output, "Output schemes loaded!\n");
printf(default_output, "currently executing in kern_main() at %X\n",kern_main);
printf(default_output, "Entry eax:%X\n", multiboot_magic); printf(default_output, "Entry eax:%X\n", multiboot_magic);
if(multiboot_magic != 0x2BADB002) { if(multiboot_magic != 0x2BADB002) {
println(default_output, "Bootloader not multiboot1 compliant! Needed for mmap, etc. Can't work without it, kthxbye!"); println(default_output, "Bootloader not multiboot1 compliant! Needed for mmap, etc. Can't work without it, kthxbye!");
@ -60,8 +56,10 @@ void kern_main(uint32_t multiboot_magic, mb_info_t* multiboot_info)
return; return;
} }
unsigned int pages_allocated = build_bitmap((mb_mmap_entry_t*)multiboot_info->mmap_addr, multiboot_info->mmap_length); unsigned int pages_allocated = build_bitmap((mb_mmap_entry_t*)multiboot_info->mmap_addr, multiboot_info->mmap_length);
printf(default_output, "Available mem:%d Pages | %dK", pages_allocated, pages_allocated * 4); printf(default_output, "Available mem:%d Pages | %dK", pages_allocated, pages_allocated * 4);
} }

View file

@ -19,13 +19,17 @@ void free_page(void* addr) {
unsigned int build_bitmap(mb_mmap_entry_t* mmap, int mmap_size) { unsigned int build_bitmap(mb_mmap_entry_t* mmap, int mmap_size) {
//rather important global pointer to the bitmap //rather important global pointer to the bitmap
pmem_bitmap = (&_kernel_end); pmem_bitmap = &_kernel_end;
//some variables //some variables
int mmap_end = (uint32_t)mmap + mmap_size; int mmap_end = (uint32_t)mmap + mmap_size;
unsigned int pages_allocated = 0; unsigned int pages_allocated = 0;
uint32_t max_memory = 0; uint32_t max_memory = 0;
//How much memory do we even have? Find the highest usable mmap region, and that'll be our bitmap size. //How much memory do we even have? Find the highest usable mmap region, and that'll be our bitmap size.
for(mb_mmap_entry_t* mmap_walk = mmap; for(mb_mmap_entry_t* mmap_walk = mmap;
(int)mmap_walk < mmap_end; (int)mmap_walk < mmap_end;

View file

@ -5,8 +5,6 @@ bits 32
;Some symbols we'll need from other files... ;Some symbols we'll need from other files...
extern kern_main extern kern_main
extern gdtr extern gdtr
extern _kernel_start
extern _kernel_end
;This will be our entrypoint function name - gotta initialize it now as global so the linker knows later. ;This will be our entrypoint function name - gotta initialize it now as global so the linker knows later.
global start global start
@ -19,28 +17,21 @@ section .bss align=16
;Therefore, we put a label here to represent the top of our stack for later. ;Therefore, we put a label here to represent the top of our stack for later.
stack_top: stack_top:
;We're gonna throw the TSS here too. ;We're gonna throw the TSS here too.
section .tss align=16 nobits
tss: tss:
resb 104 resb 104
section .bootstrap_tables nobits align=4096
global_page_dir:
resb 4096
kernel_pagetable:
resb 4096
;Actual code. Entry point goes here! ;Actual code. Entry point goes here!
section .lower_text exec section .text
;Here it is! ;Here it is!
start: start:
;We made a GDT! Let's use it! ;We made a GDT! Let's use it!
lgdt [gdtr - 0xC0000000] lgdt [gdtr]
;Now we start by setting the code segment (CS) with a far jump... ;Now we start by setting the code segment (CS) with a far jump...
jmp 0x08:gdt_load jmp 0x08:segment_be_gone
gdt_load: segment_be_gone:
;Now we go ahead and dump our kernel mode data segment (0x10) into the rest of our segments. ;Now we go ahead and dump our kernel mode data segment (0x10) into the rest of our segments.
;Also preserving eax because it has the bootloader's multiboot magic in it and I want to check it in main. ;Also preserving eax because it has the bootloader's multiboot magic in it and I want to check it in main.
mov cx, 0x10 mov cx, 0x10
@ -49,67 +40,7 @@ section .lower_text exec
mov ss, cx mov ss, cx
mov fs, cx mov fs, cx
mov gs, cx mov gs, cx
;Lets set up the stack. Stack grows downward on x86. We did the work earlier of defining where the top of the stack is, so just tell esp.
;So, we want to set up a page table and page directory. Let's take inventory.
;eax - preserve, mb_magic
;ebx - preserve, mb_info
;ecx,edx,esi - can use
;Can technically use esp as the stack is set to stack_top later.
;ecx = our current indexing for pages, this is a 4K-aligned address
mov ecx, 0x0
;edi = our pointer to the current page table entry. Array of 4byte entries. It's at, of course, where we put it earlier.
;Worth noting that it's actually physically at ~1M with the kernel. The pointer, however, is virtually inclined. So we need to adjust.
mov edi, kernel_pagetable - 0xC0000000
page_alloc_loop:
;If we're lower than our kernel, skip this page. If we've passed our kernel, we're done mapping.
cmp ecx, _kernel_start
jl next_page
cmp ecx, _kernel_end - 0xC0000000
jge page_alloc_done
;Okay, we're in kernel zone. Let's map this one.
;Let's make a page table entry in edx.
;The top bits for the page table entry are just the upper bits of the address, so we dont need to touch it.
mov edx, ecx
;Set last two bits, "present" and "writeable". Later on we'll make a proper page table with proper permissions, but we're bootstrapping here.
or edx, 0x003
;edi holds a pointer to the page table entry, so dereference it and throw our new entry (in edx) to it. Done!
mov [edi], edx
next_page:
;address page + 1
add ecx, 0x1000
;page table entry + 1
add edi, 4
jmp page_alloc_loop
page_alloc_done:
;By now we've mapped the kernel in a page table! Let's map VGA too, we'll need that address later.
mov dword [kernel_pagetable - 0xC0000000 + 1023 * 4], 0x000B8000 | 0x27
;We have our page tables mapped to the phys addr of kernel + VGA. Time to add them to our page directory!
;First identity maps, second maps to higher half.
mov dword [global_page_dir - 0xC0000000], kernel_pagetable - 0xC0000000 + 0x003
mov dword [global_page_dir - 0xC0000000 + 4 * (0xC0000000 >> 22)], kernel_pagetable - 0xC0000000 + 0x003
;Let's set it! You do this with cr3.
mov ecx, global_page_dir - 0xC0000000
mov cr3, ecx
;Enable paging in cr0
mov ecx, cr0
or ecx, 0x80010000
mov cr0, ecx
;Done! Leave to the higher half!
lea ecx, setup_c_env
jmp ecx
section .text
setup_c_env:
;set up the stack. Stack grows downward on x86. We did the work earlier of defining where the top of the stack is, so just tell esp.
mov esp, stack_top ;set the stack pointer mov esp, stack_top ;set the stack pointer
push ebx push ebx
push eax push eax

View file

@ -5,7 +5,7 @@
* VARS * VARS
*/ */
volatile uint16_t* const vga_buffer = (uint16_t*)0xC03FF000; volatile uint16_t* const vga_buffer = (uint16_t*)0xB8000;
char_writer_t* default_vga = 0; char_writer_t* default_vga = 0;
/* /*

View file

@ -1,10 +0,0 @@
#include "virtmem.h"
int map(uint32_t* page_dir, uint32_t phys_loc, uint32_t virtual_loc, uint8_t page_opts) {
}
int kmap(uint32_t phys_loc, uint32_t virtual_loc, uint8_t page_opts){
return map(&global_page_dir, phys_loc, virtual_loc, page_opts);
}