2026-06-24 16:47:22 -05:00
|
|
|
#include "lib/memory.h"
|
|
|
|
|
#include "memory/mm.h"
|
|
|
|
|
|
2026-06-25 14:03:35 -05:00
|
|
|
#define KHEAP_START 0xE0000000
|
|
|
|
|
|
|
|
|
|
typedef struct __attribute__((packed)) {
|
2026-06-26 20:05:01 -05:00
|
|
|
size_t size;
|
2026-06-25 14:03:35 -05:00
|
|
|
uint8_t free;
|
2026-06-26 20:05:01 -05:00
|
|
|
void* next_blk;
|
2026-06-25 14:03:35 -05:00
|
|
|
} alloc_header_t;
|
2026-06-24 13:30:23 -05:00
|
|
|
|
|
|
|
|
void memcpy(const void* src, void* dst, size_t sz) {
|
|
|
|
|
for (size_t i = 0; i < sz; i++) {
|
|
|
|
|
((uint8_t*)dst)[i] = ((uint8_t*)src)[i];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-24 16:47:22 -05:00
|
|
|
void memset(const uint8_t* dst, uint8_t val, size_t sz) {
|
|
|
|
|
for (size_t i = 0; i < sz; i++) {
|
|
|
|
|
((uint8_t*)dst)[i] = val;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-24 13:30:23 -05:00
|
|
|
int strcmp(const char* s1, const char* s2) {
|
|
|
|
|
while (*s1 && (*s1 == *s2)) {
|
|
|
|
|
s1++;
|
|
|
|
|
s2++;
|
|
|
|
|
}
|
|
|
|
|
return *(const uint8_t*)s1 - *(const uint8_t*)s2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int strlen(const char* str) {
|
|
|
|
|
int len = 0;
|
|
|
|
|
while(*str != 0) {
|
|
|
|
|
str++;
|
|
|
|
|
len++;
|
|
|
|
|
}
|
|
|
|
|
return len;
|
2026-06-24 16:47:22 -05:00
|
|
|
}
|
|
|
|
|
|
2026-06-29 17:00:07 -05:00
|
|
|
int strncmp(const char *s1, const char *s2, size_t n) {
|
|
|
|
|
// If n is 0, we don't compare anything and strings are "equal"
|
|
|
|
|
while (n > 0) {
|
|
|
|
|
// If characters don't match, or we hit the null-terminator of s1
|
|
|
|
|
if (*s1 != *s2) {
|
|
|
|
|
return *(unsigned char *)s1 - *(unsigned char *)s2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If we reached the end of the strings simultaneously
|
|
|
|
|
if (*s1 == '\0') {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s1++;
|
|
|
|
|
s2++;
|
|
|
|
|
n--;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-30 00:03:21 -05:00
|
|
|
char* strcpy(char* dest, const char* src) {
|
|
|
|
|
char* saved_dest = dest;
|
|
|
|
|
|
|
|
|
|
while ((*dest++ = *src++) != '\0') {}
|
|
|
|
|
|
|
|
|
|
return saved_dest;
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-25 14:03:35 -05:00
|
|
|
static void* kernel_heap_start = (void*)KHEAP_START;
|
|
|
|
|
static void* kernel_heap_end = (void*)KHEAP_START;
|
|
|
|
|
alloc_header_t* blk_list = NULL;
|
2026-06-24 16:47:22 -05:00
|
|
|
|
2026-06-25 14:03:35 -05:00
|
|
|
void kgrow(size_t pages) {
|
|
|
|
|
for (size_t p = 0; p < pages; p++) {
|
|
|
|
|
void* frame = p_alloc_frame();
|
|
|
|
|
map_page((uint32_t)kernel_heap_end, (uint32_t)frame, PAGE_PRESENT | PAGE_WRITABLE);
|
|
|
|
|
kernel_heap_end = (void*)((uint32_t)kernel_heap_end + PAGE_SIZE);
|
2026-06-24 16:47:22 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-26 20:05:01 -05:00
|
|
|
#define ALIGNMENT 4
|
|
|
|
|
#define ALIGN(size) (((size) + (ALIGNMENT - 1)) & ~(ALIGNMENT - 1))
|
2026-06-25 14:03:35 -05:00
|
|
|
void* kalloc(size_t sz) {
|
2026-06-26 20:05:01 -05:00
|
|
|
sz = ALIGN(sz);
|
2026-06-25 14:03:35 -05:00
|
|
|
|
2026-06-26 20:05:01 -05:00
|
|
|
if (kernel_heap_end == kernel_heap_start) {
|
|
|
|
|
// probaably not great, but if we don't have a heap yet, allocate the first (or only) frame requested.
|
|
|
|
|
// Then initialize the first block header for the allocator
|
|
|
|
|
kgrow(4);
|
|
|
|
|
|
|
|
|
|
blk_list = (alloc_header_t*)kernel_heap_start;
|
|
|
|
|
blk_list->size = ((uint32_t)kernel_heap_end - (uint32_t)kernel_heap_start) - sizeof(alloc_header_t);
|
|
|
|
|
blk_list->free = 1;
|
|
|
|
|
blk_list->next_blk = NULL;
|
2026-06-25 14:03:35 -05:00
|
|
|
}
|
|
|
|
|
|
2026-06-26 20:05:01 -05:00
|
|
|
alloc_header_t* curr = blk_list;
|
|
|
|
|
alloc_header_t* prev = NULL;
|
2026-06-25 14:03:35 -05:00
|
|
|
|
2026-06-26 20:05:01 -05:00
|
|
|
while (curr != NULL) {
|
|
|
|
|
if (curr->free && curr->size >= sz) {
|
|
|
|
|
if (curr->size >= sz + sizeof(alloc_header_t) + ALIGNMENT) {
|
|
|
|
|
alloc_header_t* new_blk = (alloc_header_t*)((uint32_t)curr + sizeof(alloc_header_t) + sz);
|
|
|
|
|
|
|
|
|
|
new_blk->size = curr->size - sz - sizeof(alloc_header_t);
|
|
|
|
|
new_blk->free = 1;
|
|
|
|
|
new_blk->next_blk = curr->next_blk;
|
|
|
|
|
|
|
|
|
|
curr->size = sz;
|
|
|
|
|
curr->next_blk = new_blk;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
curr->free = 0;
|
|
|
|
|
return (void*)((uint32_t)curr + sizeof(alloc_header_t));
|
|
|
|
|
}
|
|
|
|
|
prev = curr;
|
|
|
|
|
curr = curr->next_blk;
|
|
|
|
|
}
|
2026-06-24 16:47:22 -05:00
|
|
|
|
2026-06-26 20:05:01 -05:00
|
|
|
// no more space, grow!!
|
|
|
|
|
size_t required_space = sz + sizeof(alloc_header_t);
|
|
|
|
|
size_t pages_to_grow = (required_space + PAGE_SIZE - 1) / PAGE_SIZE;
|
|
|
|
|
|
|
|
|
|
alloc_header_t* new_heap_blk = (alloc_header_t*)kernel_heap_end;
|
|
|
|
|
|
|
|
|
|
kgrow(pages_to_grow);
|
|
|
|
|
|
|
|
|
|
new_heap_blk->size = (pages_to_grow * PAGE_SIZE) - sizeof(alloc_header_t);
|
|
|
|
|
new_heap_blk->free = 1;
|
|
|
|
|
new_heap_blk->next_blk = NULL;
|
|
|
|
|
|
|
|
|
|
if (prev != NULL) {
|
|
|
|
|
prev->next_blk = new_heap_blk;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return kalloc(sz);
|
2026-07-01 20:00:22 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void kfree(void* ptr) {
|
|
|
|
|
|
2026-06-24 13:30:23 -05:00
|
|
|
}
|