mirror of
https://github.com/gbowne1/ClassicOS.git
synced 2025-05-15 09:01:27 -07:00
addind more important kernel files and also fixing bugs
This commit is contained in:
parent
512bd49ff7
commit
a9f2826014
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@ -1,6 +1,7 @@
|
||||
{
|
||||
"files.associations": {
|
||||
".fantomasignore": "ignore",
|
||||
"stddef.h": "c"
|
||||
"stddef.h": "c",
|
||||
"io.h": "c"
|
||||
}
|
||||
}
|
35
kernel/cpu.c
Normal file
35
kernel/cpu.c
Normal file
@ -0,0 +1,35 @@
|
||||
#include "cpu.h"
|
||||
#include "serial.h"
|
||||
#include "terminal.h"
|
||||
|
||||
void cpuid(uint32_t function, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) {
|
||||
asm volatile (
|
||||
"cpuid"
|
||||
: "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx)
|
||||
: "a"(function)
|
||||
);
|
||||
}
|
||||
|
||||
void identify_cpu() {
|
||||
uint32_t eax, ebx, ecx, edx;
|
||||
char vendor[13];
|
||||
|
||||
cpuid(0, &eax, &ebx, &ecx, &edx);
|
||||
|
||||
*(uint32_t *)&vendor[0] = ebx;
|
||||
*(uint32_t *)&vendor[4] = edx;
|
||||
*(uint32_t *)&vendor[8] = ecx;
|
||||
vendor[12] = '\0';
|
||||
|
||||
terminal_write("CPU Vendor: ");
|
||||
terminal_write(vendor);
|
||||
terminal_write("\n");
|
||||
|
||||
serial_write("CPU Vendor: ");
|
||||
serial_write(vendor);
|
||||
serial_write("\n");
|
||||
|
||||
terminal_write("CPUID max leaf: ");
|
||||
print_hex(eax); // You must implement this (see below)
|
||||
terminal_write("\n");
|
||||
}
|
9
kernel/cpu.h
Normal file
9
kernel/cpu.h
Normal file
@ -0,0 +1,9 @@
|
||||
#ifndef CPU_H
|
||||
#define CPU_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void cpuid(uint32_t function, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx);
|
||||
void identify_cpu(void);
|
||||
|
||||
#endif // CPU_H
|
0
kernel/elf.c
Normal file
0
kernel/elf.c
Normal file
0
kernel/elf.h
Normal file
0
kernel/elf.h
Normal file
12
kernel/isr.c
12
kernel/isr.c
@ -1,12 +1,12 @@
|
||||
#include "terminal.h"
|
||||
#include "serial.h"
|
||||
#include "isr.h"
|
||||
#include "io.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: ");
|
||||
// Here you can add a basic itoa to print int_num
|
||||
serial_write("INT triggered\n");
|
||||
|
||||
if (interrupt_handlers[int_num]) {
|
||||
@ -27,6 +27,16 @@ void isr_handler(uint32_t int_num, uint32_t err_code) {
|
||||
asm volatile ("hlt");
|
||||
}
|
||||
}
|
||||
|
||||
// === Send End Of Interrupt to PIC(s) ===
|
||||
if (int_num >= 40) {
|
||||
// Send reset signal to slave PIC
|
||||
outb(0xA0, 0x20);
|
||||
}
|
||||
if (int_num >= 32) {
|
||||
// Send reset signal to master PIC
|
||||
outb(0x20, 0x20);
|
||||
}
|
||||
}
|
||||
|
||||
void register_interrupt_handler(uint8_t n, isr_callback_t handler) {
|
||||
|
97
kernel/malloc.c
Normal file
97
kernel/malloc.c
Normal file
@ -0,0 +1,97 @@
|
||||
#include "malloc.h"
|
||||
#include <stdint.h>
|
||||
|
||||
static void *heap_start; // Start of the heap
|
||||
static void *heap_end; // End of the heap
|
||||
static struct memory_block *free_blocks; // List of free blocks
|
||||
|
||||
void init_heap(void *start, void *end)
|
||||
{
|
||||
heap_start = start;
|
||||
heap_end = end;
|
||||
|
||||
// Initialize the heap with a single large free block
|
||||
free_blocks = (struct memory_block *)start;
|
||||
free_blocks->size = (uintptr_t)end - (uintptr_t)start - sizeof(struct memory_block);
|
||||
free_blocks->next = NULL;
|
||||
free_blocks->is_free = 1;
|
||||
}
|
||||
|
||||
void *find_free_block(size_t size) {
|
||||
struct memory_block *current = free_blocks;
|
||||
while (current != NULL) {
|
||||
if (current->is_free && current->size >= size) {
|
||||
return current;
|
||||
}
|
||||
current = current->next;
|
||||
}
|
||||
// No suitable block found
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void mark_as_used(void *ptr, size_t size) {
|
||||
struct memory_block *block = (struct memory_block *)ptr;
|
||||
block->is_free = 0;
|
||||
|
||||
// If the block is larger than needed, split it
|
||||
if (block->size > size + sizeof(struct memory_block)) {
|
||||
struct memory_block *new_block = (struct memory_block *)((uintptr_t)ptr + size + sizeof(struct memory_block));
|
||||
new_block->size = block->size - size - sizeof(struct memory_block);
|
||||
new_block->next = block->next;
|
||||
new_block->is_free = 1;
|
||||
|
||||
block->size = size;
|
||||
block->next = new_block;
|
||||
}
|
||||
}
|
||||
|
||||
void mark_as_free(void *ptr) {
|
||||
struct memory_block *block = (struct memory_block *)ptr;
|
||||
block->is_free = 1;
|
||||
|
||||
// Coalesce with next block if it's free
|
||||
if (block->next && block->next->is_free) {
|
||||
block->size += block->next->size + sizeof(struct memory_block);
|
||||
block->next = block->next->next;
|
||||
}
|
||||
|
||||
// TODO: Implement coalescing with previous block
|
||||
}
|
||||
|
||||
void *malloc(size_t size)
|
||||
{
|
||||
if (heap_start == NULL || heap_end == NULL)
|
||||
{
|
||||
// Heap not initialized, cannot allocate
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Align the size to the word size for efficiency
|
||||
size = (size + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1);
|
||||
|
||||
// Search for a free block of sufficient size
|
||||
void *block = find_free_block(size);
|
||||
if (block != NULL)
|
||||
{
|
||||
// Mark the block as used
|
||||
mark_as_used(block, size);
|
||||
return (void *)((uintptr_t)block + sizeof(struct memory_block));
|
||||
}
|
||||
|
||||
// No suitable block found, out of memory
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void free(void *ptr)
|
||||
{
|
||||
if (ptr == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Adjust pointer to the start of the memory block
|
||||
struct memory_block *block = (struct memory_block *)((uintptr_t)ptr - sizeof(struct memory_block));
|
||||
|
||||
// Mark the block as free
|
||||
mark_as_free(block);
|
||||
}
|
27
kernel/malloc.h
Normal file
27
kernel/malloc.h
Normal file
@ -0,0 +1,27 @@
|
||||
#ifndef MALLOC_H
|
||||
#define MALLOC_H
|
||||
|
||||
#include <stddef.h> // For size_t
|
||||
|
||||
// Define the memory block structure
|
||||
struct memory_block {
|
||||
size_t size;
|
||||
struct memory_block *next;
|
||||
int is_free;
|
||||
};
|
||||
|
||||
// Function prototypes
|
||||
void init_heap(void *start, void *end);
|
||||
void *malloc(size_t size);
|
||||
void free(void *ptr);
|
||||
|
||||
// Helper function prototypes
|
||||
void *find_free_block(size_t size);
|
||||
void mark_as_used(void *ptr, size_t size);
|
||||
void mark_as_free(void *ptr);
|
||||
|
||||
// External heap boundaries
|
||||
extern void *user_heap_start;
|
||||
extern void *user_heap_end;
|
||||
|
||||
#endif // MALLOC_H
|
@ -1,5 +1,19 @@
|
||||
#include "panic.h"
|
||||
#include "terminal.h"
|
||||
#include "serial.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
void panic(const char *message) {
|
||||
// Panic handling code
|
||||
terminal_write("KERNEL PANIC: ");
|
||||
terminal_write(message);
|
||||
terminal_write("\nSystem halted.\n");
|
||||
|
||||
serial_write("KERNEL PANIC: ");
|
||||
serial_write(message);
|
||||
serial_write("\nSystem halted.\n");
|
||||
|
||||
// Halt the system
|
||||
while (true) {
|
||||
asm volatile ("cli; hlt");
|
||||
}
|
||||
}
|
||||
|
6
kernel/print.c
Normal file
6
kernel/print.c
Normal file
@ -0,0 +1,6 @@
|
||||
#include <stdio.h>
|
||||
|
||||
void print_string(const char *str)
|
||||
{
|
||||
printf("%s", str);
|
||||
}
|
6
kernel/print.h
Normal file
6
kernel/print.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef PRINT_H
|
||||
#define PRINT_H
|
||||
|
||||
void print_string(const char *str);
|
||||
|
||||
#endif
|
@ -1,5 +1,62 @@
|
||||
#include "scheduler.h"
|
||||
#include <stddef.h>
|
||||
|
||||
static task_t tasks[MAX_TASKS];
|
||||
static uint32_t task_stacks[MAX_TASKS][STACK_SIZE / sizeof(uint32_t)];
|
||||
|
||||
static int task_count = 0;
|
||||
static task_t *task_list = NULL;
|
||||
static task_t *current_task = NULL;
|
||||
|
||||
void scheduler_init() {
|
||||
// Scheduler initialization code
|
||||
// Initialize task list, etc.
|
||||
task_list = NULL;
|
||||
current_task = NULL;
|
||||
task_count = 0;
|
||||
}
|
||||
|
||||
void scheduler_add_task(void (*entry)(void)) {
|
||||
if (task_count >= MAX_TASKS || entry == NULL) return;
|
||||
|
||||
task_t *new_task = &tasks[task_count];
|
||||
new_task->id = task_count;
|
||||
new_task->entry = entry;
|
||||
|
||||
// Simulate a stack pointer pointing to the "top" of the stack
|
||||
new_task->stack_ptr = &task_stacks[task_count][STACK_SIZE / sizeof(uint32_t) - 1];
|
||||
|
||||
new_task->next = NULL;
|
||||
|
||||
// Add to task list
|
||||
if (task_list == NULL) {
|
||||
task_list = new_task;
|
||||
} else {
|
||||
task_t *tail = task_list;
|
||||
while (tail->next) {
|
||||
tail = tail->next;
|
||||
}
|
||||
tail->next = new_task;
|
||||
}
|
||||
|
||||
task_count++;
|
||||
}
|
||||
|
||||
void scheduler_schedule() {
|
||||
// Very basic round-robin switch
|
||||
if (current_task && current_task->next) {
|
||||
current_task = current_task->next;
|
||||
} else {
|
||||
current_task = task_list; // Loop back
|
||||
}
|
||||
|
||||
// Call context switch or simulate yielding to current_task
|
||||
// In real system: context_switch_to(current_task)
|
||||
if (current_task && current_task->entry) {
|
||||
current_task->entry(); // Simulate switching by calling
|
||||
}
|
||||
}
|
||||
|
||||
void scheduler_yield() {
|
||||
// Stub: manually call schedule for cooperative multitasking
|
||||
scheduler_schedule();
|
||||
}
|
||||
|
@ -1,6 +1,21 @@
|
||||
#ifndef SCHEDULER_H
|
||||
#define SCHEDULER_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define MAX_TASKS 8
|
||||
#define STACK_SIZE 1024
|
||||
|
||||
typedef struct task {
|
||||
uint32_t id;
|
||||
void (*entry)(void);
|
||||
uint32_t *stack_ptr;
|
||||
struct task *next;
|
||||
} task_t;
|
||||
|
||||
void scheduler_init();
|
||||
void scheduler_add_task(void (*entry)(void));
|
||||
void scheduler_schedule();
|
||||
void scheduler_yield(); // Optional for cooperative scheduling
|
||||
|
||||
#endif // SCHEDULER_H
|
||||
|
60
kernel/shell.c
Normal file
60
kernel/shell.c
Normal file
@ -0,0 +1,60 @@
|
||||
#include "shell.h"
|
||||
#include "keyboard.h"
|
||||
#include "terminal.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
void execute(char *input) {
|
||||
if (strcmp(input, "help") == 0) {
|
||||
printf("Available commands: help, clear, exit\n");
|
||||
} else if (strcmp(input, "clear") == 0) {
|
||||
terminal_clear();
|
||||
} else {
|
||||
printf("Unknown command: %s\n", input);
|
||||
}
|
||||
}
|
||||
|
||||
void shell_loop()
|
||||
{
|
||||
char input[256];
|
||||
int index = 0;
|
||||
char c;
|
||||
|
||||
while (1)
|
||||
{
|
||||
printf("> ");
|
||||
index = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
c = keyboard_get_char(); // Waits for input
|
||||
|
||||
if (c == '\n' || c == '\r') // Enter key
|
||||
{
|
||||
input[index] = '\0';
|
||||
printf("\n");
|
||||
break;
|
||||
}
|
||||
else if (c == '\b' || c == 127) // Backspace
|
||||
{
|
||||
if (index > 0)
|
||||
{
|
||||
index--;
|
||||
printf("\b \b"); // Erase last char on screen
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (index < sizeof(input) - 1) {
|
||||
input[index++] = c;
|
||||
putchar(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (strcmp(input, "exit") == 0)
|
||||
break;
|
||||
|
||||
execute(input);
|
||||
}
|
||||
}
|
7
kernel/shell.h
Normal file
7
kernel/shell.h
Normal file
@ -0,0 +1,7 @@
|
||||
#ifndef SHELL_H
|
||||
#define SHELL_H
|
||||
|
||||
void shell_loop(void);
|
||||
void execute(char *input);
|
||||
|
||||
#endif
|
@ -1,5 +1,30 @@
|
||||
#include "syscalls.h"
|
||||
#include "scheduler.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
void syscall_handler() {
|
||||
// Syscall handling code
|
||||
void syscall_handler(int code, va_list args) {
|
||||
switch (code) {
|
||||
case SYSCALL_INIT:
|
||||
scheduler_init();
|
||||
break;
|
||||
case SYSCALL_SPAWN: {
|
||||
void (*entry)(void) = va_arg(args, void (*)(void));
|
||||
scheduler_add_task(entry);
|
||||
break;
|
||||
}
|
||||
case SYSCALL_YIELD:
|
||||
scheduler_yield();
|
||||
break;
|
||||
default:
|
||||
// Unknown syscall
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void syscall(int code, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, code);
|
||||
syscall_handler(code, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
@ -1,6 +1,17 @@
|
||||
#ifndef SYSCALLS_H
|
||||
#define SYSCALLS_H
|
||||
|
||||
// Syscall numbers
|
||||
typedef enum {
|
||||
SYSCALL_INIT = 0,
|
||||
SYSCALL_SPAWN,
|
||||
SYSCALL_YIELD
|
||||
} syscall_code_t;
|
||||
|
||||
// Syscall dispatcher
|
||||
void syscall_handler();
|
||||
|
||||
// Syscall interface
|
||||
void syscall(int code, ...);
|
||||
|
||||
#endif // SYSCALLS_H
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include <stdint.h>
|
||||
#include "io.h"
|
||||
#include "terminal.h"
|
||||
#include "vga.h"
|
||||
|
||||
#define VGA_ADDRESS 0xB8000
|
||||
#define VGA_WIDTH 80
|
||||
@ -12,10 +13,6 @@ static uint8_t cursor_x = 0;
|
||||
static uint8_t cursor_y = 0;
|
||||
static uint8_t current_color = WHITE_ON_BLACK;
|
||||
|
||||
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++) {
|
||||
|
@ -7,10 +7,13 @@ static uint32_t tick = 0;
|
||||
|
||||
void timer_callback(void) {
|
||||
tick++;
|
||||
// Optional: Print every 100 ticks
|
||||
// if (tick % 100 == 0) {
|
||||
// terminal_write("Tick\n");
|
||||
// }
|
||||
|
||||
// Print every 100 ticks for debugging purposes
|
||||
if (tick % 100 == 0) {
|
||||
char tick_msg[50];
|
||||
snprintf(tick_msg, sizeof(tick_msg), "Tick count: %u\n", tick);
|
||||
terminal_write(tick_msg);
|
||||
}
|
||||
}
|
||||
|
||||
void timer_init(uint32_t frequency) {
|
||||
|
@ -1,5 +1,89 @@
|
||||
#include "utils.h"
|
||||
|
||||
void util_function() {
|
||||
// Utility function code
|
||||
static void reverse(char* str, int len) {
|
||||
int start = 0;
|
||||
int end = len - 1;
|
||||
while (start < end) {
|
||||
char temp = str[start];
|
||||
str[start++] = str[end];
|
||||
str[end--] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
// Integer to ASCII for signed ints
|
||||
char* itoa(int value, char* str, int base) {
|
||||
int i = 0;
|
||||
int isNegative = 0;
|
||||
unsigned int uval;
|
||||
|
||||
if (base < 2 || base > 36) {
|
||||
str[0] = '\0';
|
||||
return str;
|
||||
}
|
||||
|
||||
// Handle zero explicitly
|
||||
if (value == 0) {
|
||||
str[i++] = '0';
|
||||
str[i] = '\0';
|
||||
return str;
|
||||
}
|
||||
|
||||
// Handle negative numbers (only for base 10)
|
||||
if (value < 0 && base == 10) {
|
||||
isNegative = 1;
|
||||
uval = (unsigned int)(-value);
|
||||
} else {
|
||||
uval = (unsigned int)value;
|
||||
}
|
||||
|
||||
while (uval != 0) {
|
||||
int rem = uval % base;
|
||||
str[i++] = (rem > 9) ? (rem - 10) + 'a' : rem + '0';
|
||||
uval /= base;
|
||||
}
|
||||
|
||||
if (isNegative) {
|
||||
str[i++] = '-';
|
||||
}
|
||||
|
||||
str[i] = '\0';
|
||||
reverse(str, i);
|
||||
return str;
|
||||
}
|
||||
|
||||
// Integer to ASCII for unsigned ints
|
||||
char* utoa(unsigned int value, char* str, int base) {
|
||||
int i = 0;
|
||||
|
||||
if (base < 2 || base > 36) {
|
||||
str[0] = '\0';
|
||||
return str;
|
||||
}
|
||||
|
||||
if (value == 0) {
|
||||
str[i++] = '0';
|
||||
str[i] = '\0';
|
||||
return str;
|
||||
}
|
||||
|
||||
while (value != 0) {
|
||||
int rem = value % base;
|
||||
str[i++] = (rem > 9) ? (rem - 10) + 'a' : rem + '0';
|
||||
value /= base;
|
||||
}
|
||||
|
||||
str[i] = '\0';
|
||||
reverse(str, i);
|
||||
return str;
|
||||
}
|
||||
|
||||
void print_hex(uint32_t val) {
|
||||
char hex_chars[] = "0123456789ABCDEF";
|
||||
char buf[11] = "0x00000000";
|
||||
for (int i = 9; i >= 2; i--) {
|
||||
buf[i] = hex_chars[val & 0xF];
|
||||
val >>= 4;
|
||||
}
|
||||
terminal_write(buf);
|
||||
serial_write(buf);
|
||||
}
|
@ -1,6 +1,14 @@
|
||||
#ifndef UTILS_H
|
||||
#define UTILS_H
|
||||
#include <stdint.h>
|
||||
|
||||
void util_function();
|
||||
|
||||
// Convert integer to string (base is typically 10, 16, etc.)
|
||||
char* itoa(int value, char* str, int base);
|
||||
|
||||
// Convert unsigned integer to string (base is typically 10, 16, etc.)
|
||||
char* utoa(unsigned int value, char* str, int base);
|
||||
|
||||
void print_hex(uint32_t val);
|
||||
|
||||
#endif // UTILS_H
|
||||
|
Loading…
x
Reference in New Issue
Block a user