mirror of
https://github.com/Fennix-Project/Kernel.git
synced 2025-07-11 07:19:20 +00:00
Restructured and rewritten entire codebase
This commit is contained in:
212
core/memory/find_bitmap_region.cpp
Normal file
212
core/memory/find_bitmap_region.cpp
Normal file
@ -0,0 +1,212 @@
|
||||
/*
|
||||
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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <memory.hpp>
|
||||
|
||||
#include <acpi.hpp>
|
||||
#include <debug.h>
|
||||
#include <elf.h>
|
||||
#ifdef DEBUG
|
||||
#include <uart.hpp>
|
||||
#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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user