mirror of
https://github.com/gbowne1/ClassicOS.git
synced 2025-10-13 05:05:07 -07:00
new OS
This commit is contained in:
43
kernel/idt.c
Normal file
43
kernel/idt.c
Normal file
@@ -0,0 +1,43 @@
|
||||
#include "idt.h"
|
||||
#include "io.h"
|
||||
|
||||
#define KERNEL_CS 0x08 // Kernel code segment selector
|
||||
|
||||
idt_entry_t idt[IDT_ENTRIES];
|
||||
idt_ptr_t idt_ptr;
|
||||
|
||||
// External assembly stubs for ISRs (provided below)
|
||||
extern void isr0();
|
||||
extern void isr13();
|
||||
extern void isr_default();
|
||||
|
||||
// Helper to set an IDT gate
|
||||
void idt_set_gate(int n, uint32_t handler) {
|
||||
idt[n].offset_low = handler & 0xFFFF;
|
||||
idt[n].selector = KERNEL_CS;
|
||||
idt[n].zero = 0;
|
||||
idt[n].type_attr = 0x8E; // Present, ring 0, 32-bit interrupt gate
|
||||
idt[n].offset_high = (handler >> 16) & 0xFFFF;
|
||||
}
|
||||
|
||||
// Load IDT via lidt
|
||||
static void idt_load() {
|
||||
asm volatile("lidt (%0)" : : "r" (&idt_ptr));
|
||||
}
|
||||
|
||||
// IDT initialization
|
||||
void idt_init() {
|
||||
idt_ptr.limit = sizeof(idt_entry_t) * IDT_ENTRIES - 1;
|
||||
idt_ptr.base = (uint32_t)&idt;
|
||||
|
||||
// Clear all entries
|
||||
for (int i = 0; i < IDT_ENTRIES; i++) {
|
||||
idt_set_gate(i, (uint32_t)isr_default);
|
||||
}
|
||||
|
||||
// Set specific handlers
|
||||
idt_set_gate(0, (uint32_t)isr0); // Divide by zero
|
||||
idt_set_gate(13, (uint32_t)isr13); // General protection fault
|
||||
|
||||
idt_load();
|
||||
}
|
24
kernel/idt.h
Normal file
24
kernel/idt.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#ifndef IDT_H
|
||||
#define IDT_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define IDT_ENTRIES 256
|
||||
|
||||
typedef struct {
|
||||
uint16_t offset_low;
|
||||
uint16_t selector;
|
||||
uint8_t zero;
|
||||
uint8_t type_attr;
|
||||
uint16_t offset_high;
|
||||
} __attribute__((packed)) idt_entry_t;
|
||||
|
||||
typedef struct {
|
||||
uint16_t limit;
|
||||
uint32_t base;
|
||||
} __attribute__((packed)) idt_ptr_t;
|
||||
|
||||
void idt_set_gate(int n, uint32_t handler);
|
||||
void idt_init(void);
|
||||
|
||||
#endif
|
14
kernel/io.h
Normal file
14
kernel/io.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef IO_H
|
||||
#define IO_H
|
||||
|
||||
static inline void outb(uint16_t port, uint8_t val) {
|
||||
asm volatile ("outb %0, %1" : : "a"(val), "Nd"(port));
|
||||
}
|
||||
|
||||
static inline uint8_t inb(uint16_t port) {
|
||||
uint8_t ret;
|
||||
asm volatile ("inb %1, %0" : "=a"(ret) : "Nd"(port));
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
30
kernel/isr.asm
Normal file
30
kernel/isr.asm
Normal file
@@ -0,0 +1,30 @@
|
||||
; isr.asm
|
||||
[BITS 32]
|
||||
[GLOBAL isr0, isr13, isr_default]
|
||||
|
||||
isr0:
|
||||
cli
|
||||
push byte 0
|
||||
push byte 0
|
||||
call isr_handler
|
||||
add esp, 8
|
||||
sti
|
||||
iret
|
||||
|
||||
isr13:
|
||||
cli
|
||||
push byte 13
|
||||
push byte 0
|
||||
call isr_handler
|
||||
add esp, 8
|
||||
sti
|
||||
iret
|
||||
|
||||
isr_default:
|
||||
cli
|
||||
push byte 255
|
||||
push byte 0
|
||||
call isr_handler
|
||||
add esp, 8
|
||||
sti
|
||||
iret
|
21
kernel/isr.c
Normal file
21
kernel/isr.c
Normal file
@@ -0,0 +1,21 @@
|
||||
#include "terminal.h"
|
||||
#include "serial.h"
|
||||
|
||||
void isr_handler(uint32_t int_num, uint32_t err_code) {
|
||||
terminal_write("Interrupt occurred: ");
|
||||
// Add simple int-to-string printing here
|
||||
serial_write("INT triggered\n");
|
||||
|
||||
if (int_num == 0) {
|
||||
terminal_write(" -> Divide by zero error!\n");
|
||||
} else if (int_num == 13) {
|
||||
terminal_write(" -> General Protection Fault!\n");
|
||||
} else {
|
||||
terminal_write(" -> Unknown interrupt\n");
|
||||
}
|
||||
|
||||
// Halt CPU
|
||||
while (1) {
|
||||
asm volatile ("hlt");
|
||||
}
|
||||
}
|
53
kernel/kmain.c
Normal file
53
kernel/kmain.c
Normal file
@@ -0,0 +1,53 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "io.h"
|
||||
#include "serial.h"
|
||||
#include "terminal.h"
|
||||
#include "idt.h"
|
||||
#include "paging.h"
|
||||
#include "memmap.h"
|
||||
|
||||
#define LPT1 0x378
|
||||
|
||||
void lpt_write(char c) {
|
||||
while ((inb(LPT1 + 1) & 0x80) == 0); // Wait for ready
|
||||
outb(LPT1, c);
|
||||
}
|
||||
|
||||
void kmain(void) {
|
||||
terminal_initialize();
|
||||
terminal_write("Welcome to ClassicOS\n");
|
||||
|
||||
serial_init();
|
||||
serial_write("Serial port initialized.\n");
|
||||
|
||||
lpt_write('L'); // Send 'L' to LPT1 to test
|
||||
|
||||
terminal_write("Initializing IDT...\n");
|
||||
idt_init();
|
||||
serial_write("IDT initialized.\n");
|
||||
|
||||
terminal_write("Enabling paging...\n");
|
||||
paging_init();
|
||||
serial_write("Paging initialized.\n");
|
||||
|
||||
terminal_write("Getting memory map...\n");
|
||||
memory_map_entry_t mmap[32];
|
||||
uint32_t mmap_size = get_memory_map(mmap, 32);
|
||||
serial_write("Memory map retrieved.\n");
|
||||
|
||||
terminal_write("Memory Regions:\n");
|
||||
for (uint32_t i = 0; i < mmap_size; i++) {
|
||||
terminal_write(" - Region: ");
|
||||
// You would format and print base/length/type here
|
||||
// (e.g., with a basic itoa and print_hex helper)
|
||||
serial_write("Memory region entry\n");
|
||||
}
|
||||
|
||||
terminal_write("System initialized. Halting.\n");
|
||||
|
||||
// Halt CPU in loop
|
||||
while (1) {
|
||||
asm volatile("hlt");
|
||||
}
|
||||
}
|
14
kernel/memmap.c
Normal file
14
kernel/memmap.c
Normal file
@@ -0,0 +1,14 @@
|
||||
#include "memmap.h"
|
||||
|
||||
uint32_t get_memory_map(memory_map_entry_t *map, uint32_t max_entries) {
|
||||
// Fill with dummy values for now
|
||||
map[0].base_addr = 0x00000000;
|
||||
map[0].length = 0x0009FC00;
|
||||
map[0].type = 1;
|
||||
|
||||
map[1].base_addr = 0x00100000;
|
||||
map[1].length = 0x1FF00000;
|
||||
map[1].type = 1;
|
||||
|
||||
return 2; // 2 regions
|
||||
}
|
14
kernel/memmap.h
Normal file
14
kernel/memmap.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef MEMMAP_H
|
||||
#define MEMMAP_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
uint64_t base_addr;
|
||||
uint64_t length;
|
||||
uint32_t type;
|
||||
} __attribute__((packed)) memory_map_entry_t;
|
||||
|
||||
uint32_t get_memory_map(memory_map_entry_t *map, uint32_t max_entries);
|
||||
|
||||
#endif
|
56
kernel/paging.c
Normal file
56
kernel/paging.c
Normal file
@@ -0,0 +1,56 @@
|
||||
#include "paging.h"
|
||||
#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
|
||||
|
||||
// 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 = 1;
|
||||
dir[i].rw = 1; // Read/Write
|
||||
dir[i].user = 0; // Kernel mode
|
||||
dir[i].write_through = 0;
|
||||
dir[i].cache_disabled = 0;
|
||||
dir[i].accessed = 0;
|
||||
dir[i].frame = (uint32_t)&page_table[i] >> 12; // Page table frame address
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function to set up the page table entry
|
||||
void set_page_table(page_table_entry_t *table) {
|
||||
for (int i = 0; i < PAGE_TABLE_SIZE; i++) {
|
||||
// Set up page table entries with identity mapping
|
||||
table[i].present = 1;
|
||||
table[i].rw = 1; // Read/Write
|
||||
table[i].user = 0; // Kernel mode
|
||||
table[i].write_through = 0;
|
||||
table[i].cache_disabled = 0;
|
||||
table[i].accessed = 0;
|
||||
table[i].frame = i; // Identity mapping
|
||||
}
|
||||
}
|
||||
|
||||
// Enable paging by loading the page directory into CR3 and setting the PG bit in CR0
|
||||
void enable_paging() {
|
||||
uint32_t cr0;
|
||||
|
||||
// Load page directory into CR3
|
||||
asm volatile("mov %0, %%cr3" : : "r"(page_directory));
|
||||
|
||||
// Enable paging (set the PG bit in CR0)
|
||||
asm volatile("mov %%cr0, %0" : "=r"(cr0));
|
||||
cr0 |= 0x80000000; // Set the PG (paging) bit
|
||||
asm volatile("mov %0, %%cr0" : : "r"(cr0));
|
||||
}
|
||||
|
||||
// Initialize paging: set up the page directory and enable paging
|
||||
void paging_init() {
|
||||
// Set up the page directory and page tables
|
||||
set_page_directory(page_directory);
|
||||
set_page_table(page_table);
|
||||
|
||||
// Enable paging
|
||||
enable_paging();
|
||||
}
|
47
kernel/paging.h
Normal file
47
kernel/paging.h
Normal file
@@ -0,0 +1,47 @@
|
||||
#ifndef PAGING_H
|
||||
#define PAGING_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#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
|
||||
|
||||
// Page Directory and Page Table structure
|
||||
typedef struct {
|
||||
uint32_t present : 1; // Present bit (1: page is present in memory)
|
||||
uint32_t rw : 1; // Read-Write bit (1: page is read-write)
|
||||
uint32_t user : 1; // User-supervisor bit (1: user mode access)
|
||||
uint32_t write_through : 1; // Write-through cache
|
||||
uint32_t cache_disabled : 1; // Cache disabled
|
||||
uint32_t accessed : 1; // Accessed bit
|
||||
uint32_t reserved : 1; // Reserved bit
|
||||
uint32_t page_size : 1; // Page size (0: 4KB, 1: 4MB)
|
||||
uint32_t global : 1; // Global page (can be used across different processes)
|
||||
uint32_t available : 3; // Available bits for the system
|
||||
uint32_t frame : 20; // Frame address (physical address)
|
||||
} __attribute__((packed)) page_table_entry_t;
|
||||
|
||||
// Define page directory entry
|
||||
typedef struct {
|
||||
uint32_t present : 1;
|
||||
uint32_t rw : 1;
|
||||
uint32_t user : 1;
|
||||
uint32_t write_through : 1;
|
||||
uint32_t cache_disabled : 1;
|
||||
uint32_t accessed : 1;
|
||||
uint32_t reserved : 1;
|
||||
uint32_t zero : 5; // Must be zero for page directory
|
||||
uint32_t reserved_2 : 7; // Reserved bits
|
||||
uint32_t frame : 20; // Frame address of the page table
|
||||
} __attribute__((packed)) page_directory_entry_t;
|
||||
|
||||
extern page_directory_entry_t *page_directory;
|
||||
extern page_table_entry_t *page_table;
|
||||
|
||||
void paging_init(void);
|
||||
void set_page_directory(page_directory_entry_t *dir);
|
||||
void set_page_table(page_table_entry_t *table);
|
||||
void enable_paging(void);
|
||||
|
||||
#endif
|
20
kernel/serial.c
Normal file
20
kernel/serial.c
Normal file
@@ -0,0 +1,20 @@
|
||||
#include "io.h"
|
||||
|
||||
#define COM1 0x3F8
|
||||
|
||||
void serial_init(void) {
|
||||
outb(COM1 + 1, 0x00); // Disable interrupts
|
||||
outb(COM1 + 3, 0x80); // Enable DLAB
|
||||
outb(COM1 + 0, 0x03); // Set baud rate to 38400
|
||||
outb(COM1 + 1, 0x00);
|
||||
outb(COM1 + 3, 0x03); // 8 bits, no parity, one stop bit
|
||||
outb(COM1 + 2, 0xC7); // Enable FIFO, clear, 14-byte threshold
|
||||
outb(COM1 + 4, 0x0B); // IRQs enabled, RTS/DSR set
|
||||
}
|
||||
|
||||
void serial_write(const char *str) {
|
||||
while (*str) {
|
||||
while (!(inb(COM1 + 5) & 0x20)); // Wait for the transmitter holding register to be empty
|
||||
outb(COM1, *str++);
|
||||
}
|
||||
}
|
10
kernel/serial.h
Normal file
10
kernel/serial.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#ifndef SERIAL_H
|
||||
#define SERIAL_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void serial_init(void);
|
||||
void serial_write(char c);
|
||||
void serial_write_string(const char *str);
|
||||
|
||||
#endif
|
63
kernel/terminal.c
Normal file
63
kernel/terminal.c
Normal file
@@ -0,0 +1,63 @@
|
||||
#include <stdint.h>
|
||||
#include "io.h"
|
||||
|
||||
#define VGA_ADDRESS 0xB8000
|
||||
#define VGA_WIDTH 80
|
||||
#define VGA_HEIGHT 25
|
||||
#define WHITE_ON_BLACK 0x0F
|
||||
|
||||
static uint16_t* const vga_buffer = (uint16_t*) VGA_ADDRESS;
|
||||
static uint8_t cursor_x = 0;
|
||||
static uint8_t cursor_y = 0;
|
||||
|
||||
static uint16_t vga_entry(char c, uint8_t color) {
|
||||
return (uint16_t) color << 8 | (uint8_t) c;
|
||||
}
|
||||
|
||||
void terminal_initialize(void) {
|
||||
for (uint16_t y = 0; y < VGA_HEIGHT; y++) {
|
||||
for (uint16_t x = 0; x < VGA_WIDTH; x++) {
|
||||
const size_t index = y * VGA_WIDTH + x;
|
||||
vga_buffer[index] = vga_entry(' ', WHITE_ON_BLACK);
|
||||
}
|
||||
}
|
||||
cursor_x = 0;
|
||||
cursor_y = 0;
|
||||
}
|
||||
|
||||
void terminal_putchar(char c) {
|
||||
if (c == '\n') {
|
||||
cursor_x = 0;
|
||||
cursor_y++;
|
||||
} else {
|
||||
const size_t index = cursor_y * VGA_WIDTH + cursor_x;
|
||||
vga_buffer[index] = vga_entry(c, WHITE_ON_BLACK);
|
||||
cursor_x++;
|
||||
if (cursor_x >= VGA_WIDTH) {
|
||||
cursor_x = 0;
|
||||
cursor_y++;
|
||||
}
|
||||
}
|
||||
|
||||
// Scroll if needed
|
||||
if (cursor_y >= VGA_HEIGHT) {
|
||||
for (uint16_t y = 1; y < VGA_HEIGHT; y++) {
|
||||
for (uint16_t x = 0; x < VGA_WIDTH; x++) {
|
||||
vga_buffer[(y - 1) * VGA_WIDTH + x] = vga_buffer[y * VGA_WIDTH + x];
|
||||
}
|
||||
}
|
||||
|
||||
// Clear the last line
|
||||
for (uint16_t x = 0; x < VGA_WIDTH; x++) {
|
||||
vga_buffer[(VGA_HEIGHT - 1) * VGA_WIDTH + x] = vga_entry(' ', WHITE_ON_BLACK);
|
||||
}
|
||||
|
||||
cursor_y = VGA_HEIGHT - 1;
|
||||
}
|
||||
}
|
||||
|
||||
void terminal_write(const char* str) {
|
||||
for (size_t i = 0; str[i] != '\0'; i++) {
|
||||
terminal_putchar(str[i]);
|
||||
}
|
||||
}
|
11
kernel/terminal.h
Normal file
11
kernel/terminal.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#ifndef TERMINAL_H
|
||||
#define TERMINAL_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void terminal_initialize(void);
|
||||
void terminal_putchar(char c);
|
||||
void terminal_write(const char *str);
|
||||
void terminal_setcolor(uint8_t color);
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user