mirror of
				https://github.com/gbowne1/ClassicOS.git
				synced 2025-10-30 11:55:07 -07:00 
			
		
		
		
	doing some memory work and gdt and timer and vga
This commit is contained in:
		| @@ -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 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user