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 "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) {
|
||||
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");
|
||||
|
||||
if (interrupt_handlers[int_num]) {
|
||||
interrupt_handlers[int_num](); // Call registered handler
|
||||
} else {
|
||||
terminal_write(" -> No handler registered\n");
|
||||
|
||||
if (int_num == 0) {
|
||||
terminal_write(" -> Divide by zero error!\n");
|
||||
} else if (int_num == 13) {
|
||||
@ -18,4 +26,9 @@ void isr_handler(uint32_t int_num, uint32_t err_code) {
|
||||
while (1) {
|
||||
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();
|
||||
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");
|
||||
memory_map_entry_t 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"
|
||||
|
||||
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
|
||||
void set_page_directory(page_directory_entry_t *dir) {
|
||||
for (int i = 0; i < PAGE_DIRECTORY_SIZE; i++) {
|
||||
// Set up a page directory entry with identity mapping
|
||||
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[i].present = 0;
|
||||
}
|
||||
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
|
||||
@ -47,10 +45,26 @@ void enable_paging() {
|
||||
|
||||
// Initialize paging: set up the page directory and enable paging
|
||||
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_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();
|
||||
}
|
||||
|
@ -6,6 +6,7 @@
|
||||
#define PAGE_SIZE 4096 // Page size in bytes
|
||||
#define PAGE_DIRECTORY_SIZE 1024 // 1024 entries in page directory
|
||||
#define PAGE_TABLE_SIZE 1024 // 1024 entries in a page table
|
||||
#define KERNEL_HEAP_START 0xC0100000
|
||||
|
||||
// Page Directory and Page Table structure
|
||||
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