Map all memory regions and graphics framebuffer
This commit is contained in:
parent
7c5af33ace
commit
d8c85ad045
@ -90,7 +90,7 @@ private bool set_graphics_mode()
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool get_memory_map()
|
||||
private ulong get_memory_map()
|
||||
{
|
||||
UINTN memory_map_size = scratch_free();
|
||||
UINTN descriptor_size;
|
||||
@ -105,26 +105,39 @@ private bool get_memory_map()
|
||||
if (status != EFI_SUCCESS)
|
||||
{
|
||||
writeln("GetMemoryMap: Error %x", status);
|
||||
return false;
|
||||
return 0u;
|
||||
}
|
||||
ulong max_physical_address;
|
||||
size_t n_entries = memory_map_size / descriptor_size;
|
||||
size_t di;
|
||||
for (size_t i = 0u; i < n_entries; i++)
|
||||
size_t count;
|
||||
for (count = 0u; count < n_entries; count++)
|
||||
{
|
||||
EFI_MEMORY_DESCRIPTOR * descriptor = cast(EFI_MEMORY_DESCRIPTOR *)&scratch_base[i * descriptor_size];
|
||||
if ((descriptor.Type == EfiLoaderCode) ||
|
||||
if (count > bootinfo.memory_map.length)
|
||||
{
|
||||
writeln("Memory map too large");
|
||||
for (;;)
|
||||
{
|
||||
}
|
||||
}
|
||||
EFI_MEMORY_DESCRIPTOR * descriptor = cast(EFI_MEMORY_DESCRIPTOR *)&scratch_base[count * descriptor_size];
|
||||
ulong end_address = descriptor.PhysicalStart + descriptor.NumberOfPages * 4096u;
|
||||
if ((end_address > max_physical_address) &&
|
||||
((descriptor.Type == EfiLoaderCode) ||
|
||||
(descriptor.Type == EfiLoaderData) ||
|
||||
(descriptor.Type == EfiBootServicesCode) ||
|
||||
(descriptor.Type == EfiBootServicesCode) ||
|
||||
(descriptor.Type == EfiConventionalMemory))
|
||||
(descriptor.Type == EfiBootServicesData) ||
|
||||
(descriptor.Type == EfiRuntimeServicesCode) ||
|
||||
(descriptor.Type == EfiRuntimeServicesData) ||
|
||||
(descriptor.Type == EfiConventionalMemory)))
|
||||
{
|
||||
bootinfo.memory_map[di].base = descriptor.PhysicalStart;
|
||||
bootinfo.memory_map[di].size = descriptor.NumberOfPages * 4096u;
|
||||
di++;
|
||||
max_physical_address = end_address;
|
||||
}
|
||||
bootinfo.memory_map[count].base = descriptor.PhysicalStart;
|
||||
bootinfo.memory_map[count].size = descriptor.NumberOfPages * 4096u;
|
||||
bootinfo.memory_map[count].type = cast(ubyte)descriptor.Type;
|
||||
}
|
||||
bootinfo.memory_map_count = di;
|
||||
return true;
|
||||
bootinfo.memory_map_count = count;
|
||||
return max_physical_address;
|
||||
}
|
||||
|
||||
private PageTableEntry * new_page_table()
|
||||
@ -134,7 +147,7 @@ private PageTableEntry * new_page_table()
|
||||
return pt;
|
||||
}
|
||||
|
||||
private void map(ulong source_page, ulong dest_page, PageTableEntry * pt_base)
|
||||
private void map4k(ulong source_page, ulong dest_page, PageTableEntry * pt_base)
|
||||
{
|
||||
PageTableEntry * pt = pt_base;
|
||||
PageTableEntry * next_pt;
|
||||
@ -164,32 +177,77 @@ private void map(ulong source_page, ulong dest_page, PageTableEntry * pt_base)
|
||||
}
|
||||
}
|
||||
|
||||
private void map2m(ulong source_page, ulong dest_page, PageTableEntry * pt_base)
|
||||
{
|
||||
PageTableEntry * pt = pt_base;
|
||||
PageTableEntry * next_pt;
|
||||
for (size_t level = 0; level < 3u; level++)
|
||||
{
|
||||
size_t pt_index = PageTableEntry.page_table_index(source_page, level);
|
||||
if (pt[pt_index].present())
|
||||
{
|
||||
pt = pt[pt_index].next();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (level < 2u)
|
||||
{
|
||||
next_pt = new_page_table();
|
||||
pt[pt_index] = PageTableEntry(cast(ulong)next_pt,
|
||||
0u, 0u, 0u, 0u, 0u, 0u, 1u, 1u);
|
||||
}
|
||||
else
|
||||
{
|
||||
pt[pt_index] = PageTableEntry(dest_page,
|
||||
0u, 0u, 1u, 0u, 0u, 0u, 1u, 1u);
|
||||
}
|
||||
pt = next_pt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void map_hulk(PageTableEntry * pt_base)
|
||||
{
|
||||
ulong virt = HULK_VIRTUAL_START;
|
||||
ulong phys = cast(ulong)&hulk_start;
|
||||
while (phys < cast(ulong)&hulk_end)
|
||||
{
|
||||
map(virt, phys, pt_base);
|
||||
map4k(virt, phys, pt_base);
|
||||
virt += 4096u;
|
||||
phys += 4096u;
|
||||
}
|
||||
}
|
||||
|
||||
private void build_page_tables()
|
||||
private void build_page_tables(ulong max_physical_address)
|
||||
{
|
||||
PageTableEntry * pt_base = new_page_table();
|
||||
/* Map physical RAM. */
|
||||
for (size_t addr = 0u; addr < max_physical_address; addr += (2u * 1024u * 1024u))
|
||||
{
|
||||
map2m(addr, addr, pt_base);
|
||||
}
|
||||
/* Map any memory regions that are outside physical RAM. */
|
||||
for (size_t i = 0u; i < bootinfo.memory_map_count; i++)
|
||||
{
|
||||
size_t n_pages = bootinfo.memory_map[i].size / 4096u;
|
||||
for (size_t p = 0u; p < n_pages; p++)
|
||||
if (bootinfo.memory_map[i].base > max_physical_address)
|
||||
{
|
||||
ulong page_addr = bootinfo.memory_map[i].base + 4096u * p;
|
||||
/* Identity map all pages. */
|
||||
map(page_addr, page_addr, pt_base);
|
||||
for (size_t offset = 0u; offset < bootinfo.memory_map[i].size; offset += 4096u)
|
||||
{
|
||||
ulong addr = bootinfo.memory_map[i].base + offset;
|
||||
map4k(addr, addr, pt_base);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Map graphics framebuffer. */
|
||||
ulong framebuffer_size = bootinfo.fb.height * bootinfo.fb.stride;
|
||||
for (size_t offset = 0u; offset < framebuffer_size; offset++)
|
||||
{
|
||||
ulong addr = cast(ulong)bootinfo.fb.buffer + offset;
|
||||
map4k(addr, addr, pt_base);
|
||||
}
|
||||
/* Map HULK to its requested starting virtual address. */
|
||||
map_hulk(pt_base);
|
||||
/* Switch to the new page table. */
|
||||
write_cr3(cast(ulong)pt_base);
|
||||
}
|
||||
|
||||
@ -214,9 +272,10 @@ extern (C) EFI_STATUS efi_main(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE * st)
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
ulong max_physical_address;
|
||||
for (;;)
|
||||
{
|
||||
get_memory_map();
|
||||
max_physical_address = get_memory_map();
|
||||
|
||||
EFI_STATUS status = st.BootServices.ExitBootServices(image_handle, memory_map_key);
|
||||
if (status == EFI_INVALID_PARAMETER)
|
||||
@ -232,7 +291,7 @@ extern (C) EFI_STATUS efi_main(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE * st)
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
build_page_tables();
|
||||
build_page_tables(max_physical_address);
|
||||
|
||||
jump_to_hulk();
|
||||
|
||||
|
@ -4,6 +4,7 @@ struct BootInfo
|
||||
{
|
||||
ulong base;
|
||||
size_t size;
|
||||
ubyte type;
|
||||
}
|
||||
struct Framebuffer
|
||||
{
|
||||
@ -15,7 +16,7 @@ struct BootInfo
|
||||
}
|
||||
|
||||
Framebuffer fb;
|
||||
MemoryRegion[500] memory_map;
|
||||
MemoryRegion[800] memory_map;
|
||||
size_t memory_map_count;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user