Some unfinished changes + TODO chnages

This commit is contained in:
2025-03-18 20:40:29 +01:00
parent 244b83d370
commit 883cd5c1d4
11 changed files with 333 additions and 205 deletions
+44
View File
@@ -0,0 +1,44 @@
#ifndef _BOOTLOADER_H
#define _BOOTLOADER_H
#include <kernel.h>
// Boot protocols
#define BOOT_UNKNOWN 0 // Unknown
#define BOOT_MB1 1 // MultiBoot 1
#define BOOT_MB2 2 // MultiBoot 2
#define BOOT_LIMINE 3 // Limine
struct boot_memmapEntry {
uint64_t base;
uint64_t size;
uint32_t type;
uint32_t attr;
};
/*
* Some values may not be provided by the bootloader, in this case
* pointers will be NULL and integer values will be 0 if applicable.
* Some unprovided values may also be implied. Eg.:
* If 'memmap = NULL' then 'memmapLen' doesn't matter.
*/
struct boot_info {
uint32_t memLower;
uint32_t memUpper;
struct boot_memmapEntry* memmap;
size_t memmapLen;
};
/*
* This functions arguments depend on the boot protocol provided.
* This is the reason for the varargs thing. It runs on of the functions
* defined after it.
*/
int boot_init(int type, ...);
int boot_init_mb1(void* ptr, uint32_t magic);
// TODO:
// int boot_init_mb2(...);
// int boot_init_limine(...);
#endif
+7 -9
View File
@@ -76,17 +76,15 @@ extern uint32_t __kernel_start, __kernel_end;
/*
* Logging and errors
*/
// TODO: Logging with printk()
// TODO: Log levels & pr_*() wrappers for printk()
#define BUG() (panic("BUG()"))
// TODO
#define printk(_s) NULL
#define pr_dbg(_s) NULL
#define pr_wrn(_s) NULL
#define pr_err(_s) NULL
#define panic(_s) NULL
#define BUG() NULL
#define WARN() NULL
#define BUG_ON(_e) ((_e) ? BUG() : NULL)
#define WARN_ON(_e) ((_e) ? WARN() : NULL)
#include <serial.h>
__noreturn static inline void panic(char* s) {
serial_puts(COM1, s);
__asm__ volatile("cli");
while (1) __asm__ volatile ("hlt");
}
#endif
+1 -1
View File
@@ -68,7 +68,7 @@
/* is there a symbol table loaded? */
#define MULTIBOOT_INFO_AOUT_SYMS 0x00000010
/* is there an ELF section header table? */
#define MULTIBOOT_INFO_ELF_SHDR 0X00000020
#define MULTIBOOT_INFO_ELF_SHDR 0x00000020
/* is there a full memory map? */
#define MULTIBOOT_INFO_MEM_MAP 0x00000040
+10 -1
View File
@@ -1,6 +1,15 @@
#ifndef _PMM_H
#define _PMM_H
int pmm_init();
#include <multiboot.h>
#define PMM_BS 4096 // Block Size
#define PMM_BPB 8 // Blocks per byte
int pmm_init(void);
void pmm_initRegion(size_t base, size_t len);
void pmm_deinitRegion(size_t base, size_t len);
void* pmm_alloc(size_t blockCount);
void pmm_free(void* ptr, size_t blockCount);
#endif
+6
View File
@@ -8,6 +8,9 @@
#define COM3 0x3e8
#define COM4 0x2e8
// Buffer for (v)debugf()
#define DF_BUF_LEN 2048
int serial_init(int dev);
int serial_txem(int dev);
void serial_send(int dev, char data);
@@ -16,4 +19,7 @@ char serial_recv(int dev);
void serial_write(int dev, char* buf, size_t len);
void serial_puts(int dev, char* s);
int debugf(char* fmt, ...);
int vdebugf(char* fmt, va_list args);
#endif
+19 -9
View File
@@ -1,31 +1,41 @@
OUTPUT_FORMAT("elf32-i386")
OUTPUT_ARCH("i386");
ENTRY(_start)
/* Define correct program headers */
PHDRS {
text PT_LOAD FLAGS((1 << 0) | (1 << 2)); /* Read, Execute */
rodata PT_LOAD FLAGS((1 << 0)); /* Read */
data PT_LOAD FLAGS((1 << 0) | (1 << 1)); /* Read, Write */
}
/* Define sections */
SECTIONS {
/* 1MB is a conventional place for kernels */
. = 1M;
/* We need the multiboot header in the first 8192 bytes */
__kernel_start = .;
.text BLOCK(4K) : ALIGN(4K) {
*(.multiboot)
*(.text)
}
} : text
/* Read-only data */
.rodata BLOCK(4K) : ALIGN(4K) {
*(.rodata)
}
} : rodata
/* Initalized r/w data */
.data BLOCK(4K) : ALIGN(4K) {
*(.data)
}
} : data
/* Uninitialized r/w data and stack */
.bss BLOCK(4K) : ALIGN(4K) {
*(COMMON)
*(.bss)
}
} : data
__kernel_end = .;
. = 4M;
/DISCARD/ : {
*(.eh_frame)
*(.note*)
}
}
+47
View File
@@ -0,0 +1,47 @@
#include <bootloader.h>
#include <multiboot.h>
#include <kernel.h>
struct boot_info bootloader = { 0 };
int boot_init(int type, ...) {
va_list args;
va_start(args, type);
switch (type) {
case BOOT_UNKNOWN: return 1;
case BOOT_MB1: return boot_init_mb1(va_arg(args, void*), va_arg(args, uint32_t));
case BOOT_MB2: return 1;
case BOOT_LIMINE: return 1;
}
// We got an invalid boot protocol
return 1;
}
int boot_init_mb1(void* ptr, uint32_t magic) {
multiboot_info_t* mbi = ptr;
if (magic != 0xBADB002) return 1;
// Memory info
if (mbi->flags & MULTIBOOT_INFO_MEMORY) {
bootloader.memLower = mbi->mem_lower;
bootloader.memUpper = mbi->mem_upper;
}
// Memory map
if (mbi->flags & MULTIBOOT_INFO_MEM_MAP) {
uint32_t memmap = mbi->mmap_addr;
uint32_t offset = 0;
while (offset < mbi->mmap_length) {
multiboot_memory_map_t* entry = (multiboot_memory_map_t*)(memmap + offset);
offset += entry->size;
}
}
return 0;
}
+6 -7
View File
@@ -1,19 +1,17 @@
#include <bootloader.h>
#include <kernel.h>
#include <serial.h>
#include <pmm.h>
#include <tty.h>
#define _hlt() while (1) __asm__ volatile ("cli; hlt");
/* TODO: Commented out stuff */
__noreturn
void kmain(void* ptr, uint32_t magic) {
// Init with MultiBoot 1, this populates the global bootloader struct
//if (boot_init(BOOT_MB1, ptr, magic) != 0) panic("Unsupporred bootloader.");
if (boot_init(BOOT_MB1, ptr, magic) != 0) panic("Unsupporred bootloader.");
// Serial console for debugging
serial_init(COM1);
serial_puts(COM1, "\x1b[0H\x1b[Jkern.\n");
debugf("\x1b[H\x1b[J\x1b[0mkern. \x1b[35m(serial console)\x1b[0m\n\n");
// VGA tty thingy
tty_init();
@@ -29,8 +27,9 @@ void kmain(void* ptr, uint32_t magic) {
debugf("Basic initialization complete!\n");
/* TODO: Commented out stuff */
panic("kmain() reached end.");
// Temporary loop since panic() does not halt
while (1);
}
+91 -1
View File
@@ -1,4 +1,94 @@
#include <multiboot.h>
#include <kernel.h>
#include <pmm.h>
int pmm_init() { return 0; }
// Helpers
#define SET_BLOCK(_b) memmap[(_b) / 32] |= (1 << ((_b) % 32))
#define USET_BLOCK(_b) memmap[(_b) / 32] &= ~(1 << ((_b) % 32))
#define TEST_BLOCK(_b) ((memmap[(_b) % 32] & (1 << ((_b) % 32))) ? 1 : 0)
// Memory manager bitmap
uint32_t* memmap = NULL;
size_t usedBlocks = 0;
size_t maxBlocks = 0;
// TODO: improve these hardcoded values
int pmm_init(void) {
memmap = NULL; // Memory map location
usedBlocks = 0;
maxBlocks = 0; // TODO
return 0;
}
int findFreeBlocks(size_t blockCount) {
if (blockCount == 0) return -1;
uint32_t max = maxBlocks / 32;
uint32_t freeCount = 0;
for (size_t i = 0; i < max; i++) {
// We don't have to check, cause it's all reserved
if (memmap[i] == 0xffffffff) continue;
for (uint8_t j = 0; j < 32; j++) {
if (TEST_BLOCK(i * PMM_BPB + j)) freeCount++;
else freeCount = 0;
if (freeCount >= blockCount) return i * PMM_BPB + j;
}
}
// We didn't find enough free memory :(
return -1;
}
void pmm_initRegion(size_t base, size_t len) {
uint32_t align = base / PMM_BS;
uint32_t blockCount = len / PMM_BS;
while (blockCount-- > 0) {
USET_BLOCK(align);
align++;
usedBlocks--;
}
SET_BLOCK(0);
}
void pmm_deinitRegion(size_t base, size_t len) {
uint32_t align = base / PMM_BS;
uint32_t blockCount = len / PMM_BS;
while (blockCount-- > 0) {
align++;
SET_BLOCK(align); // We can't increment here, because macros -_(._.)_-
usedBlocks++;
}
SET_BLOCK(0);
}
void* pmm_alloc(size_t blockCount) {
if ((maxBlocks - usedBlocks) < blockCount) return NULL;
int startBlock = findFreeBlocks(blockCount);
if (startBlock == -1) return NULL;
for (size_t i = 0; i < blockCount; i++) {
SET_BLOCK(startBlock + i);
usedBlocks++;
}
return (void*)(startBlock * PMM_BS);
}
void pmm_free(void* ptr, size_t blockCount) {
size_t startBlock = (size_t)ptr / PMM_BS;
for (size_t i = 0; i < blockCount; i++) {
USET_BLOCK(startBlock + i);
usedBlocks--;
}
SET_BLOCK(0); // Make sure block 0 is always set
}