This commit is contained in:
nub31
2025-09-05 21:41:00 +02:00
parent 8e986807df
commit 0f6b66a486
21 changed files with 210 additions and 245 deletions

View File

@@ -2,34 +2,18 @@
#include "std.h"
typedef struct
{
uint64_t base_address;
size_t length;
} memory_region_t;
typedef struct
{
memory_region_t* regions;
size_t num_regions;
} memory_map_t;
typedef void (*arch_panic_t)(const char*);
typedef void (*arch_putchar_t)(char c);
typedef uint64_t (*arch_page_size_t)();
typedef void (*arch_enable_interrupts_t)();
typedef void (*arch_disable_interrupts_t)();
typedef memory_map_t (*arch_get_memory_map_t)();
typedef void (*arch_halt_t)();
typedef struct
{
arch_panic_t panic;
arch_putchar_t putchar;
arch_page_size_t page_size;
arch_enable_interrupts_t enable_interrupts;
arch_disable_interrupts_t disable_interrupts;
arch_get_memory_map_t get_memory_map;
arch_halt_t halt;
} arch_api_t;

View File

@@ -5,15 +5,15 @@
typedef struct
{
uint8_t character;
uint8_t color;
u8 character;
u8 color;
} vga_char_t;
static vga_char_t* vga_buffer = (vga_char_t*)0xb8000;
static uint8_t cursor_row = 0;
static uint8_t cursor_col = 0;
static u8 cursor_row = 0;
static u8 cursor_col = 0;
void console_put_char(char c, uint8_t color)
void console_put_char(char c, u8 color)
{
switch (c)
{
@@ -30,7 +30,7 @@ void console_put_char(char c, uint8_t color)
}
case '\t':
{
uint8_t remainder = 4 - (cursor_col % 4);
u8 remainder = 4 - (cursor_col % 4);
cursor_col += remainder;
break;
}

View File

@@ -21,5 +21,5 @@
#define VGA_DEFAULT_COLOR VGA_LIGHT_GRAY | VGA_BLACK << 4
void console_put_char(char character, uint8_t color);
void console_put_char(char character, u8 color);
void console_clear();

View File

@@ -26,7 +26,7 @@ void remap_pic()
outb(PIC2_DATA, 0);
}
void register_irq_handler(uint8_t irq, irq_handler_t handler)
void register_irq_handler(u8 irq, irq_handler_t handler)
{
if (irq >= 16)
{
@@ -40,7 +40,7 @@ void register_irq_handler(uint8_t irq, irq_handler_t handler)
void handle_irq(const isr_frame_t* frame)
{
uint8_t irq = frame->int_no - 32;
u8 irq = frame->int_no - 32;
if (irq_handlers[irq])
{

View File

@@ -6,4 +6,4 @@ typedef void (*irq_handler_t)(const isr_frame_t*);
void remap_pic();
void handle_irq(const isr_frame_t* frame);
void register_irq_handler(uint8_t irq, irq_handler_t handler);
void register_irq_handler(u8 irq, irq_handler_t handler);

View File

@@ -4,9 +4,9 @@
typedef struct
{
uint64_t r15, r14, r13, r12, r11, r10, r9, r8;
uint64_t rbp, rdi, rsi, rdx, rcx, rbx, rax;
uint64_t int_no;
uint64_t err_code;
uint64_t rip, cs, rflags, rsp, ss;
u64 r15, r14, r13, r12, r11, r10, r9, r8;
u64 rbp, rdi, rsi, rdx, rcx, rbx, rax;
u64 int_no;
u64 err_code;
u64 rip, cs, rflags, rsp, ss;
} __attribute__((packed)) isr_frame_t;

View File

@@ -1,12 +1,13 @@
#include "arch.h"
#include "console/console.h"
#include "interrupts/idt.h"
#include "interrupts/irq.h"
#include "kernel.h"
#include "memory/mmap.h"
#include "mem.h"
#include "panic.h"
#include "util.h"
void x86_64_main(uint32_t magic, multiboot_info_t* info)
void x86_64_main(u32 magic, multiboot_info_t* info)
{
console_clear();
@@ -21,28 +22,20 @@ void x86_64_main(uint32_t magic, multiboot_info_t* info)
}
idt_init();
mem_init(info);
remap_pic();
map_memory(info);
enable_interrupts();
kernel_main();
}
void arch_console_putchar(char c)
void console_putchar(char c)
{
console_put_char(c, VGA_DEFAULT_COLOR);
}
uint64_t arch_page_size()
{
return 4096;
}
arch_api_t arch_api = {
.panic = panic,
.putchar = arch_console_putchar,
.page_size = arch_page_size,
.enable_interrupts = enable_interrupts,
.disable_interrupts = disable_interrupts,
.get_memory_map = get_memory_map,
.putchar = console_putchar,
.halt = halt,
};

134
src/arch/x86_64/mem.c Normal file
View File

@@ -0,0 +1,134 @@
#include "mem.h"
#include "x86_64/panic.h"
typedef struct
{
u64 base_address;
size_t length;
} memory_region_t;
typedef struct
{
memory_region_t* regions;
size_t num_regions;
} memory_map_t;
#define USABLE_REGION_SIZE 32
static memory_region_t usable_regions[USABLE_REGION_SIZE];
static size_t num_regions = 0;
#define BITMAP_SIZE 32768 // Supports up to 1GB of RAM
#define USABLE_REGION_SIZE 32
#define PAGE_SIZE 4096
static u8 page_bitmap[BITMAP_SIZE];
static u64 total_pages = 0;
static u64 free_pages = 0;
void mem_init(multiboot_info_t* info)
{
if (!(info->flags & (1 << 6)))
{
panic("Invalid memory map given by bootloader\n");
}
u64 offset = 0;
while (offset < info->mmap_length)
{
multiboot_memory_map_t* mmmt = (multiboot_memory_map_t*)(info->mmap_addr + offset);
if (mmmt->type == MULTIBOOT_MEMORY_AVAILABLE)
{
if (num_regions < USABLE_REGION_SIZE)
{
usable_regions[num_regions] = (memory_region_t){
.base_address = mmmt->addr,
.length = mmmt->len,
};
num_regions++;
}
else
{
printf("System has more memory than the memory map can hold\n");
break;
}
}
offset += mmmt->size + sizeof(mmmt->size);
}
memset(page_bitmap, 0xFF, BITMAP_SIZE);
for (size_t i = 0; i < num_regions; i++)
{
memory_region_t region = usable_regions[i];
u64 start_page = region.base_address / PAGE_SIZE;
u64 num_pages = region.length / PAGE_SIZE;
for (u64 page = start_page; page < start_page + num_pages; page++)
{
if (page < BITMAP_SIZE * 8)
{
page_bitmap[page / 8] &= ~(1 << (page % 8));
free_pages++;
total_pages++;
}
else
{
printf("System has more ram than the bitmap allows!\n");
break;
}
}
}
// Reserve first 64MB which is reserved by boot code
// todo(nub31): Later we should only identity map only the kernel pages or make a higher half kernel
for (u64 page = 0; page < (64 * 1024 * 1024) / PAGE_SIZE; page++)
{
if (page < BITMAP_SIZE * 8)
{
if (!(page_bitmap[page / 8] & (1 << (page % 8))))
{
page_bitmap[page / 8] |= (1 << (page % 8));
free_pages--;
}
}
}
}
u64 mem_alloc_physical_page()
{
for (size_t i = 0; i < BITMAP_SIZE; i++)
{
if (page_bitmap[i] != 0xFF)
{
for (int bit = 0; bit < 8; bit++)
{
if (!(page_bitmap[i] & (1 << bit)))
{
page_bitmap[i] |= (1 << bit);
free_pages--;
return ((i * 8 + bit) * PAGE_SIZE);
}
}
}
}
return 0;
}
void mem_free_physical_page(u64 address)
{
u64 page = address / PAGE_SIZE;
if (page < BITMAP_SIZE * 8)
{
if (page_bitmap[page / 8] & (1 << (page % 8)))
{
page_bitmap[page / 8] &= ~(1 << (page % 8));
free_pages++;
}
}
}

9
src/arch/x86_64/mem.h Normal file
View File

@@ -0,0 +1,9 @@
#pragma once
#include "std.h"
#include "x86_64/multiboot.h"
void mem_init(multiboot_info_t* info);
u64 mem_alloc_physical_page();
void mem_free_physical_page(u64 address);

View File

@@ -1,49 +0,0 @@
#include "mmap.h"
#include "../panic.h"
#define USABLE_REGION_SIZE 32
static memory_region_t usable_regions[USABLE_REGION_SIZE];
static size_t num_regions = 0;
void map_memory(multiboot_info_t* info)
{
if (!(info->flags & (1 << 6)))
{
panic("Invalid memory map given by bootloader\n");
}
uint64_t offset = 0;
while (offset < info->mmap_length)
{
multiboot_memory_map_t* mmmt = (multiboot_memory_map_t*)(info->mmap_addr + offset);
if (mmmt->type == MULTIBOOT_MEMORY_AVAILABLE)
{
if (num_regions < USABLE_REGION_SIZE)
{
usable_regions[num_regions] = (memory_region_t){
.base_address = mmmt->addr,
.length = mmmt->len,
};
num_regions++;
}
else
{
printf("System has more memory than the memory map can hold\n");
break;
}
}
offset += mmmt->size + sizeof(mmmt->size);
}
}
memory_map_t get_memory_map()
{
return (memory_map_t){
.num_regions = num_regions,
.regions = usable_regions,
};
}

View File

@@ -1,7 +0,0 @@
#pragma once
#include "../multiboot.h"
#include "arch.h"
void map_memory(multiboot_info_t* mbd);
memory_map_t get_memory_map();

View File

@@ -68,14 +68,14 @@ enum
CPUID_FEAT_EDX_PBE = 1 << 31
};
static inline void outb(uint16_t port, uint8_t val)
static inline void outb(u16 port, u8 val)
{
__asm__ volatile("outb %0, %1" : : "a"(val), "Nd"(port));
}
static inline uint8_t inb(uint16_t port)
static inline u8 inb(u16 port)
{
uint8_t ret;
u8 ret;
__asm__ volatile("inb %1, %0" : "=a"(ret) : "Nd"(port));
return ret;
}
@@ -85,22 +85,22 @@ static inline void io_wait()
outb(0x80, 0);
}
static inline void cpuid(uint32_t code, uint32_t* a, uint32_t* d)
static inline void cpuid(u32 code, u32* a, u32* d)
{
__asm__ volatile("cpuid" : "=a"(*a), "=d"(*d) : "a"(code) : "ecx", "ebx");
}
static inline uint64_t rdmsr(uint32_t msr)
static inline u64 rdmsr(u32 msr)
{
uint32_t lo, hi;
u32 lo, hi;
__asm__ volatile("rdmsr" : "=a"(lo), "=d"(hi) : "c"(msr));
return ((uint64_t)hi << 32) | lo;
return ((u64)hi << 32) | lo;
}
static inline void wrmsr(uint32_t msr, uint64_t value)
static inline void wrmsr(u32 msr, u64 value)
{
uint32_t lo = (uint32_t)value;
uint32_t hi = (uint32_t)(value >> 32);
u32 lo = (u32)value;
u32 hi = (u32)(value >> 32);
__asm__ volatile("wrmsr" : : "c"(msr), "a"(lo), "d"(hi));
}

View File

@@ -1,11 +1,7 @@
#include "kernel.h"
#include "pmm.h"
#include "std.h"
void kernel_main()
{
pmm_init();
uint64_t page = pmm_alloc_page();
printf("page: %u\n", page);
printf("Welcome to nub OS :)\n");
}

View File

@@ -1,88 +0,0 @@
#include "pmm.h"
#include "arch.h"
#define BITMAP_SIZE 32768 // Supports up to 1GB of RAM
#define USABLE_REGION_SIZE 32
static uint8_t page_bitmap[BITMAP_SIZE];
static uint64_t total_pages = 0;
static uint64_t free_pages = 0;
void pmm_init()
{
memory_map_t memory_map = arch_api.get_memory_map();
memset(page_bitmap, 0xFF, BITMAP_SIZE);
for (size_t i = 0; i < memory_map.num_regions; i++)
{
memory_region_t region = memory_map.regions[i];
uint64_t start_page = region.base_address / arch_api.page_size();
uint64_t num_pages = region.length / arch_api.page_size();
for (uint64_t page = start_page; page < start_page + num_pages; page++)
{
if (page < BITMAP_SIZE * 8)
{
page_bitmap[page / 8] &= ~(1 << (page % 8));
free_pages++;
total_pages++;
}
else
{
printf("System has more ram than the bitmap allows!\n");
break;
}
}
}
// Reserve first 64MB which is reserved by boot code
for (uint64_t page = 0; page < (64 * 1024 * 1024) / arch_api.page_size(); page++)
{
if (page < BITMAP_SIZE * 8)
{
if (!(page_bitmap[page / 8] & (1 << (page % 8))))
{
page_bitmap[page / 8] |= (1 << (page % 8));
free_pages--;
}
}
}
}
// Returns the address of first free physical page
uint64_t pmm_alloc_page()
{
for (size_t i = 0; i < BITMAP_SIZE; i++)
{
if (page_bitmap[i] != 0xFF)
{
for (int bit = 0; bit < 8; bit++)
{
if (!(page_bitmap[i] & (1 << bit)))
{
page_bitmap[i] |= (1 << bit);
free_pages--;
return ((i * 8 + bit) * arch_api.page_size());
}
}
}
}
return 0;
}
// Frees the physical page at the specified address
void pmm_free_page(uint64_t addr)
{
uint64_t page = addr / arch_api.page_size();
if (page < BITMAP_SIZE * 8)
{
if (page_bitmap[page / 8] & (1 << (page % 8)))
{
page_bitmap[page / 8] &= ~(1 << (page % 8));
free_pages++;
}
}
}

View File

@@ -1,7 +0,0 @@
#pragma once
#include "std.h"
void pmm_init();
uint64_t pmm_alloc_page();
void pmm_free_page(uint64_t addr);

View File

@@ -18,29 +18,18 @@ typedef __builtin_va_list va_list;
#endif
typedef unsigned long size_t;
typedef long ptrdiff_t;
typedef long intptr_t;
typedef unsigned long uintptr_t;
#define offsetof(type, member) __builtin_offsetof(type, member)
typedef signed char int8_t;
typedef unsigned char uint8_t;
typedef signed short int16_t;
typedef unsigned short uint16_t;
typedef signed int int32_t;
typedef unsigned int uint32_t;
typedef signed long long int64_t;
typedef unsigned long long uint64_t;
typedef uint8_t u8;
typedef int8_t i8;
typedef uint16_t u16;
typedef int16_t i16;
typedef uint32_t u32;
typedef int32_t i32;
typedef uint64_t u64;
typedef int64_t i64;
typedef unsigned char u8;
typedef signed char i8;
typedef unsigned short u16;
typedef signed short i16;
typedef unsigned int u32;
typedef signed int i32;
typedef unsigned long long u64;
typedef signed long long i64;
#define INT8_MIN (-128)
#define INT8_MAX 127

View File

@@ -27,12 +27,12 @@ void printf(const char* fmt, ...)
}
else if (fmt[i] == 'c')
{
char character = (char)va_arg(args, int64_t);
char character = (char)va_arg(args, u64);
arch_api.putchar(character);
}
else if (fmt[i] == 'd')
{
int64_t val = va_arg(args, int64_t);
u64 val = va_arg(args, u64);
char buf[21];
itoa64(val, buf);
for (size_t j = 0; buf[j] != '\0'; j++)
@@ -42,7 +42,7 @@ void printf(const char* fmt, ...)
}
else if (fmt[i] == 'u')
{
uint64_t val = va_arg(args, uint64_t);
u64 val = va_arg(args, u64);
char buf[21];
uitoa64(val, buf);
for (size_t j = 0; buf[j] != '\0'; j++)
@@ -52,7 +52,7 @@ void printf(const char* fmt, ...)
}
else if (fmt[i] == 'x')
{
uint64_t val = va_arg(args, uint64_t);
u64 val = va_arg(args, u64);
char buf[17];
uitoa64_hex(val, buf);
for (size_t j = 0; buf[j] != '\0'; j++)

View File

@@ -1,9 +1,17 @@
#include "mem.h"
void memset(void* destination, uint8_t value, size_t length)
void memset(void* destination, u8 value, size_t length)
{
for (size_t i = 0; i < length; i++)
{
((uint8_t*)destination)[i] = value;
((u8*)destination)[i] = value;
}
}
void memcpy(void* destination, void* source, size_t length)
{
for (size_t i = 0; i < length; i++)
{
((u8*)destination)[i] = ((u8*)source)[i];
}
}

View File

@@ -2,4 +2,5 @@
#include "std.h"
void memset(void* destination, uint8_t value, size_t length);
void memset(void* destination, u8 value, size_t length);
void memcpy(void* destination, void* source, size_t length);

View File

@@ -1,6 +1,6 @@
#include "string.h"
int kstrcmp(const char* a, const char* b)
int strcmp(const char* a, const char* b)
{
while ((*a != '\0' && *b != '\0') && *a == *b)
{
@@ -25,7 +25,7 @@ void reverse(char* str, size_t length)
}
}
void itoa64(int64_t value, char* buffer)
void itoa64(i64 value, char* buffer)
{
char temp[21];
int i = 0, j = 0;
@@ -75,7 +75,7 @@ void itoa64(int64_t value, char* buffer)
buffer[j] = '\0';
}
void uitoa64(uint64_t value, char* buffer)
void uitoa64(u64 value, char* buffer)
{
char temp[21];
int i = 0, j = 0;
@@ -100,7 +100,7 @@ void uitoa64(uint64_t value, char* buffer)
buffer[j] = '\0';
}
void uitoa64_hex(uint64_t value, char* buffer)
void uitoa64_hex(u64 value, char* buffer)
{
const char* digits = "0123456789abcdef";
char temp[17];

View File

@@ -3,6 +3,8 @@
#include "std.h"
int strcmp(const char* a, const char* b);
void uitoa64(uint64_t value, char* buffer);
void itoa64(int64_t value, char* buffer);
void uitoa64_hex(uint64_t value, char* buffer);
void reverse(char* str, size_t length);
void uitoa64(u64 value, char* buffer);
void itoa64(i64 value, char* buffer);
void uitoa64_hex(u64 value, char* buffer);