mirror of
https://github.com/gbowne1/ClassicOS.git
synced 2025-05-15 09:01:27 -07:00
doing some memory work and gdt and timer and vga
This commit is contained in:
parent
10b8fdc33f
commit
799f744f47
@ -0,0 +1,21 @@
|
|||||||
|
; gdt.asm
|
||||||
|
; Assembler function to load the GDT and update segment registers
|
||||||
|
|
||||||
|
global gdt_flush
|
||||||
|
|
||||||
|
gdt_flush:
|
||||||
|
mov eax, [esp + 4] ; Argument: pointer to GDT descriptor
|
||||||
|
lgdt [eax] ; Load GDT
|
||||||
|
|
||||||
|
; Reload segment registers
|
||||||
|
mov ax, 0x10 ; 0x10 = offset to kernel data segment (3rd entry)
|
||||||
|
mov ds, ax
|
||||||
|
mov es, ax
|
||||||
|
mov fs, ax
|
||||||
|
mov gs, ax
|
||||||
|
mov ss, ax
|
||||||
|
|
||||||
|
; Jump to flush the instruction pipeline and load CS
|
||||||
|
jmp 0x08:.flush ; 0x08 = offset to code segment (2nd entry)
|
||||||
|
.flush:
|
||||||
|
ret
|
48
kernel/gdt.c
48
kernel/gdt.c
@ -0,0 +1,48 @@
|
|||||||
|
#include "gdt.h"
|
||||||
|
|
||||||
|
// Structure of a GDT entry (8 bytes)
|
||||||
|
struct gdt_entry {
|
||||||
|
uint16_t limit_low; // Limit bits 0–15
|
||||||
|
uint16_t base_low; // Base bits 0–15
|
||||||
|
uint8_t base_middle; // Base bits 16–23
|
||||||
|
uint8_t access; // Access flags
|
||||||
|
uint8_t granularity; // Granularity + limit bits 16–19
|
||||||
|
uint8_t base_high; // Base bits 24–31
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
// Structure of the GDT pointer
|
||||||
|
struct gdt_ptr {
|
||||||
|
uint16_t limit;
|
||||||
|
uint32_t base;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
// Declare GDT with 3 entries
|
||||||
|
static struct gdt_entry gdt[3];
|
||||||
|
static struct gdt_ptr gp;
|
||||||
|
|
||||||
|
// External ASM function to load GDT
|
||||||
|
extern void gdt_flush(uint32_t);
|
||||||
|
|
||||||
|
// Set an individual GDT entry
|
||||||
|
static void gdt_set_gate(int num, uint32_t base, uint32_t limit, uint8_t access, uint8_t granularity) {
|
||||||
|
gdt[num].base_low = (base & 0xFFFF);
|
||||||
|
gdt[num].base_middle = (base >> 16) & 0xFF;
|
||||||
|
gdt[num].base_high = (base >> 24) & 0xFF;
|
||||||
|
|
||||||
|
gdt[num].limit_low = (limit & 0xFFFF);
|
||||||
|
gdt[num].granularity = ((limit >> 16) & 0x0F) | (granularity & 0xF0);
|
||||||
|
|
||||||
|
gdt[num].access = access;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize the GDT
|
||||||
|
void gdt_init(void) {
|
||||||
|
gp.limit = (sizeof(struct gdt_entry) * 3) - 1;
|
||||||
|
gp.base = (uint32_t)&gdt;
|
||||||
|
|
||||||
|
gdt_set_gate(0, 0, 0, 0, 0); // Null segment
|
||||||
|
gdt_set_gate(1, 0, 0xFFFFFFFF, 0x9A, 0xCF); // Code segment
|
||||||
|
gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF); // Data segment
|
||||||
|
|
||||||
|
gdt_flush((uint32_t)&gp);
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
#ifndef GDT_H
|
||||||
|
#define GDT_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
void gdt_init(void);
|
||||||
|
|
||||||
|
#endif
|
15
kernel/isr.c
15
kernel/isr.c
@ -1,11 +1,19 @@
|
|||||||
#include "terminal.h"
|
#include "terminal.h"
|
||||||
#include "serial.h"
|
#include "serial.h"
|
||||||
|
#include "isr.h"
|
||||||
|
|
||||||
|
static isr_callback_t interrupt_handlers[MAX_INTERRUPTS] = { 0 };
|
||||||
|
|
||||||
void isr_handler(uint32_t int_num, uint32_t err_code) {
|
void isr_handler(uint32_t int_num, uint32_t err_code) {
|
||||||
terminal_write("Interrupt occurred: ");
|
terminal_write("Interrupt occurred: ");
|
||||||
// Add simple int-to-string printing here
|
// Here you can add a basic itoa to print int_num
|
||||||
serial_write("INT triggered\n");
|
serial_write("INT triggered\n");
|
||||||
|
|
||||||
|
if (interrupt_handlers[int_num]) {
|
||||||
|
interrupt_handlers[int_num](); // Call registered handler
|
||||||
|
} else {
|
||||||
|
terminal_write(" -> No handler registered\n");
|
||||||
|
|
||||||
if (int_num == 0) {
|
if (int_num == 0) {
|
||||||
terminal_write(" -> Divide by zero error!\n");
|
terminal_write(" -> Divide by zero error!\n");
|
||||||
} else if (int_num == 13) {
|
} else if (int_num == 13) {
|
||||||
@ -19,3 +27,8 @@ void isr_handler(uint32_t int_num, uint32_t err_code) {
|
|||||||
asm volatile ("hlt");
|
asm volatile ("hlt");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void register_interrupt_handler(uint8_t n, isr_callback_t handler) {
|
||||||
|
interrupt_handlers[n] = handler;
|
||||||
|
}
|
||||||
|
13
kernel/isr.h
13
kernel/isr.h
@ -0,0 +1,13 @@
|
|||||||
|
#ifndef ISR_H
|
||||||
|
#define ISR_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define MAX_INTERRUPTS 256
|
||||||
|
|
||||||
|
typedef void (*isr_callback_t)(void);
|
||||||
|
|
||||||
|
void isr_handler(uint32_t int_num, uint32_t err_code);
|
||||||
|
void register_interrupt_handler(uint8_t n, isr_callback_t handler);
|
||||||
|
|
||||||
|
#endif
|
@ -31,6 +31,17 @@ void kmain(void) {
|
|||||||
paging_init();
|
paging_init();
|
||||||
serial_write("Paging initialized.\n");
|
serial_write("Paging initialized.\n");
|
||||||
|
|
||||||
|
terminal_write("Initializing memory allocator...\n");
|
||||||
|
kmalloc_init(0xC0100000); // Virtual heap start address (must be mapped!)
|
||||||
|
serial_write("kmalloc initialized.\n");
|
||||||
|
|
||||||
|
void* ptr = kmalloc(128); // Allocation test
|
||||||
|
serial_write("Allocated 128 bytes.\n");
|
||||||
|
|
||||||
|
terminal_write("Initializing timer...\n");
|
||||||
|
timer_init(100); // 100 Hz (10 ms interval)
|
||||||
|
serial_write("Timer initialized.\n");
|
||||||
|
|
||||||
terminal_write("Getting memory map...\n");
|
terminal_write("Getting memory map...\n");
|
||||||
memory_map_entry_t mmap[32];
|
memory_map_entry_t mmap[32];
|
||||||
uint32_t mmap_size = get_memory_map(mmap, 32);
|
uint32_t mmap_size = get_memory_map(mmap, 32);
|
||||||
|
@ -0,0 +1,38 @@
|
|||||||
|
#include "kmalloc.h"
|
||||||
|
#include "terminal.h" // Optional: for debug output
|
||||||
|
|
||||||
|
static uint32_t current_heap = 0;
|
||||||
|
|
||||||
|
// Initialize the allocator with a starting heap address
|
||||||
|
void kmalloc_init(uint32_t heap_start) {
|
||||||
|
current_heap = heap_start;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simple bump allocator
|
||||||
|
void* kmalloc(size_t size) {
|
||||||
|
if (current_heap == 0) {
|
||||||
|
terminal_write("kmalloc used before initialization!\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* addr = (void*)current_heap;
|
||||||
|
current_heap += size;
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate memory aligned to a power-of-two boundary (e.g., 0x1000)
|
||||||
|
void* kmalloc_aligned(size_t size, uint32_t alignment) {
|
||||||
|
if (current_heap == 0) {
|
||||||
|
terminal_write("kmalloc_aligned used before initialization!\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Align the current_heap pointer
|
||||||
|
if ((current_heap & (alignment - 1)) != 0) {
|
||||||
|
current_heap = (current_heap + alignment) & ~(alignment - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* addr = (void*)current_heap;
|
||||||
|
current_heap += size;
|
||||||
|
return addr;
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
#ifndef KMALLOC_H
|
||||||
|
#define KMALLOC_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h> // for size_t
|
||||||
|
|
||||||
|
void kmalloc_init(uint32_t heap_start);
|
||||||
|
void* kmalloc(size_t size);
|
||||||
|
void* kmalloc_aligned(size_t size, uint32_t alignment);
|
||||||
|
|
||||||
|
#endif
|
@ -2,20 +2,18 @@
|
|||||||
#include "io.h"
|
#include "io.h"
|
||||||
|
|
||||||
page_directory_entry_t *page_directory = (page_directory_entry_t *)0x100000;
|
page_directory_entry_t *page_directory = (page_directory_entry_t *)0x100000;
|
||||||
page_table_entry_t *page_table = (page_table_entry_t *)0x101000; // Located right after the page directory
|
page_table_entry_t *page_table = (page_table_entry_t *)0x101000;
|
||||||
|
page_table_entry_t *heap_page_table = (page_table_entry_t *)0x102000; // Located right after the page directory
|
||||||
|
|
||||||
// Helper function to set up the page directory entry
|
// Helper function to set up the page directory entry
|
||||||
void set_page_directory(page_directory_entry_t *dir) {
|
void set_page_directory(page_directory_entry_t *dir) {
|
||||||
for (int i = 0; i < PAGE_DIRECTORY_SIZE; i++) {
|
for (int i = 0; i < PAGE_DIRECTORY_SIZE; i++) {
|
||||||
// Set up a page directory entry with identity mapping
|
dir[i].present = 0;
|
||||||
dir[i].present = 9;
|
|
||||||
dir[i].rw = 0; // Read/Write
|
|
||||||
dir[i].user = 0; // Kernel mode
|
|
||||||
dir[i].write_through = 0;
|
|
||||||
dir[i].cache_disabled = 0;
|
|
||||||
dir[i].accessed = 0;
|
|
||||||
dir[0].frame = (uint32_t)page_table >> 12;
|
|
||||||
}
|
}
|
||||||
|
dir[0].present = 1;
|
||||||
|
dir[0].rw = 1;
|
||||||
|
dir[0].user = 0;
|
||||||
|
dir[0].frame = (uint32_t)page_table >> 12;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper function to set up the page table entry
|
// Helper function to set up the page table entry
|
||||||
@ -47,10 +45,26 @@ void enable_paging() {
|
|||||||
|
|
||||||
// Initialize paging: set up the page directory and enable paging
|
// Initialize paging: set up the page directory and enable paging
|
||||||
void paging_init() {
|
void paging_init() {
|
||||||
// Set up the page directory and page tables
|
// Set up identity-mapped page directory + table
|
||||||
set_page_directory(page_directory);
|
set_page_directory(page_directory);
|
||||||
set_page_table(page_table);
|
set_page_table(page_table);
|
||||||
|
|
||||||
// Enable paging
|
// === Set up heap mapping at 0xC0100000 ===
|
||||||
|
for (int i = 0; i < PAGE_TABLE_SIZE; i++) {
|
||||||
|
heap_page_table[i].present = 1;
|
||||||
|
heap_page_table[i].rw = 1;
|
||||||
|
heap_page_table[i].user = 0;
|
||||||
|
heap_page_table[i].write_through = 0;
|
||||||
|
heap_page_table[i].cache_disabled = 0;
|
||||||
|
heap_page_table[i].accessed = 0;
|
||||||
|
heap_page_table[i].frame = (256 + i); // Start physical heap at 1MB (256*4KB = 1MB)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Index 772 = 0xC0100000 / 4MB
|
||||||
|
page_directory[772].present = 1;
|
||||||
|
page_directory[772].rw = 1;
|
||||||
|
page_directory[772].user = 0;
|
||||||
|
page_directory[772].frame = (uint32_t)heap_page_table >> 12;
|
||||||
|
|
||||||
enable_paging();
|
enable_paging();
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#define PAGE_SIZE 4096 // Page size in bytes
|
#define PAGE_SIZE 4096 // Page size in bytes
|
||||||
#define PAGE_DIRECTORY_SIZE 1024 // 1024 entries in page directory
|
#define PAGE_DIRECTORY_SIZE 1024 // 1024 entries in page directory
|
||||||
#define PAGE_TABLE_SIZE 1024 // 1024 entries in a page table
|
#define PAGE_TABLE_SIZE 1024 // 1024 entries in a page table
|
||||||
|
#define KERNEL_HEAP_START 0xC0100000
|
||||||
|
|
||||||
// Page Directory and Page Table structure
|
// Page Directory and Page Table structure
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -0,0 +1,28 @@
|
|||||||
|
#include "timer.h"
|
||||||
|
#include "io.h"
|
||||||
|
#include "isr.h"
|
||||||
|
#include "terminal.h"
|
||||||
|
|
||||||
|
static uint32_t tick = 0;
|
||||||
|
|
||||||
|
void timer_callback(void) {
|
||||||
|
tick++;
|
||||||
|
// Optional: Print every 100 ticks
|
||||||
|
// if (tick % 100 == 0) {
|
||||||
|
// terminal_write("Tick\n");
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
void timer_init(uint32_t frequency) {
|
||||||
|
register_interrupt_handler(32, timer_callback); // IRQ0 = Interrupt 32
|
||||||
|
|
||||||
|
uint32_t divisor = 1193180 / frequency;
|
||||||
|
|
||||||
|
outb(0x43, 0x36); // Command byte
|
||||||
|
outb(0x40, divisor & 0xFF); // Low byte
|
||||||
|
outb(0x40, (divisor >> 8)); // High byte
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t timer_get_ticks(void) {
|
||||||
|
return tick;
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
#ifndef TIMER_H
|
||||||
|
#define TIMER_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
void timer_init(uint32_t frequency);
|
||||||
|
uint32_t timer_get_ticks(void);
|
||||||
|
|
||||||
|
#endif
|
@ -0,0 +1,9 @@
|
|||||||
|
#include "vga.h"
|
||||||
|
|
||||||
|
uint8_t vga_entry_color(vga_color fg, vga_color bg) {
|
||||||
|
return fg | bg << 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t vga_entry(unsigned char uc, uint8_t color) {
|
||||||
|
return (uint16_t)uc | (uint16_t)color << 8;
|
||||||
|
}
|
28
kernel/vga.h
28
kernel/vga.h
@ -0,0 +1,28 @@
|
|||||||
|
#ifndef VGA_H
|
||||||
|
#define VGA_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
VGA_COLOR_BLACK = 0,
|
||||||
|
VGA_COLOR_BLUE = 1,
|
||||||
|
VGA_COLOR_GREEN = 2,
|
||||||
|
VGA_COLOR_CYAN = 3,
|
||||||
|
VGA_COLOR_RED = 4,
|
||||||
|
VGA_COLOR_MAGENTA = 5,
|
||||||
|
VGA_COLOR_BROWN = 6,
|
||||||
|
VGA_COLOR_LIGHT_GREY = 7,
|
||||||
|
VGA_COLOR_DARK_GREY = 8,
|
||||||
|
VGA_COLOR_LIGHT_BLUE = 9,
|
||||||
|
VGA_COLOR_LIGHT_GREEN = 10,
|
||||||
|
VGA_COLOR_LIGHT_CYAN = 11,
|
||||||
|
VGA_COLOR_LIGHT_RED = 12,
|
||||||
|
VGA_COLOR_LIGHT_MAGENTA = 13,
|
||||||
|
VGA_COLOR_LIGHT_BROWN = 14,
|
||||||
|
VGA_COLOR_WHITE = 15,
|
||||||
|
} vga_color;
|
||||||
|
|
||||||
|
uint8_t vga_entry_color(vga_color fg, vga_color bg);
|
||||||
|
uint16_t vga_entry(unsigned char uc, uint8_t color);
|
||||||
|
|
||||||
|
#endif
|
Loading…
x
Reference in New Issue
Block a user