#include "memorymap.h" #include int compare_regions(struct memory_region_t *lhs, struct memory_region_t *rhs) { if(lhs->location == rhs->location) { return lhs->size > rhs->size ? 1 : (lhs->size == rhs->size ? 0 : -1); } else { return lhs->location > rhs->location ? 1 : -1; } } bool region_overlaps(struct memory_region_t *lhs, struct memory_region_t *rhs) { if(rhs->location < lhs->location) { return rhs->location + rhs->size > lhs->location; } return rhs->location < lhs->location + lhs->size; } bool region_contains(struct memory_region_t *lhs, struct memory_region_t *rhs) { return (rhs->location >= lhs->location) && (rhs->location + rhs->size <= lhs->location + lhs->size); } void insert_map_entry(struct memory_map_t *map, physaddr_t location, size_t size, unsigned int type) { struct memory_region_t new_region = {.location = location, .size = size, .type = type}; unsigned int i = 0; while(i < map->size) { if(compare_regions(&new_region, &map->array[i]) < 0) { struct memory_region_t buffer = new_region; new_region = map->array[i]; map->array[i] = buffer; } i++; } map->array[i] = new_region; map->size++; } void remove_map_entry(struct memory_map_t *map, int index) { if(index >= 0 && index < map->size) { for(int i = index; i < map->size - 1; i++) { map->array[i] = map->array[i + 1]; } map->size--; } } int trim_map(struct memory_map_t *map, int index) { if(index + 1 >= map->size) { return -1; } struct memory_region_t left = map->array[index]; struct memory_region_t right = map->array[index + 1]; if(region_overlaps(&left, &right)) { if(left.type == right.type) { left.size = (right.location + right.size > left.location + left.size ? right.location + right.size : left.location + left.size) - left.location; remove_map_entry(map, index + 1); return index; } else if(left.type < right.type) { if(region_contains(&right, &left)) { remove_map_entry(map, index); return index; } else if(left.location + left.size <= right.location + right.size) { left.size = (right.location > left.location) ? right.location - left.location : 0; return index + 1; } else { struct memory_region_t new_right = { .location = right.location + right.size, .size = (left.location + left.size) - (right.location + right.size), .type = left.type}; left.size = (right.location > left.location) ? right.location - left.location : 0; if(left.size == 0) remove_map_entry(map, index); insert_map_entry(map, new_right.location, new_right.size, new_right.type); return index + 2; } } else { if(region_contains(&left, &right)) { remove_map_entry(map, index + 1); return index; } else { right.size = (right.location + right.size) - (left.location + left.size); right.location = left.location + left.size; return index + 1; } } } else if((left.location + left.size == right.location) && left.type == right.type) { left.size = right.location + right.size - left.location; remove_map_entry(map, index + 1); return index; } return index + 1; } void insert_region(struct memory_map_t *map, physaddr_t location, size_t size, unsigned int type) { insert_map_entry(map, location, size, type); int i = 0; while(i >= 0) { i = trim_map(map, i); } }