// // Created by rick on 22-04-20. // #include #include #include #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; typedef struct { void *address; u32 length; u32 type; } __attribute((packed)) mmap_entry; 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_multiboot(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_malloc_info() { printf("Malloc avail entries: %d\n" "Malloc used entries: %d\n", malloc_entries, malloc_used); } void print_mmap_info() { for (int i = 0; i < 16; ++i) { if (memmap[i].type == 0) { break; } printf("Idx: %d\n" "Address: %8x\n" "Length: %8x\n" "Type: %d\n\n", i, memmap[i].address, memmap[i].length, memmap[i].type); } }