Compare commits
4 commits
main
...
basic_pagi
| Author | SHA1 | Date | |
|---|---|---|---|
| 7b4e4afd43 | |||
| 6261af8e3a | |||
| e1369902f7 | |||
|
|
20357559c1 |
21 changed files with 467 additions and 140 deletions
2
Makefile
2
Makefile
|
|
@ -1,5 +1,5 @@
|
|||
###CONFIGURATION
|
||||
ARCH := i386
|
||||
ARCH := i686
|
||||
CROSS := $(ARCH)-elf-
|
||||
AS := nasm
|
||||
CC := $(CROSS)gcc
|
||||
|
|
|
|||
|
|
@ -3,4 +3,3 @@
|
|||
i686-elf-gdb build/ukern.elf \
|
||||
-ex "target remote localhost:1234" \
|
||||
-ex "break start" \
|
||||
-ex "continue"
|
||||
|
|
|
|||
|
|
@ -1,16 +1,32 @@
|
|||
/* asm.h
|
||||
* Assembly wrappers
|
||||
*
|
||||
* Wrapper functions for using assembly files.
|
||||
*/
|
||||
/**
|
||||
* @file asm.h
|
||||
* @brief Assembly wrappers
|
||||
* @author Jake "lordtet" Holtham
|
||||
* @date 2025
|
||||
* Wrapper functions for using assembly files.
|
||||
*/
|
||||
#ifndef ASM_H
|
||||
#define ASM_H
|
||||
#include <stdint.h>
|
||||
|
||||
#define COM1 0x3F8
|
||||
#define COM2 0x2F8
|
||||
|
||||
/**
|
||||
* @brief Wrapper for asm instruction `out` that feeds a byte.
|
||||
* @param port I/O Address for the port to send to
|
||||
* @param data Data to send
|
||||
*/
|
||||
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);
|
||||
|
||||
/**
|
||||
* @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
|
||||
|
|
|
|||
|
|
@ -1,32 +1,62 @@
|
|||
/* IDT.h
|
||||
* Interrupt Descriptor Table
|
||||
*
|
||||
* IDT related structures, globals and functions
|
||||
*/
|
||||
/**
|
||||
* @file idt.h
|
||||
* @brief Interrupt Descriptor Table
|
||||
* @author Jake "lordtet" Holtham
|
||||
* @date 2025
|
||||
* IDT related structures, globals and functions
|
||||
*/
|
||||
#ifndef IDT_H
|
||||
#define IDT_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* @brief IDT Entry
|
||||
*/
|
||||
typedef struct InterruptDescriptor_s {
|
||||
uint16_t offset_lo;
|
||||
uint16_t selector;
|
||||
uint8_t reserved;
|
||||
uint8_t attributes;
|
||||
uint16_t offset_hi;
|
||||
uint16_t offset_lo; /**< Lower 16 bits of ISR ptr */
|
||||
uint16_t selector; /**< */
|
||||
uint8_t reserved; /**< Nothing */
|
||||
uint8_t attributes; /**< */
|
||||
uint16_t offset_hi; /**< Upper 16 bits of ISR ptr */
|
||||
} InterruptDescriptor_t;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
typedef struct IDTR_s {
|
||||
uint16_t size;
|
||||
InterruptDescriptor_t* IDT;
|
||||
uint16_t size; /**< IDT Length */
|
||||
InterruptDescriptor_t* IDT; /**< Pointer to the IDT Entry array */
|
||||
} __attribute__((packed)) IDTR_t;
|
||||
|
||||
/**
|
||||
* @brief The IDTR in memory.
|
||||
*/
|
||||
extern IDTR_t idtr;
|
||||
|
||||
/**
|
||||
* @brief First IDT Entry
|
||||
*/
|
||||
extern InterruptDescriptor_t idt_start;
|
||||
|
||||
/**
|
||||
* @brief Amount of ISRs implemented
|
||||
*/
|
||||
extern unsigned char num_interrupts;
|
||||
|
||||
/**
|
||||
* @brief Call setup and write to construct and load the IDT.
|
||||
*/
|
||||
void setup_idt();
|
||||
|
||||
/**
|
||||
* @brief Write the IDT and IDTR
|
||||
*/
|
||||
void write_descriptors();
|
||||
|
||||
/**
|
||||
* @brief LIDT call
|
||||
*/
|
||||
extern void load_idt();
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,21 +1,31 @@
|
|||
/* interrupt_handlers.h
|
||||
* Interrupt Handlers
|
||||
*
|
||||
* Functions and structs for the C side of handling interrupts.
|
||||
*/
|
||||
/**
|
||||
* @file interrupt_handlers.h
|
||||
* @brief Interrupt Handlers
|
||||
* @details Functions and structs for the C side of handling interrupts.
|
||||
*/
|
||||
#ifndef INTERRUPTHANDLERS_H
|
||||
#define INTERRUPTHANDLERS_H
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
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 {
|
||||
uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax;
|
||||
uint32_t interrupt_id, error_code;
|
||||
uint32_t eip, cs, eflags;
|
||||
uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax; /**< @brief */
|
||||
uint32_t interrupt_id, error_code; /**< @brief */
|
||||
uint32_t eip, cs, eflags; /**< @brief */
|
||||
} StateSnapshot_t;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* @param cpu_state
|
||||
*/
|
||||
void generic_isr_handler(StateSnapshot_t* cpu_state);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
68
include/io.h
68
include/io.h
|
|
@ -1,26 +1,78 @@
|
|||
/* io.h
|
||||
* In/Out
|
||||
*
|
||||
* Common library for handling user i/o. Aims to be mechanic agnostic, and instead
|
||||
* focus on implementing generic functions to format and manipulate data.
|
||||
*/
|
||||
/**
|
||||
* @file io.h
|
||||
* @brief In/Out
|
||||
* @details Common library for handling user i/o. Aims to be mechanic agnostic, and instead
|
||||
* focus on implementing generic functions to format and manipulate data.
|
||||
*/
|
||||
#ifndef IO_H
|
||||
#define IO_H
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
typedef struct char_writer_s char_writer_t;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
struct char_writer_s {
|
||||
int (*putChar)(void* ctx, char out);
|
||||
void* ctx;
|
||||
int (*putChar)(void* ctx, char out); /**< @brief */
|
||||
void* ctx; /**< @brief */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
extern char_writer_t* default_output;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* @param
|
||||
* @param
|
||||
* @return int
|
||||
*/
|
||||
int putc(char_writer_t*, char);
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* @param
|
||||
* @param
|
||||
* @return int
|
||||
*/
|
||||
int print(char_writer_t*, const char*);
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* @param
|
||||
* @param
|
||||
* @return int
|
||||
*/
|
||||
int println(char_writer_t*, const char*);
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* @param
|
||||
* @param
|
||||
* @return int
|
||||
*/
|
||||
int printhex(char_writer_t*, uint64_t);
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* @param
|
||||
* @param out
|
||||
* @return int
|
||||
*/
|
||||
int prindec(char_writer_t*, uint64_t out);
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* @param
|
||||
* @param fmt
|
||||
* @param ...
|
||||
* @return int
|
||||
*/
|
||||
int printf(char_writer_t*, const char* fmt, ...);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,35 +1,47 @@
|
|||
/* kmultiboot.h
|
||||
* Kernel Multiboot
|
||||
*
|
||||
* Data needed for multiboot compatibility.
|
||||
*/
|
||||
/**
|
||||
* @file kmultiboot.h
|
||||
* @brief Kernel Multiboot
|
||||
* @details Data needed for multiboot compatibility.
|
||||
*/
|
||||
#ifndef KMULTIBOOT_H
|
||||
#define KMULTIBOOT_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
typedef struct multiboot_mmap_entry {
|
||||
uint32_t entry_size; //size of this struct entry
|
||||
uint64_t addr; //physical location of memory
|
||||
uint64_t mem_size; //size of the memory block
|
||||
uint32_t type;
|
||||
uint32_t entry_size; /**< @brief size of this struct entry */
|
||||
uint64_t addr; /**< @brief physical location of memory */
|
||||
uint64_t mem_size; /**< @brief size of the memory block */
|
||||
uint32_t type; /**< @brief */
|
||||
} __attribute__((packed)) mb_mmap_entry_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
typedef struct mb_info_s {
|
||||
uint32_t flags;
|
||||
uint32_t mem_lower;
|
||||
uint32_t mem_upper;
|
||||
uint32_t boot_device;
|
||||
uint32_t cmdline;
|
||||
uint32_t mods_count;
|
||||
uint32_t mods_addr;
|
||||
uint32_t syms[4];
|
||||
uint32_t mmap_length;
|
||||
uint32_t mmap_addr;
|
||||
uint32_t flags; /**< @brief */
|
||||
uint32_t mem_lower; /**< @brief */
|
||||
uint32_t mem_upper; /**< @brief */
|
||||
uint32_t boot_device; /**< @brief */
|
||||
uint32_t cmdline; /**< @brief */
|
||||
uint32_t mods_count; /**< @brief */
|
||||
uint32_t mods_addr; /**< @brief */
|
||||
uint32_t syms[4]; /**< @brief */
|
||||
uint32_t mmap_length; /**< @brief */
|
||||
uint32_t mmap_addr; /**< @brief */
|
||||
} mb_info_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
extern uint8_t _kernel_start;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
extern uint8_t _kernel_end;
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/* kttools.h
|
||||
* Kernel Type Tools
|
||||
*
|
||||
* Library for converting types and transcribing data.
|
||||
*/
|
||||
/**
|
||||
* @file kttools.h
|
||||
* @brief Kernel Type Tools
|
||||
* @details Library for converting types and transcribing data.
|
||||
*/
|
||||
#ifndef KTTOOLS_H
|
||||
#define KTTOOLS_H
|
||||
#include <stdint.h>
|
||||
|
|
|
|||
|
|
@ -1,11 +1,29 @@
|
|||
/**
|
||||
* @file physmem.h
|
||||
* @brief
|
||||
* @details
|
||||
*/
|
||||
#ifndef PHYSMEM_H
|
||||
#define PHYSMEM_H
|
||||
#include <stdint.h>
|
||||
#include "kmultiboot.h"
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
#define PAGE_SIZE 0x1000
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
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);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -9,6 +9,11 @@
|
|||
#include "io.h"
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
|
||||
#define COM1 0x3F8
|
||||
#define COM2 0x2F8
|
||||
|
||||
typedef struct serial_ctx_s {
|
||||
uint16_t port;
|
||||
} serial_ctx_t;
|
||||
|
|
|
|||
|
|
@ -1,44 +1,64 @@
|
|||
/* tss.h
|
||||
* Task State Segment
|
||||
*
|
||||
* Structure definitions for the TSS
|
||||
/**
|
||||
* @file tss.h
|
||||
* @brief Task State Segment (TSS) definitions and structures
|
||||
* @author Jake Holtham
|
||||
* @date 2025
|
||||
*
|
||||
* This header file contains the structure definitions for the x86 Task State Segment (TSS).
|
||||
*/
|
||||
|
||||
#ifndef TSS_H
|
||||
#define TSS_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 {
|
||||
uint32_t LINK;
|
||||
uint32_t ESP0;
|
||||
uint32_t SS0;
|
||||
uint32_t ESP1;
|
||||
uint32_t SS1;
|
||||
uint32_t ESP2;
|
||||
uint32_t SS2;
|
||||
uint32_t CR3;
|
||||
uint32_t EIP;
|
||||
uint32_t EFLAGS;
|
||||
uint32_t EAX;
|
||||
uint32_t ECX;
|
||||
uint32_t EDX;
|
||||
uint32_t EBX;
|
||||
uint32_t ESP;
|
||||
uint32_t ESI;
|
||||
uint32_t EDI;
|
||||
uint32_t ES;
|
||||
uint32_t CS;
|
||||
uint32_t SS;
|
||||
uint32_t DS;
|
||||
uint32_t FS;
|
||||
uint32_t GS;
|
||||
uint32_t LDTR;
|
||||
uint32_t IOPB;
|
||||
uint32_t SSP;
|
||||
uint32_t LINK; /**< Previous TSS selector*/
|
||||
uint32_t ESP0; /**< Stack pointer for privilege level0*/
|
||||
uint32_t SS0; /**< Stack segment for privilege level0*/
|
||||
uint32_t ESP1; /**< Stack pointer for privilege level1*/
|
||||
uint32_t SS1; /**< Stack segment for privilege level1*/
|
||||
uint32_t ESP2; /**< Stack pointer for privilege level2*/
|
||||
uint32_t SS2; /**< Stack segment for privilege level2*/
|
||||
uint32_t CR3; /**< Page Directory register */
|
||||
uint32_t EIP; /**< Instruction pointer */
|
||||
uint32_t EFLAGS; /**< Flags register */
|
||||
uint32_t EAX; /**< General purpose */
|
||||
uint32_t ECX; /**< General purpose */
|
||||
uint32_t EDX; /**< General purpose */
|
||||
uint32_t EBX; /**< General purpose */
|
||||
uint32_t ESP; /**< Stack pointer */
|
||||
uint32_t ESI; /**< Source index register */
|
||||
uint32_t EDI; /**< Destination index register */
|
||||
uint32_t ES; /**< Extra segment register */
|
||||
uint32_t CS; /**< Code segment register */
|
||||
uint32_t SS; /**< Stack segment register */
|
||||
uint32_t DS; /**< Data segment register */
|
||||
uint32_t FS; /**< Extra segment register FS */
|
||||
uint32_t GS; /**< Extra segment register GS */
|
||||
uint32_t LDTR; /**< Local descriptor table register */
|
||||
uint32_t IOPB; /**< I/O permission bitmap offset */
|
||||
uint32_t SSP; /**< Stack segment pointer */
|
||||
} __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;
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
#endif /* TSS_H */
|
||||
|
|
|
|||
|
|
@ -1,42 +1,71 @@
|
|||
/* vga.h
|
||||
* VGA
|
||||
*
|
||||
* Responsible for VGA buffer control.
|
||||
/**
|
||||
* @file vga.h
|
||||
* @brief VGA
|
||||
* @details Responsible for VGA buffer control.
|
||||
*/
|
||||
#ifndef VGA_H
|
||||
#define VGA_H
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
#define VGA_GRID_COLS 80
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
#define VGA_GRID_ROWS 25
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
#define DEFAULT_ATTRIBUTES 0x0F00
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
#include "io.h"
|
||||
/*
|
||||
* CONSTANTS AND VARIABLES
|
||||
*/
|
||||
|
||||
//Information on the VGA buffer
|
||||
/**
|
||||
* @brief Information on the VGA buffer
|
||||
*/
|
||||
extern volatile uint16_t* const vga_buffer;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
typedef struct vga_ctx_s {
|
||||
int cursor_col;
|
||||
int cursor_row;
|
||||
uint16_t attributes;
|
||||
int cursor_col; /**< @brief */
|
||||
int cursor_row; /**< @brief */
|
||||
uint16_t attributes; /**< @brief */
|
||||
} vga_ctx_t;
|
||||
|
||||
//grid is top left origin. This is our cursor!
|
||||
extern uint16_t vga_attributes; // Black background, White foreground
|
||||
/**
|
||||
* @brief grid is top left origin. This is our cursor! Black background, White foreground
|
||||
*/
|
||||
extern uint16_t vga_attributes;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
extern char_writer_t* default_vga;
|
||||
|
||||
/*
|
||||
* Functions
|
||||
/**
|
||||
* @brief Clear the VGA buffer, context optional
|
||||
* @param ctx
|
||||
*/
|
||||
|
||||
//Clear the VGA buffer, context optional
|
||||
void vga_clear_ctx(vga_ctx_t* ctx);
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
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);
|
||||
|
||||
|
||||
|
|
|
|||
40
include/virtmem.h
Normal file
40
include/virtmem.h
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/**
|
||||
* @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
|
||||
26
linker.ld
26
linker.ld
|
|
@ -6,19 +6,31 @@ SECTIONS
|
|||
/*start me at 1Mb because below that is x86 essential stuff, which we dont want to be written on top of.*/
|
||||
. = 1M;
|
||||
|
||||
_kernel_start = .;
|
||||
|
||||
/* 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.*/
|
||||
/*executable section*/
|
||||
.text BLOCK(4K) : ALIGN(4K)
|
||||
{
|
||||
.mb_sect :
|
||||
{
|
||||
*(.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)
|
||||
{
|
||||
*(.text)
|
||||
}
|
||||
|
||||
/*general read only data*/
|
||||
.rodata BLOCK(4K) : ALIGN(4K)
|
||||
.rodata ALIGN (4K) : AT(ADDR(.rodata) - 0xC0000000)
|
||||
{
|
||||
*(.rodata*)
|
||||
*(.gdt_sect)
|
||||
|
|
@ -26,16 +38,18 @@ SECTIONS
|
|||
}
|
||||
|
||||
/*initialized rw data. */
|
||||
.data BLOCK(4K) : ALIGN(4K)
|
||||
.data ALIGN (4K) : AT(ADDR(.data) - 0xC0000000)
|
||||
{
|
||||
*(.data)
|
||||
}
|
||||
|
||||
/*uninitialized data, and our stack as defined in start.s*/
|
||||
.bss BLOCK(4K) : ALIGN(4K)
|
||||
.bss ALIGN(4K) : AT(ADDR(.bss) - 0xC0000000)
|
||||
{
|
||||
*(COMMON)
|
||||
*(.bss)
|
||||
*(.bootstrap_tables)
|
||||
*(.tss)
|
||||
*(.idt)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
global outb, inb
|
||||
global outb, inb, invlpg
|
||||
section .text
|
||||
outb:
|
||||
mov dx, [esp+4]
|
||||
|
|
@ -11,3 +11,8 @@ section .text
|
|||
mov dx, [esp+4]
|
||||
in al, dx
|
||||
ret
|
||||
|
||||
cr3_reload:
|
||||
mov eax, cr3
|
||||
mov cr3, eax
|
||||
ret
|
||||
|
|
|
|||
|
|
@ -55,5 +55,5 @@ section .gdt_sect
|
|||
;size of the gdt
|
||||
dw gdt_end - gdt - 1
|
||||
;location of the gdt
|
||||
dd gdt
|
||||
dd gdt - 0xC0000000
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@
|
|||
#include "idt.h"
|
||||
#include "serial.h"
|
||||
#include "physmem.h"
|
||||
|
||||
|
||||
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.
|
||||
|
|
@ -38,6 +40,8 @@ void kern_main(uint32_t multiboot_magic, mb_info_t* multiboot_info)
|
|||
//AND OUR DEFAULT OUTPUT IS:
|
||||
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);
|
||||
if(multiboot_magic != 0x2BADB002) {
|
||||
println(default_output, "Bootloader not multiboot1 compliant! Needed for mmap, etc. Can't work without it, kthxbye!");
|
||||
|
|
@ -56,10 +60,8 @@ void kern_main(uint32_t multiboot_magic, mb_info_t* multiboot_info)
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,17 +19,13 @@ void free_page(void* addr) {
|
|||
|
||||
unsigned int build_bitmap(mb_mmap_entry_t* mmap, int mmap_size) {
|
||||
//rather important global pointer to the bitmap
|
||||
pmem_bitmap = &_kernel_end;
|
||||
pmem_bitmap = (&_kernel_end);
|
||||
|
||||
|
||||
|
||||
//some variables
|
||||
int mmap_end = (uint32_t)mmap + mmap_size;
|
||||
unsigned int pages_allocated = 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.
|
||||
for(mb_mmap_entry_t* mmap_walk = mmap;
|
||||
(int)mmap_walk < mmap_end;
|
||||
|
|
|
|||
81
src/start.s
81
src/start.s
|
|
@ -5,6 +5,8 @@ bits 32
|
|||
;Some symbols we'll need from other files...
|
||||
extern kern_main
|
||||
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.
|
||||
global start
|
||||
|
||||
|
|
@ -17,21 +19,28 @@ section .bss align=16
|
|||
;Therefore, we put a label here to represent the top of our stack for later.
|
||||
stack_top:
|
||||
;We're gonna throw the TSS here too.
|
||||
|
||||
section .tss align=16 nobits
|
||||
tss:
|
||||
resb 104
|
||||
|
||||
|
||||
section .bootstrap_tables nobits align=4096
|
||||
global_page_dir:
|
||||
resb 4096
|
||||
kernel_pagetable:
|
||||
resb 4096
|
||||
|
||||
;Actual code. Entry point goes here!
|
||||
section .text
|
||||
section .lower_text exec
|
||||
;Here it is!
|
||||
start:
|
||||
;We made a GDT! Let's use it!
|
||||
lgdt [gdtr]
|
||||
lgdt [gdtr - 0xC0000000]
|
||||
;Now we start by setting the code segment (CS) with a far jump...
|
||||
jmp 0x08:segment_be_gone
|
||||
jmp 0x08:gdt_load
|
||||
|
||||
|
||||
segment_be_gone:
|
||||
gdt_load:
|
||||
;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.
|
||||
mov cx, 0x10
|
||||
|
|
@ -40,7 +49,67 @@ section .text
|
|||
mov ss, cx
|
||||
mov fs, 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
|
||||
push ebx
|
||||
push eax
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
* VARS
|
||||
*/
|
||||
|
||||
volatile uint16_t* const vga_buffer = (uint16_t*)0xB8000;
|
||||
volatile uint16_t* const vga_buffer = (uint16_t*)0xC03FF000;
|
||||
char_writer_t* default_vga = 0;
|
||||
|
||||
/*
|
||||
|
|
|
|||
10
src/virtmem.c
Normal file
10
src/virtmem.c
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
#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);
|
||||
}
|
||||
Loading…
Reference in a new issue