/* This file is part of Fennix Kernel. Fennix Kernel 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 (at your option) any later version. Fennix Kernel 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 Fennix Kernel. If not, see . */ #include #include #include #include #ifdef DEBUG #include #endif #include "../../kernel.h" namespace Memory { __no_sanitize("alignment") void Physical::FindBitmapRegion(uintptr_t &BitmapAddress, size_t &BitmapAddressSize) { size_t BitmapSize = (size_t)(bInfo.Memory.Size / PAGE_SIZE) / 8 + 1; uintptr_t KernelStart = (uintptr_t)bInfo.Kernel.PhysicalBase; uintptr_t KernelEnd = (uintptr_t)bInfo.Kernel.PhysicalBase + bInfo.Kernel.Size; uintptr_t SectionsStart = 0x0; uintptr_t SectionsEnd = 0x0; uintptr_t Symbols = 0x0; uintptr_t StringAddress = 0x0; size_t SymbolSize = 0; size_t StringSize = 0; uintptr_t RSDPStart = 0x0; uintptr_t RSDPEnd = 0x0; if (bInfo.Kernel.Symbols.Num && bInfo.Kernel.Symbols.EntSize && bInfo.Kernel.Symbols.Shndx) { char *sections = r_cst(char *, bInfo.Kernel.Symbols.Sections); SectionsStart = (uintptr_t)sections; SectionsEnd = (uintptr_t)sections + bInfo.Kernel.Symbols.EntSize * bInfo.Kernel.Symbols.Num; for (size_t i = 0; i < bInfo.Kernel.Symbols.Num; ++i) { Elf_Shdr *sym = (Elf_Shdr *)§ions[bInfo.Kernel.Symbols.EntSize * i]; Elf_Shdr *str = (Elf_Shdr *)§ions[bInfo.Kernel.Symbols.EntSize * sym->sh_link]; if (sym->sh_type == SHT_SYMTAB && str->sh_type == SHT_STRTAB) { Symbols = (uintptr_t)sym->sh_addr; StringAddress = (uintptr_t)str->sh_addr; SymbolSize = (size_t)sym->sh_size; StringSize = (size_t)str->sh_size; break; } } } #if defined(a86) if (bInfo.RSDP) { RSDPStart = (uintptr_t)bInfo.RSDP; RSDPEnd = (uintptr_t)bInfo.RSDP + sizeof(BootInfo::RSDPInfo); #ifdef DEBUG ACPI::ACPI::ACPIHeader *ACPIPtr; bool XSDT = false; if (bInfo.RSDP->Revision >= 2 && bInfo.RSDP->XSDTAddress) { ACPIPtr = (ACPI::ACPI::ACPIHeader *)bInfo.RSDP->XSDTAddress; XSDT = true; } else ACPIPtr = (ACPI::ACPI::ACPIHeader *)(uintptr_t)bInfo.RSDP->RSDTAddress; if (Memory::Virtual().Check(ACPIPtr)) { size_t TableSize = ((ACPIPtr->Length - sizeof(ACPI::ACPI::ACPIHeader)) / (XSDT ? 8 : 4)); debug("There are %d ACPI tables", TableSize); } #endif } #elif defined(aa64) #endif for (uint64_t i = 0; i < bInfo.Memory.Entries; i++) { if (bInfo.Memory.Entry[i].Type == Usable) { uintptr_t RegionAddress = (uintptr_t)bInfo.Memory.Entry[i].BaseAddress; uintptr_t RegionSize = bInfo.Memory.Entry[i].Length; /* We don't want to use the first 1MB of memory. */ if (RegionAddress <= 0xFFFFF) continue; if ((BitmapSize + 0x100) > RegionSize) { debug("Region %p-%p (%d MiB) is too small for bitmap.", (void *)RegionAddress, (void *)(RegionAddress + RegionSize), TO_MiB(RegionSize)); continue; } BitmapAddress = RegionAddress; BitmapAddressSize = RegionSize; struct AddrRange { uintptr_t Start; uintptr_t End; }; auto SortAddresses = [](AddrRange *Array, size_t n) { size_t MinimumIndex; for (size_t i = 0; i < n - 1; i++) { MinimumIndex = i; for (size_t j = i + 1; j < n; j++) if (Array[j].Start < Array[MinimumIndex].Start) MinimumIndex = j; AddrRange tmp = Array[MinimumIndex]; Array[MinimumIndex] = Array[i]; Array[i] = tmp; } }; AddrRange PtrArray[] = { {KernelStart, KernelEnd}, {SectionsStart, SectionsEnd}, {Symbols, Symbols + SymbolSize}, {StringAddress, StringAddress + StringSize}, {RSDPStart, RSDPEnd}, {(uintptr_t)bInfo.Kernel.FileBase, (uintptr_t)bInfo.Kernel.FileBase + bInfo.Kernel.Size}, {(uintptr_t)bInfo.Modules[0].Address, (uintptr_t)bInfo.Modules[0].Address + bInfo.Modules[0].Size}, {(uintptr_t)bInfo.Modules[1].Address, (uintptr_t)bInfo.Modules[1].Address + bInfo.Modules[1].Size}, {(uintptr_t)bInfo.Modules[2].Address, (uintptr_t)bInfo.Modules[2].Address + bInfo.Modules[2].Size}, {(uintptr_t)bInfo.Modules[3].Address, (uintptr_t)bInfo.Modules[3].Address + bInfo.Modules[3].Size}, /* MAX_MODULES == 4 */ }; SortAddresses(PtrArray, sizeof(PtrArray) / sizeof(PtrArray[0])); for (size_t i = 0; i < sizeof(PtrArray) / sizeof(PtrArray[0]); i++) { if (PtrArray[i].Start == 0x0) continue; uintptr_t Start = PtrArray[i].Start; uintptr_t End = PtrArray[i].End; debug("%#lx - %#lx", Start, End); if (RegionAddress >= Start && End <= (RegionAddress + RegionSize)) { BitmapAddress = End; BitmapAddressSize = RegionSize - (End - RegionAddress); } } if ((BitmapSize + 0x100) > BitmapAddressSize) { debug("Region %p-%p (%d MiB) is too small for bitmap.", (void *)BitmapAddress, (void *)(BitmapAddress + BitmapAddressSize), TO_MiB(BitmapAddressSize)); continue; } debug("Found free memory for bitmap: %p (%d MiB)", (void *)BitmapAddress, TO_MiB(BitmapAddressSize)); break; } } } }