Allocate HULK stack region from HELLO, translate memory region types
This commit is contained in:
parent
f236a64b21
commit
f29bd9d00c
@ -23,12 +23,12 @@ class HulkBinObj < Builder
|
|||||||
File.write(@target, <<EOF)
|
File.write(@target, <<EOF)
|
||||||
.section ".rodata"
|
.section ".rodata"
|
||||||
.balign 4096
|
.balign 4096
|
||||||
.global hulk_bin_start
|
.global _hulk_bin_start
|
||||||
hulk_bin_start:
|
_hulk_bin_start:
|
||||||
.incbin "#{@sources.first}"
|
.incbin "#{@sources.first}"
|
||||||
.balign 4096
|
.balign 4096
|
||||||
.global hulk_bin_end
|
.global _hulk_bin_end
|
||||||
hulk_bin_end:
|
_hulk_bin_end:
|
||||||
EOF
|
EOF
|
||||||
unless @cache.up_to_date?(@target, nil, @sources, @env)
|
unless @cache.up_to_date?(@target, nil, @sources, @env)
|
||||||
print_run_message("Creating HULK binary object <target>#{@target}<reset>", nil)
|
print_run_message("Creating HULK binary object <target>#{@target}<reset>", nil)
|
||||||
|
@ -14,9 +14,38 @@ import hos.memory;
|
|||||||
|
|
||||||
__gshared EFI_SYSTEM_TABLE * st;
|
__gshared EFI_SYSTEM_TABLE * st;
|
||||||
private __gshared BootInfo bootinfo;
|
private __gshared BootInfo bootinfo;
|
||||||
private __gshared UINTN memory_map_key;
|
extern extern(C) __gshared ubyte _hulk_bin_start;
|
||||||
extern extern(C) __gshared ubyte hulk_bin_start;
|
extern extern(C) __gshared ubyte _hulk_bin_end;
|
||||||
extern extern(C) __gshared ubyte hulk_bin_end;
|
|
||||||
|
private HulkHeader * hulk_header()
|
||||||
|
{
|
||||||
|
return cast(HulkHeader *)&_hulk_bin_start;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ulong hulk_bin_phys()
|
||||||
|
{
|
||||||
|
return cast(ulong)&_hulk_bin_start;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ulong hulk_bin_size()
|
||||||
|
{
|
||||||
|
return cast(ulong)&_hulk_bin_end - cast(ulong)&_hulk_bin_start;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ulong hulk_total_size()
|
||||||
|
{
|
||||||
|
return cast(ulong)hulk_header().total_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ulong hulk_bss_size()
|
||||||
|
{
|
||||||
|
return hulk_total_size() - hulk_bin_size();
|
||||||
|
}
|
||||||
|
|
||||||
|
private ulong hulk_stack_size()
|
||||||
|
{
|
||||||
|
return hulk_header().stack_size;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Detect if we're running in QEMU.
|
* Detect if we're running in QEMU.
|
||||||
@ -94,11 +123,26 @@ private bool set_graphics_mode()
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Walk the EFI memory map and translate it to the HULK bootinfo format.
|
* Walk the EFI memory map and translate it to the HULK bootinfo format.
|
||||||
*
|
|
||||||
* @return Maximum physical address to identity map.
|
|
||||||
*/
|
*/
|
||||||
private ulong get_memory_map()
|
private void get_memory_map(ulong * bss_phys, ulong * stack_phys, ulong * max_physical_address, UINTN * memory_map_key)
|
||||||
{
|
{
|
||||||
|
immutable static ubyte[] efi_to_hulk_memory_map_type = [
|
||||||
|
BootInfo.MemoryRegion.Type.Reserved, // EfiReservedMemoryType
|
||||||
|
BootInfo.MemoryRegion.Type.Conventional, // EfiLoaderCode
|
||||||
|
BootInfo.MemoryRegion.Type.Conventional, // EfiLoaderData
|
||||||
|
BootInfo.MemoryRegion.Type.Conventional, // EfiBootServicesCode
|
||||||
|
BootInfo.MemoryRegion.Type.Conventional, // EfiBootServicesData
|
||||||
|
BootInfo.MemoryRegion.Type.Reserved, // EfiRuntimeServicesCode
|
||||||
|
BootInfo.MemoryRegion.Type.Reserved, // EfiRuntimeServicesData
|
||||||
|
BootInfo.MemoryRegion.Type.Conventional, // EfiConventionalMemory
|
||||||
|
BootInfo.MemoryRegion.Type.Unusable, // EfiUnusableMemory
|
||||||
|
BootInfo.MemoryRegion.Type.ACPIReclaim, // EfiACPIReclaimMemory
|
||||||
|
BootInfo.MemoryRegion.Type.ACPINVS, // EfiACPIMemoryNVS
|
||||||
|
BootInfo.MemoryRegion.Type.MemoryMappedIO, // EfiMemoryMappedIO
|
||||||
|
BootInfo.MemoryRegion.Type.MemoryMappedIOPortSpace, // EfiMemoryMappedIOPortSpace
|
||||||
|
BootInfo.MemoryRegion.Type.PalCode, // EfiPalCode
|
||||||
|
];
|
||||||
|
*max_physical_address = 0u;
|
||||||
UINTN memory_map_size = scratch.free();
|
UINTN memory_map_size = scratch.free();
|
||||||
UINTN descriptor_size;
|
UINTN descriptor_size;
|
||||||
UINT32 descriptor_version;
|
UINT32 descriptor_version;
|
||||||
@ -106,29 +150,28 @@ private ulong get_memory_map()
|
|||||||
UINTN status = st.BootServices.GetMemoryMap(
|
UINTN status = st.BootServices.GetMemoryMap(
|
||||||
&memory_map_size,
|
&memory_map_size,
|
||||||
cast(EFI_MEMORY_DESCRIPTOR *)scratch_base,
|
cast(EFI_MEMORY_DESCRIPTOR *)scratch_base,
|
||||||
&memory_map_key,
|
memory_map_key,
|
||||||
&descriptor_size,
|
&descriptor_size,
|
||||||
&descriptor_version);
|
&descriptor_version);
|
||||||
if (status != EFI_SUCCESS)
|
if (status != EFI_SUCCESS)
|
||||||
{
|
{
|
||||||
console.writeln("GetMemoryMap: Error %x", status);
|
console.writeln("GetMemoryMap: Error %x", status);
|
||||||
return 0u;
|
for (;;) {}
|
||||||
}
|
}
|
||||||
ulong max_physical_address;
|
|
||||||
size_t n_entries = memory_map_size / descriptor_size;
|
size_t n_entries = memory_map_size / descriptor_size;
|
||||||
size_t count;
|
size_t count;
|
||||||
|
bool found_bss;
|
||||||
|
bool found_stack;
|
||||||
for (count = 0u; count < n_entries; count++)
|
for (count = 0u; count < n_entries; count++)
|
||||||
{
|
{
|
||||||
if (count > bootinfo.memory_map.length)
|
if (count > bootinfo.memory_map.length)
|
||||||
{
|
{
|
||||||
console.writeln("Memory map too large");
|
console.writeln("Memory map too large");
|
||||||
for (;;)
|
for (;;) {}
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
EFI_MEMORY_DESCRIPTOR * descriptor = cast(EFI_MEMORY_DESCRIPTOR *)&scratch_base[count * descriptor_size];
|
EFI_MEMORY_DESCRIPTOR * descriptor = cast(EFI_MEMORY_DESCRIPTOR *)&scratch_base[count * descriptor_size];
|
||||||
ulong end_address = descriptor.PhysicalStart + descriptor.NumberOfPages * 4096u;
|
ulong end_address = descriptor.PhysicalStart + descriptor.NumberOfPages * 4096u;
|
||||||
if ((end_address > max_physical_address) &&
|
if ((end_address > *max_physical_address) &&
|
||||||
((descriptor.Type == EfiLoaderCode) ||
|
((descriptor.Type == EfiLoaderCode) ||
|
||||||
(descriptor.Type == EfiLoaderData) ||
|
(descriptor.Type == EfiLoaderData) ||
|
||||||
(descriptor.Type == EfiBootServicesCode) ||
|
(descriptor.Type == EfiBootServicesCode) ||
|
||||||
@ -137,14 +180,39 @@ private ulong get_memory_map()
|
|||||||
(descriptor.Type == EfiRuntimeServicesData) ||
|
(descriptor.Type == EfiRuntimeServicesData) ||
|
||||||
(descriptor.Type == EfiConventionalMemory)))
|
(descriptor.Type == EfiConventionalMemory)))
|
||||||
{
|
{
|
||||||
max_physical_address = end_address;
|
*max_physical_address = end_address;
|
||||||
|
}
|
||||||
|
if (descriptor.Type >= efi_to_hulk_memory_map_type.length)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
bootinfo.memory_map[count].base = descriptor.PhysicalStart;
|
bootinfo.memory_map[count].base = descriptor.PhysicalStart;
|
||||||
bootinfo.memory_map[count].size = descriptor.NumberOfPages * 4096u;
|
bootinfo.memory_map[count].size = descriptor.NumberOfPages * 4096u;
|
||||||
bootinfo.memory_map[count].type = cast(ubyte)descriptor.Type;
|
bootinfo.memory_map[count].type = efi_to_hulk_memory_map_type[descriptor.Type];
|
||||||
|
if ((!found_bss) &&
|
||||||
|
(descriptor.Type == EfiConventionalMemory) &&
|
||||||
|
(bootinfo.memory_map[count].size >= hulk_bss_size()))
|
||||||
|
{
|
||||||
|
*bss_phys = bootinfo.memory_map[count].base;
|
||||||
|
bootinfo.memory_map[count].base += hulk_bss_size();
|
||||||
|
bootinfo.memory_map[count].size -= hulk_bss_size();
|
||||||
|
found_bss = true;
|
||||||
|
}
|
||||||
|
if ((!found_stack) &&
|
||||||
|
(descriptor.Type == EfiConventionalMemory) &&
|
||||||
|
(bootinfo.memory_map[count].size >= hulk_stack_size()))
|
||||||
|
{
|
||||||
|
*stack_phys = bootinfo.memory_map[count].base;
|
||||||
|
bootinfo.memory_map[count].base += hulk_stack_size();
|
||||||
|
bootinfo.memory_map[count].size -= hulk_stack_size();
|
||||||
|
found_stack = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
bootinfo.memory_map_count = count;
|
bootinfo.memory_map_count = count;
|
||||||
return max_physical_address;
|
if ((!found_bss) && (!found_stack))
|
||||||
|
{
|
||||||
|
for (;;) {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -194,6 +262,25 @@ private void map4k(ulong source_page, ulong dest_page, PageTableEntry * pt_base)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map a virtual region to a physical region using 4KB pages.
|
||||||
|
*
|
||||||
|
* @param source Source address.
|
||||||
|
* @param dest Destination address.
|
||||||
|
* @param size Region size.
|
||||||
|
* @param pt_base Page table base address.
|
||||||
|
*/
|
||||||
|
private void map4kregion(ulong source, ulong dest, size_t size, PageTableEntry * pt_base)
|
||||||
|
{
|
||||||
|
ulong end = source + size;
|
||||||
|
while (source < end)
|
||||||
|
{
|
||||||
|
map4k(source, dest, pt_base);
|
||||||
|
source += 4096u;
|
||||||
|
dest += 4096u;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Map a virtual address to a physical address using 2MB pages.
|
* Map a virtual address to a physical address using 2MB pages.
|
||||||
*
|
*
|
||||||
@ -230,64 +317,22 @@ private void map2m(ulong source_page, ulong dest_page, PageTableEntry * pt_base)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Allocate a memory region for the HULK bss section.
|
|
||||||
*
|
|
||||||
* @param bss_size Size of the HULK bss section.
|
|
||||||
*
|
|
||||||
* @return Physical memory address.
|
|
||||||
*/
|
|
||||||
private ulong alloc_hulk_bss(size_t bss_size)
|
|
||||||
{
|
|
||||||
for (size_t i = 0u; i < bootinfo.memory_map_count; i++)
|
|
||||||
{
|
|
||||||
if ((bootinfo.memory_map[i].type == EfiConventionalMemory) &&
|
|
||||||
(bootinfo.memory_map[i].size >= bss_size))
|
|
||||||
{
|
|
||||||
memset64(cast(void *)bootinfo.memory_map[i].base, 0u, bss_size / 8u);
|
|
||||||
return bootinfo.memory_map[i].base;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We failed to find free memory. */
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Map HULK virtual addresses to physical kernel location.
|
* Map HULK virtual addresses to physical kernel location.
|
||||||
*
|
*
|
||||||
* @param pt_base Page table base address.
|
* @param pt_base Page table base address.
|
||||||
*/
|
*/
|
||||||
private void map_hulk(PageTableEntry * pt_base)
|
private void map_hulk(PageTableEntry * pt_base, ulong bss_phys, ulong stack_phys)
|
||||||
{
|
{
|
||||||
|
/* Map HULK bin region. */
|
||||||
ulong virt = HULK_VIRTUAL_START;
|
ulong virt = HULK_VIRTUAL_START;
|
||||||
ulong hulk_bin_phys_start = cast(ulong)&hulk_bin_start;
|
map4kregion(virt, hulk_bin_phys(), hulk_bin_size(), pt_base);
|
||||||
bootinfo.hulk_phys = hulk_bin_phys_start;
|
/* Map HULK bss region. */
|
||||||
ulong hulk_bin_phys_end = cast(ulong)&hulk_bin_end;
|
virt += hulk_bin_size();
|
||||||
ulong phys_iter = hulk_bin_phys_start;
|
map4kregion(virt, bss_phys, hulk_bss_size(), pt_base);
|
||||||
while (phys_iter < hulk_bin_phys_end)
|
/* Map HULK stack. */
|
||||||
{
|
virt += hulk_bss_size();
|
||||||
map4k(virt, phys_iter, pt_base);
|
map4kregion(virt, stack_phys, hulk_stack_size(), pt_base);
|
||||||
virt += 4096u;
|
|
||||||
phys_iter += 4096u;
|
|
||||||
}
|
|
||||||
/* Now the binary has been mapped, but the bss section still needs to be
|
|
||||||
* allocated, zeroed and mapped. */
|
|
||||||
HulkHeader * hulk_header = cast(HulkHeader *)&hulk_bin_start;
|
|
||||||
size_t hulk_bin_phys_size = hulk_bin_phys_end - hulk_bin_phys_end;
|
|
||||||
size_t bss_size = cast(size_t)hulk_header.total_size - hulk_bin_phys_size;
|
|
||||||
ulong bss_phys = alloc_hulk_bss(bss_size);
|
|
||||||
bootinfo.bss_phys = bss_phys;
|
|
||||||
bootinfo.bss_size = bss_size;
|
|
||||||
ulong bss_phys_end = bss_phys + bss_size;
|
|
||||||
while (bss_phys < bss_phys_end)
|
|
||||||
{
|
|
||||||
map4k(virt, bss_phys, pt_base);
|
|
||||||
virt += 4096u;
|
|
||||||
bss_phys += 4096u;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -295,7 +340,7 @@ private void map_hulk(PageTableEntry * pt_base)
|
|||||||
*
|
*
|
||||||
* @param max_physical_address Maximum physical address to identity map.
|
* @param max_physical_address Maximum physical address to identity map.
|
||||||
*/
|
*/
|
||||||
private void build_page_tables(ulong max_physical_address)
|
private void build_page_tables(ulong max_physical_address, ulong bss_phys, ulong stack_phys)
|
||||||
{
|
{
|
||||||
PageTableEntry * pt_base = new_page_table();
|
PageTableEntry * pt_base = new_page_table();
|
||||||
/* Map physical RAM. */
|
/* Map physical RAM. */
|
||||||
@ -323,7 +368,7 @@ private void build_page_tables(ulong max_physical_address)
|
|||||||
map4k(addr, addr, pt_base);
|
map4k(addr, addr, pt_base);
|
||||||
}
|
}
|
||||||
/* Map HULK to its requested starting virtual address. */
|
/* Map HULK to its requested starting virtual address. */
|
||||||
map_hulk(pt_base);
|
map_hulk(pt_base, bss_phys, stack_phys);
|
||||||
/* Switch to the new page table. */
|
/* Switch to the new page table. */
|
||||||
write_cr3(cast(ulong)pt_base);
|
write_cr3(cast(ulong)pt_base);
|
||||||
}
|
}
|
||||||
@ -333,9 +378,8 @@ private void build_page_tables(ulong max_physical_address)
|
|||||||
*/
|
*/
|
||||||
private void jump_to_hulk()
|
private void jump_to_hulk()
|
||||||
{
|
{
|
||||||
HulkHeader * hulk_header = cast(HulkHeader *)&hulk_bin_start;
|
void function(BootInfo *) hulk_entry_fn = cast(void function(BootInfo *))hulk_header().entry;
|
||||||
void function(BootInfo *) hulk_start = cast(void function(BootInfo *))hulk_header.entry;
|
hulk_entry_fn(&bootinfo);
|
||||||
hulk_start(&bootinfo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -359,10 +403,13 @@ extern (C) EFI_STATUS efi_main(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE * st)
|
|||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ulong bss_phys;
|
||||||
|
ulong stack_phys;
|
||||||
ulong max_physical_address;
|
ulong max_physical_address;
|
||||||
|
UINTN memory_map_key;
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
max_physical_address = get_memory_map();
|
get_memory_map(&bss_phys, &stack_phys, &max_physical_address, &memory_map_key);
|
||||||
|
|
||||||
EFI_STATUS status = st.BootServices.ExitBootServices(image_handle, memory_map_key);
|
EFI_STATUS status = st.BootServices.ExitBootServices(image_handle, memory_map_key);
|
||||||
if (status == EFI_INVALID_PARAMETER)
|
if (status == EFI_INVALID_PARAMETER)
|
||||||
@ -378,7 +425,11 @@ extern (C) EFI_STATUS efi_main(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE * st)
|
|||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
build_page_tables(max_physical_address);
|
build_page_tables(max_physical_address, bss_phys, stack_phys);
|
||||||
|
|
||||||
|
bootinfo.hulk_phys = hulk_bin_phys();
|
||||||
|
bootinfo.bss_phys = bss_phys;
|
||||||
|
bootinfo.stack_phys = stack_phys;
|
||||||
|
|
||||||
jump_to_hulk();
|
jump_to_hulk();
|
||||||
|
|
||||||
|
@ -30,6 +30,18 @@ struct BootInfo
|
|||||||
*/
|
*/
|
||||||
struct MemoryRegion
|
struct MemoryRegion
|
||||||
{
|
{
|
||||||
|
enum Type
|
||||||
|
{
|
||||||
|
Reserved,
|
||||||
|
Conventional,
|
||||||
|
Unusable,
|
||||||
|
ACPIReclaim,
|
||||||
|
ACPINVS,
|
||||||
|
MemoryMappedIO,
|
||||||
|
MemoryMappedIOPortSpace,
|
||||||
|
PalCode,
|
||||||
|
}
|
||||||
|
|
||||||
/** Base address of the memory region. */
|
/** Base address of the memory region. */
|
||||||
ulong base;
|
ulong base;
|
||||||
/** Size in bytes of the memory region. */
|
/** Size in bytes of the memory region. */
|
||||||
@ -42,7 +54,7 @@ struct BootInfo
|
|||||||
Framebuffer fb;
|
Framebuffer fb;
|
||||||
|
|
||||||
/* Memory map. */
|
/* Memory map. */
|
||||||
MemoryRegion[800] memory_map;
|
MemoryRegion[1000] memory_map;
|
||||||
|
|
||||||
/* Number of memory map entries. */
|
/* Number of memory map entries. */
|
||||||
size_t memory_map_count;
|
size_t memory_map_count;
|
||||||
@ -53,8 +65,8 @@ struct BootInfo
|
|||||||
/* Physical address used for HULK bss section. */
|
/* Physical address used for HULK bss section. */
|
||||||
ulong bss_phys;
|
ulong bss_phys;
|
||||||
|
|
||||||
/* Size of HULK bss region. */
|
/* Physical address of stack while jumping to HULK. */
|
||||||
ulong bss_size;
|
ulong stack_phys;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** HULK base virtual address. */
|
/** HULK base virtual address. */
|
||||||
|
@ -20,4 +20,7 @@ struct Header
|
|||||||
|
|
||||||
/** Entry point. */
|
/** Entry point. */
|
||||||
void * entry;
|
void * entry;
|
||||||
|
|
||||||
|
/** Stack size. */
|
||||||
|
ulong stack_size;
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ extern extern(C) __gshared ubyte _hulk_total_size;
|
|||||||
private __gshared Header hulk_header = {
|
private __gshared Header hulk_header = {
|
||||||
&_hulk_total_size,
|
&_hulk_total_size,
|
||||||
&hulk_start,
|
&hulk_start,
|
||||||
|
16u * 1024u,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
x
Reference in New Issue
Block a user