209 lines
5.6 KiB
C
209 lines
5.6 KiB
C
//
|
|
// Created by rick on 22-04-20.
|
|
//
|
|
|
|
#include <types.h>
|
|
#include <kprint.h>
|
|
#include <mem/mem.h>
|
|
#include <libc/libc.h>
|
|
|
|
#define MEMMAP_ENTRIES 16
|
|
|
|
#define MMAP_TYPE_UNDEFINED 0
|
|
#define MMAP_TYPE_AVAILABLE 1
|
|
#define MMAP_TYPE_RESERVED 2
|
|
#define MMAP_TYPE_ACPI_RECLAIMABLE 3
|
|
#define MMAP_TYPE_NVS 4
|
|
#define MMAP_TYPE_BADRAM 5
|
|
#define MMAP_TYPE_KERNEL 6
|
|
#define MMAP_TYPE_MALLOC 7
|
|
|
|
#define MALLOC_TYPE_FREE 0
|
|
#define MALLOC_TYPE_USED 1
|
|
|
|
#define kilobyte (1024)
|
|
//#define kernel_start (one_meg)
|
|
#define kernel_size (32 * kilobyte)
|
|
#define kernel_end (kernel_start + kernel_size)
|
|
extern void *kernel_start;
|
|
//extern void *kernel_end;
|
|
|
|
char *msg_index = "Idx: ";
|
|
char *msg_addr = "Address: ";
|
|
char *msg_len = "Length: ";
|
|
char *msg_type = "Type: ";
|
|
char *msg_nl = "\n";
|
|
char *msg_malloc_num_entries_avail = "Malloc avail entries: ";
|
|
char *msg_malloc_num_entries_used = "Malloc used entries: ";
|
|
|
|
typedef struct {
|
|
void *address;
|
|
u32 length;
|
|
u32 type;
|
|
} __attribute((packed)) mmap_entry;
|
|
|
|
char *msg_lu = "0123456789ABCDEF";
|
|
|
|
int malloc_entries = 0;
|
|
int malloc_used = 0;
|
|
|
|
int last_memmap_entry = 0;
|
|
mmap_entry memmap[MEMMAP_ENTRIES] = {
|
|
{0, 0, 0},
|
|
{0, 0, 0},
|
|
{0, 0, 0},
|
|
{0, 0, 0},
|
|
{0, 0, 0},
|
|
{0, 0, 0},
|
|
{0, 0, 0},
|
|
{0, 0, 0},
|
|
{0, 0, 0},
|
|
{0, 0, 0},
|
|
{0, 0, 0},
|
|
{0, 0, 0},
|
|
{0, 0, 0},
|
|
{0, 0, 0},
|
|
{0, 0, 0},
|
|
{0, 0, 0},
|
|
};
|
|
|
|
typedef struct malloc_map {
|
|
struct malloc_map *next;
|
|
struct malloc_map *pref;
|
|
u32 size;
|
|
int type;
|
|
} malloc_map;
|
|
|
|
void use_mmap_entry(struct multiboot_mmap_entry *entry) {
|
|
mmap_entry *mm_entry = &memmap[last_memmap_entry++];
|
|
mm_entry->address = (void *) entry->addr;
|
|
mm_entry->length = entry->len;
|
|
mm_entry->type = entry->type;
|
|
if (last_memmap_entry == 1) {
|
|
// not using first map entry for now
|
|
return;
|
|
}
|
|
// check if the entry overlaps with the kernel address space
|
|
if (kernel_start >= mm_entry->address && kernel_start <= mm_entry->address + mm_entry->length) {
|
|
// todo make this something proper
|
|
struct multiboot_mmap_entry extra_entry;
|
|
extra_entry.size = entry->size;
|
|
extra_entry.type = entry->type;
|
|
extra_entry.addr = entry->addr + kernel_size;
|
|
extra_entry.len = entry->size - kernel_size;
|
|
use_mmap_entry(&extra_entry);
|
|
|
|
mm_entry->length = kernel_size;
|
|
mm_entry->type = MMAP_TYPE_KERNEL;
|
|
}
|
|
if (mm_entry->type == MMAP_TYPE_AVAILABLE && (unsigned int) mm_entry->length > sizeof(malloc_map)) {
|
|
mm_entry->type = MMAP_TYPE_MALLOC;
|
|
malloc_map *map = (malloc_map *) mm_entry->address;
|
|
map->type = MALLOC_TYPE_FREE;
|
|
map->size = mm_entry->length - sizeof(malloc_map);
|
|
map->pref = map;
|
|
map->next = map;
|
|
malloc_entries++;
|
|
}
|
|
}
|
|
|
|
void init_mmap(struct multiboot_mmap_entry *entries, u32 count) {
|
|
for (u32 i = 0; i < count; ++i) {
|
|
use_mmap_entry(&entries[i]);
|
|
}
|
|
}
|
|
|
|
void split_malloc_map(malloc_map *entry, unsigned int size) {
|
|
malloc_entries++;
|
|
malloc_map *new_entry = entry + sizeof(malloc_map) + size;
|
|
new_entry->size = entry->size - size - sizeof(malloc_map);
|
|
new_entry->next = entry->next;
|
|
new_entry->pref = entry;
|
|
new_entry->type = MALLOC_TYPE_FREE;
|
|
entry->next->pref = new_entry;
|
|
entry->next = new_entry;
|
|
entry->size = size;
|
|
}
|
|
|
|
void *malloc(unsigned int size) {
|
|
// todo replace this horrible mess!
|
|
// this lacks any page alignment and what so ever
|
|
for (int i = 0; i < MEMMAP_ENTRIES; ++i) {
|
|
if (memmap[i].type != MMAP_TYPE_MALLOC) {
|
|
continue;
|
|
}
|
|
// get first first_map of address
|
|
malloc_map *first_map = (malloc_map *) memmap[i].address;
|
|
malloc_map *current_map = first_map;
|
|
// iterate through maps
|
|
do {
|
|
if (current_map->type == MALLOC_TYPE_USED) {
|
|
goto malloc_find_next;
|
|
}
|
|
if ((unsigned int) current_map->size < size) {
|
|
goto malloc_find_next;
|
|
}
|
|
if ((unsigned int) current_map->size > (size + sizeof(malloc_map))) {
|
|
// big enough to split
|
|
split_malloc_map(current_map, size);
|
|
}
|
|
malloc_used++;
|
|
current_map->type = MALLOC_TYPE_USED;
|
|
return ((void*)current_map) + sizeof(malloc_map);
|
|
|
|
malloc_find_next:
|
|
current_map = current_map->next;
|
|
} while (current_map != first_map);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void free(void *mem) {
|
|
if (mem == NULL) {
|
|
return;
|
|
}
|
|
malloc_used--;
|
|
malloc_map *map = (mem - sizeof(malloc_map));
|
|
map->type = MALLOC_TYPE_FREE;
|
|
};
|
|
|
|
|
|
void print_int(int val, int base) {
|
|
char tmp_str[32];
|
|
memset(tmp_str, 0, 32);
|
|
itoa(val, tmp_str, base);
|
|
kprint(tmp_str);
|
|
}
|
|
|
|
void print_malloc_info() {
|
|
kprint(msg_malloc_num_entries_avail);
|
|
print_int(malloc_entries, 10);
|
|
kprint(msg_nl);
|
|
|
|
kprint(msg_malloc_num_entries_used);
|
|
print_int(malloc_used, 10);
|
|
kprint(msg_nl);
|
|
}
|
|
|
|
|
|
void print_mmap_info() {
|
|
for (int i = 0; i < 16; ++i) {
|
|
if (memmap[i].type == 0) {
|
|
break;
|
|
}
|
|
kprint(msg_index);
|
|
print_int(i, 10);
|
|
kprint(msg_nl);
|
|
kprint(msg_addr);
|
|
print_int((int) memmap[i].address, 16);
|
|
kprint(msg_nl);
|
|
kprint(msg_len);
|
|
print_int(memmap[i].length, 16);
|
|
kprint(msg_nl);
|
|
kprint(msg_type);
|
|
print_int(memmap[i].type, 10);
|
|
kprint(msg_nl);
|
|
kprint(msg_nl);
|
|
}
|
|
}
|