//----------------------------------------------------------------------------// // GNU GPL OS/K // // // // Desc: Mapping and checking memory related functions // // // // // // Copyright © 2018-2019 The OS/K Team // // // // This file is part of OS/K. // // // // OS/K is free software: you can redistribute it and/or modify // // it under the terms of the GNU General Public License as published by // // the Free Software Foundation, either version 3 of the License, or // // any later version. // // // // OS/K is distributed in the hope that it will be useful, // // but WITHOUT ANY WARRANTY//without even the implied warranty of // // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // // GNU General Public License for more details. // // // // You should have received a copy of the GNU General Public License // // along with OS/K. If not, see . // //----------------------------------------------------------------------------// #include #include #include MemoryMap_t memoryMap = { 0 }; // // Initilization of the memory map, and computation of the available ram size // error_t MmInitMemoryMap(void) { multiboot_memory_map_t *currentEntry; multiboot_memory_map_t *mapEnd; uint i = 0; // sanity checks if (!BtGetBootInfo(memory).memValid && BtGetBootInfo(memory).mapValid) return ENXIO; if ((BtGetBootInfo(memory).upMemory / (MB/KB)) <= MINIMUM_RAM_SIZE) return ENOMEM; // Ok then we can work ------------------------------------------------------ // // the memory map provided by GRUB via the BIOS currentEntry = (multiboot_memory_map_t*)BtGetBootInfo(memory).mapAddr; // End address of the map mapEnd = (multiboot_memory_map_t*) ((ullong)currentEntry + (ullong)BtGetBootInfo(memory).mapLength); // fill the map while (currentEntry < mapEnd) { // memory zone address memoryMap.entry[i].addr = (void*)( (ullong)currentEntry->addr_low + (((ullong)currentEntry->addr_high) << 32 )); // memory zone size in bytes memoryMap.entry[i].length = (ullong)currentEntry->len_low + (((ullong)currentEntry->len_high) << 32); // memory availability memoryMap.entry[i].type = (uint)currentEntry->type; // Adding the size to the size (yup) memoryMap.length++; // moving up ! currentEntry = (multiboot_memory_map_t*) ((ullong)currentEntry + currentEntry->size + sizeof(currentEntry->size)); i++; } DebugLog("[InitMemoryMap] %d entries detected in the memory map\n", memoryMap.length); // compute the free ram size for (i = 0; i < memoryMap.length; i++) { if (memoryMap.entry[i].type == AVAILABLE_ZONE) { memoryMap.freeRamSize += memoryMap.entry[i].length; } else { memoryMap.nonfreeRamSize += memoryMap.entry[i].length; } } // Trully strange if it happens... if (memoryMap.freeRamSize < MINIMUM_RAM_SIZE) return ENOMEM; KernLog("[InitMemoryMap] Available Ram Size : %u Mio, Used Ram Size : %u Kio\n", memoryMap.freeRamSize / MB, memoryMap.nonfreeRamSize / KB); KernLog("[InitMemoryMap] Physical Ram Size : %d Mio\n\n", (memoryMap.freeRamSize + memoryMap.nonfreeRamSize) / MB); return EOK; } size_t MmGetAvailZoneSize(void *start) { uint i; // Because the kernel is the kernel if (start < BtGetBootInfo(btldr).kernelEndAddr) return 0; // Search the zone where the start address is for (i = 0; i < memoryMap.length; i++) { // if the address is in an available zone, we can return the length if ( memoryMap.entry[i].type == AVAILABLE_ZONE && (ullong)start >= (ullong)memoryMap.entry[i].addr && (ullong)start < ((ullong)memoryMap.entry[i].addr + (ullong)memoryMap.entry[i].length) ) { return (size_t)((ullong)memoryMap.entry[i].length - (ullong)start); } } // If there is no zone, we return a 0 size return 0; } void *MmGetFirstAvailZone(void *start) { uint i; void *current = 0; // Because the kernel is the kernel if ((ullong)start < (ullong)BtGetBootInfo(btldr).kernelEndAddr) { return GetFirstAvailZone(BtGetBootInfo(btldr).kernelEndAddr); } // Search the zone where the start address is for (i = 0; i < memoryMap.length; i++) { // if the address is in an available zone, we can return the start address if ( memoryMap.entry[i].type == AVAILABLE_ZONE && (ullong)start >= (ullong)memoryMap.entry[i].addr && (ullong)start < ((ullong)memoryMap.entry[i].addr + (ullong)memoryMap.entry[i].length) ) { current = start; break; } } if (current) return current; // Search the first zone from start for (i = 0; i < memoryMap.length; i++) { // Return the first zone that is after start if ( memoryMap.entry[i].type == AVAILABLE_ZONE && (ullong)start <= (ullong)memoryMap.entry[i].addr ) { current = memoryMap.entry[i].addr; break; } } return current; }