mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 01:58:12 +00:00
Kernel: Parse boot modules from Multiboot specification
This commit is contained in:
parent
3cbe805486
commit
ec056f3bd1
4 changed files with 68 additions and 15 deletions
|
@ -28,6 +28,14 @@
|
||||||
|
|
||||||
#include <AK/Types.h>
|
#include <AK/Types.h>
|
||||||
|
|
||||||
|
struct multiboot_module_entry {
|
||||||
|
u32 start;
|
||||||
|
u32 end;
|
||||||
|
u32 string_addr;
|
||||||
|
u32 reserved;
|
||||||
|
};
|
||||||
|
typedef struct multiboot_module_entry multiboot_module_entry_t;
|
||||||
|
|
||||||
struct multiboot_aout_symbol_table {
|
struct multiboot_aout_symbol_table {
|
||||||
u32 tabsize;
|
u32 tabsize;
|
||||||
u32 strsize;
|
u32 strsize;
|
||||||
|
|
|
@ -64,6 +64,11 @@ namespace Kernel {
|
||||||
static MemoryManager* s_the;
|
static MemoryManager* s_the;
|
||||||
RecursiveSpinLock s_mm_lock;
|
RecursiveSpinLock s_mm_lock;
|
||||||
|
|
||||||
|
const LogStream& operator<<(const LogStream& stream, const UsedMemoryRange& value)
|
||||||
|
{
|
||||||
|
return stream << UserMemoryRangeTypeNames[static_cast<int>(value.type)] << " range @ " << value.start << " - " << value.end;
|
||||||
|
}
|
||||||
|
|
||||||
MemoryManager& MM
|
MemoryManager& MM
|
||||||
{
|
{
|
||||||
return *s_the;
|
return *s_the;
|
||||||
|
@ -122,25 +127,37 @@ void MemoryManager::parse_memory_map()
|
||||||
{
|
{
|
||||||
RefPtr<PhysicalRegion> region;
|
RefPtr<PhysicalRegion> region;
|
||||||
|
|
||||||
// We need to make sure we exclude the kmalloc range as well as the kernel image.
|
// Register used memory regions that we know of.
|
||||||
// The kmalloc range directly follows the kernel image
|
m_used_memory_ranges.ensure_capacity(4);
|
||||||
const PhysicalAddress used_range_start(virtual_to_low_physical(FlatPtr(&start_of_kernel_image)));
|
m_used_memory_ranges.append(UsedMemoryRange { UsedMemoryRangeType::LowMemory, PhysicalAddress(0x00000000), PhysicalAddress(1 * MiB) });
|
||||||
const PhysicalAddress used_range_end(virtual_to_low_physical(FlatPtr(&end_of_kernel_image)));
|
m_used_memory_ranges.append(UsedMemoryRange { UsedMemoryRangeType::Kernel, PhysicalAddress(virtual_to_low_physical(FlatPtr(&start_of_kernel_image))), PhysicalAddress(PAGE_ROUND_UP(virtual_to_low_physical(FlatPtr(&end_of_kernel_image)))) });
|
||||||
klog() << "MM: kernel range: " << used_range_start << " - " << used_range_end;
|
|
||||||
|
if (multiboot_info_ptr->flags & 0x4) {
|
||||||
|
auto* bootmods_start = multiboot_copy_boot_modules_array;
|
||||||
|
auto* bootmods_end = bootmods_start + multiboot_copy_boot_modules_count;
|
||||||
|
|
||||||
|
for (auto* bootmod = bootmods_start; bootmod < bootmods_end; bootmod++) {
|
||||||
|
m_used_memory_ranges.append(UsedMemoryRange { UsedMemoryRangeType::BootModule, PhysicalAddress(bootmod->start), PhysicalAddress(bootmod->end) });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* mmap_begin = reinterpret_cast<multiboot_memory_map_t*>(low_physical_to_virtual(multiboot_info_ptr->mmap_addr));
|
||||||
|
auto* mmap_end = reinterpret_cast<multiboot_memory_map_t*>(low_physical_to_virtual(multiboot_info_ptr->mmap_addr) + multiboot_info_ptr->mmap_length);
|
||||||
|
|
||||||
|
for (auto used_range : m_used_memory_ranges) {
|
||||||
|
klog() << "MM: " << used_range;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto* mmap = mmap_begin; mmap < mmap_end; mmap++) {
|
||||||
|
klog() << "MM: Multiboot mmap: address = " << String::format("0x%016llx", mmap->addr) << ", length = " << String::format("0x%016llx", mmap->len) << ", type = 0x" << String::format("%x", mmap->type);
|
||||||
|
|
||||||
auto* mmap = (multiboot_memory_map_t*)(low_physical_to_virtual(multiboot_info_ptr->mmap_addr));
|
|
||||||
for (; (unsigned long)mmap < (low_physical_to_virtual(multiboot_info_ptr->mmap_addr)) + (multiboot_info_ptr->mmap_length); mmap = (multiboot_memory_map_t*)((unsigned long)mmap + mmap->size + sizeof(mmap->size))) {
|
|
||||||
klog() << "MM: Multiboot mmap: base_addr = " << String::format("0x%08llx", mmap->addr) << ", length = " << String::format("0x%08llx", mmap->len) << ", type = 0x" << String::format("%x", mmap->type);
|
|
||||||
if (mmap->type != MULTIBOOT_MEMORY_AVAILABLE)
|
if (mmap->type != MULTIBOOT_MEMORY_AVAILABLE)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// FIXME: Maybe make use of stuff below the 1MiB mark?
|
|
||||||
if (mmap->addr < (1 * MiB))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if ((mmap->addr + mmap->len) > 0xffffffff)
|
if ((mmap->addr + mmap->len) > 0xffffffff)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
// Fix up unaligned memory regions.
|
||||||
auto diff = (FlatPtr)mmap->addr % PAGE_SIZE;
|
auto diff = (FlatPtr)mmap->addr % PAGE_SIZE;
|
||||||
if (diff != 0) {
|
if (diff != 0) {
|
||||||
klog() << "MM: got an unaligned region base from the bootloader; correcting " << String::format("%p", (void*)mmap->addr) << " by " << diff << " bytes";
|
klog() << "MM: got an unaligned region base from the bootloader; correcting " << String::format("%p", (void*)mmap->addr) << " by " << diff << " bytes";
|
||||||
|
@ -188,12 +205,12 @@ void MemoryManager::parse_memory_map()
|
||||||
|
|
||||||
for (auto& region : m_super_physical_regions) {
|
for (auto& region : m_super_physical_regions) {
|
||||||
m_super_physical_pages += region.finalize_capacity();
|
m_super_physical_pages += region.finalize_capacity();
|
||||||
klog() << "Super physical region: " << region.lower() << " - " << region.upper();
|
klog() << "MM: Super physical region: " << region.lower() << " - " << region.upper();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& region : m_user_physical_regions) {
|
for (auto& region : m_user_physical_regions) {
|
||||||
m_user_physical_pages += region.finalize_capacity();
|
m_user_physical_pages += region.finalize_capacity();
|
||||||
klog() << "User physical region: " << region.lower() << " - " << region.upper();
|
klog() << "MM: User physical region: " << region.lower() << " - " << region.upper();
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT(m_super_physical_pages > 0);
|
ASSERT(m_super_physical_pages > 0);
|
||||||
|
|
|
@ -67,6 +67,26 @@ inline u32 virtual_to_low_physical(u32 physical)
|
||||||
class KBuffer;
|
class KBuffer;
|
||||||
class SynthFSInode;
|
class SynthFSInode;
|
||||||
|
|
||||||
|
enum class UsedMemoryRangeType {
|
||||||
|
LowMemory = 0,
|
||||||
|
Kernel,
|
||||||
|
BootModule,
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr static const char* UserMemoryRangeTypeNames[] {
|
||||||
|
"Low memory",
|
||||||
|
"Kernel",
|
||||||
|
"Boot module",
|
||||||
|
};
|
||||||
|
|
||||||
|
struct UsedMemoryRange {
|
||||||
|
UsedMemoryRangeType type;
|
||||||
|
PhysicalAddress start;
|
||||||
|
PhysicalAddress end;
|
||||||
|
};
|
||||||
|
|
||||||
|
const LogStream& operator<<(const LogStream& stream, const UsedMemoryRange& value);
|
||||||
|
|
||||||
#define MM Kernel::MemoryManager::the()
|
#define MM Kernel::MemoryManager::the()
|
||||||
|
|
||||||
struct MemoryManagerData {
|
struct MemoryManagerData {
|
||||||
|
@ -93,6 +113,7 @@ public:
|
||||||
static MemoryManager& the();
|
static MemoryManager& the();
|
||||||
static bool is_initialized();
|
static bool is_initialized();
|
||||||
|
|
||||||
|
static void early_initialize();
|
||||||
static void initialize(u32 cpu);
|
static void initialize(u32 cpu);
|
||||||
|
|
||||||
static inline MemoryManagerData& get_data()
|
static inline MemoryManagerData& get_data()
|
||||||
|
@ -165,6 +186,8 @@ public:
|
||||||
|
|
||||||
PageDirectory& kernel_page_directory() { return *m_kernel_page_directory; }
|
PageDirectory& kernel_page_directory() { return *m_kernel_page_directory; }
|
||||||
|
|
||||||
|
const Vector<UsedMemoryRange>& used_memory_ranges() { return m_used_memory_ranges; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MemoryManager();
|
MemoryManager();
|
||||||
~MemoryManager();
|
~MemoryManager();
|
||||||
|
@ -221,6 +244,7 @@ private:
|
||||||
|
|
||||||
InlineLinkedList<Region> m_user_regions;
|
InlineLinkedList<Region> m_user_regions;
|
||||||
InlineLinkedList<Region> m_kernel_regions;
|
InlineLinkedList<Region> m_kernel_regions;
|
||||||
|
Vector<UsedMemoryRange> m_used_memory_ranges;
|
||||||
|
|
||||||
InlineLinkedList<VMObject> m_vmobjects;
|
InlineLinkedList<VMObject> m_vmobjects;
|
||||||
|
|
||||||
|
|
|
@ -79,6 +79,9 @@ extern ctor_func_t end_ctors;
|
||||||
extern u32 __stack_chk_guard;
|
extern u32 __stack_chk_guard;
|
||||||
u32 __stack_chk_guard;
|
u32 __stack_chk_guard;
|
||||||
|
|
||||||
|
multiboot_module_entry_t multiboot_copy_boot_modules_array[16];
|
||||||
|
size_t multiboot_copy_boot_modules_count;
|
||||||
|
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
|
|
||||||
[[noreturn]] static void init_stage2(void*);
|
[[noreturn]] static void init_stage2(void*);
|
||||||
|
@ -111,7 +114,8 @@ extern "C" [[noreturn]] void init()
|
||||||
// We need to copy the command line before kmalloc is initialized,
|
// We need to copy the command line before kmalloc is initialized,
|
||||||
// as it may overwrite parts of multiboot!
|
// as it may overwrite parts of multiboot!
|
||||||
CommandLine::early_initialize(reinterpret_cast<const char*>(low_physical_to_virtual(multiboot_info_ptr->cmdline)));
|
CommandLine::early_initialize(reinterpret_cast<const char*>(low_physical_to_virtual(multiboot_info_ptr->cmdline)));
|
||||||
|
memcpy(multiboot_copy_boot_modules_array, (u8*)low_physical_to_virtual(multiboot_info_ptr->mods_addr), multiboot_info_ptr->mods_count * sizeof(multiboot_module_entry_t));
|
||||||
|
multiboot_copy_boot_modules_count = multiboot_info_ptr->mods_count;
|
||||||
s_bsp_processor.early_initialize(0);
|
s_bsp_processor.early_initialize(0);
|
||||||
|
|
||||||
// Invoke the constructors needed for the kernel heap
|
// Invoke the constructors needed for the kernel heap
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue