stivale: Implement higher half returned addresses flag
diff --git a/stage23/protos/stivale.32.c b/stage23/protos/stivale.32.c
index 2f24f19b..346cad0d 100644
--- a/stage23/protos/stivale.32.c
+++ b/stage23/protos/stivale.32.c
@@ -6,11 +6,13 @@
__attribute__((noreturn)) void stivale_spinup_32(
int bits, bool level5pg, uint32_t pagemap_top_lv,
uint32_t entry_point_lo, uint32_t entry_point_hi,
- void *stivale_struct, uint32_t stack_lo, uint32_t stack_hi) {
- uint64_t entry_point =
- (uint64_t)entry_point_lo | ((uint64_t)entry_point_hi << 32);
- uint64_t stack =
- (uint64_t)stack_lo | ((uint64_t)stack_hi << 32);
+ uint32_t stivale_struct_lo, uint32_t stivale_struct_hi,
+ uint32_t stack_lo, uint32_t stack_hi) {
+ uint64_t casted_to_64[] = {
+ (uint64_t)stivale_struct_lo | ((uint64_t)stivale_struct_hi << 32),
+ (uint64_t)entry_point_lo | ((uint64_t)entry_point_hi << 32),
+ (uint64_t)stack_lo | ((uint64_t)stack_hi << 32)
+ };
if (bits == 64) {
if (level5pg) {
@@ -52,14 +54,15 @@ __attribute__((noreturn)) void stivale_spinup_32(
// Since we don't really know what is now present in the upper
// 32 bits of the 64 bit registers, clear up the upper bits
- // of the registers we use to store stack pointer and instruction
- // pointer
+ // of the register that points to the 64-bit casted value array.
"mov esi, esi\n\t"
- "mov ebx, ebx\n\t"
- "mov edi, edi\n\t"
+
+ // Move in 64-bit values
+ "mov rdi, qword ptr [rsi + 0]\n\t"
+ "mov rbx, qword ptr [rsi + 8]\n\t"
+ "mov rsi, qword ptr [rsi + 16]\n\t"
// Let's pretend we push a return address
- "mov rsi, qword ptr [rsi]\n\t"
"test rsi, rsi\n\t"
"jz 1f\n\t"
@@ -71,7 +74,7 @@ __attribute__((noreturn)) void stivale_spinup_32(
"push rsi\n\t"
"pushfq\n\t"
"push 0x28\n\t"
- "push [rbx]\n\t"
+ "push rbx\n\t"
"xor rax, rax\n\t"
"xor rbx, rbx\n\t"
@@ -91,8 +94,7 @@ __attribute__((noreturn)) void stivale_spinup_32(
"iretq\n\t"
".code32\n\t"
:
- : "a" (pagemap_top_lv), "b" (&entry_point),
- "D" (stivale_struct), "S" (&stack)
+ : "a" (pagemap_top_lv), "S" (casted_to_64)
: "memory"
);
} else if (bits == 32) {
@@ -100,13 +102,13 @@ __attribute__((noreturn)) void stivale_spinup_32(
"cli\n\t"
"cld\n\t"
- "mov esp, dword ptr [esi]\n\t"
+ "mov esp, esi\n\t"
"push edi\n\t"
"push 0\n\t"
"pushfd\n\t"
"push 0x18\n\t"
- "push [ebx]\n\t"
+ "push ebx\n\t"
"xor eax, eax\n\t"
"xor ebx, ebx\n\t"
@@ -118,7 +120,9 @@ __attribute__((noreturn)) void stivale_spinup_32(
"iret\n\t"
:
- : "b"(&entry_point), "D"(stivale_struct), "S"(&stack)
+ : "D" ((uint32_t)casted_to_64[0]),
+ "b" ((uint32_t)casted_to_64[1]),
+ "S" ((uint32_t)casted_to_64[2])
: "memory"
);
}
diff --git a/stage23/protos/stivale.c b/stage23/protos/stivale.c
index 64eb2d0d..0e606c2c 100644
--- a/stage23/protos/stivale.c
+++ b/stage23/protos/stivale.c
@@ -22,6 +22,10 @@
#include <stivale/stivale.h>
#include <drivers/vga_textmode.h>
+#define REPORTED_ADDR(PTR) \
+ ((PTR) + ((stivale_hdr.flags & (1 << 3)) ? \
+ (want_5lv ? 0xff00000000000000 : 0xffff800000000000) : 0))
+
struct stivale_struct stivale_struct = {0};
void stivale_load(char *config, char *cmdline) {
@@ -105,6 +109,9 @@ void stivale_load(char *config, char *cmdline) {
panic("stivale: Section .stivalehdr is smaller than size of the struct.");
}
+ bool want_5lv = level5pg && (stivale_hdr.flags & (1 << 1));
+ pagemap_t pagemap = stivale_build_pagemap(want_5lv, false);
+
if (stivale_hdr.entry_point != 0)
entry_point = stivale_hdr.entry_point;
@@ -141,11 +148,11 @@ void stivale_load(char *config, char *cmdline) {
if (!uri_open(&f, module_path))
panic("Requested module with path \"%s\" not found!", module_path);
- m->begin = (uint64_t)(size_t)freadall(&f, STIVALE_MMAP_KERNEL_AND_MODULES);
+ m->begin = REPORTED_ADDR((uint64_t)(size_t)freadall(&f, STIVALE_MMAP_KERNEL_AND_MODULES));
m->end = m->begin + f.size;
m->next = 0;
- *prev_mod_ptr = (uint64_t)(size_t)m;
+ *prev_mod_ptr = REPORTED_ADDR((uint64_t)(size_t)m);
prev_mod_ptr = &m->next;
print("stivale: Requested module %u:\n", i);
@@ -155,12 +162,20 @@ void stivale_load(char *config, char *cmdline) {
print(" End: %X\n", m->end);
}
- stivale_struct.rsdp = (uint64_t)(size_t)acpi_get_rsdp();
+ uint64_t rsdp = (uint64_t)(size_t)acpi_get_rsdp();
+
+ if (rsdp)
+ stivale_struct.rsdp = REPORTED_ADDR(rsdp);
- acpi_get_smbios((void **)&stivale_struct.smbios_entry_32,
- (void **)&stivale_struct.smbios_entry_64);
+ uint64_t smbios_entry_32 = 0, smbios_entry_64 = 0;
+ acpi_get_smbios((void **)&smbios_entry_32, (void **)&smbios_entry_64);
- stivale_struct.cmdline = (uint64_t)(size_t)cmdline;
+ if (smbios_entry_32)
+ stivale_struct.smbios_entry_32 = REPORTED_ADDR(smbios_entry_32);
+ if (smbios_entry_64)
+ stivale_struct.smbios_entry_64 = REPORTED_ADDR(smbios_entry_64);
+
+ stivale_struct.cmdline = REPORTED_ADDR((uint64_t)(size_t)cmdline);
stivale_struct.epoch = time();
print("stivale: Current epoch: %U\n", stivale_struct.epoch);
@@ -184,7 +199,7 @@ void stivale_load(char *config, char *cmdline) {
(uint64_t)fbinfo.framebuffer_pitch * fbinfo.framebuffer_height,
MEMMAP_FRAMEBUFFER, false, false, false, true);
- stivale_struct.framebuffer_addr = (uint64_t)fbinfo.framebuffer_addr;
+ stivale_struct.framebuffer_addr = REPORTED_ADDR((uint64_t)fbinfo.framebuffer_addr);
stivale_struct.framebuffer_width = fbinfo.framebuffer_width;
stivale_struct.framebuffer_height = fbinfo.framebuffer_height;
stivale_struct.framebuffer_bpp = fbinfo.framebuffer_bpp;
@@ -209,9 +224,6 @@ void stivale_load(char *config, char *cmdline) {
efi_exit_boot_services();
#endif
- bool want_5lv = level5pg && (stivale_hdr.flags & (1 << 1));
- pagemap_t pagemap = stivale_build_pagemap(want_5lv, false);
-
// Reserve 32K at 0x70000
memmap_alloc_range(0x70000, 0x8000, MEMMAP_USABLE, true, true, false, false);
@@ -219,10 +231,11 @@ void stivale_load(char *config, char *cmdline) {
struct e820_entry_t *memmap = get_memmap(&memmap_entries);
stivale_struct.memory_map_entries = (uint64_t)memmap_entries;
- stivale_struct.memory_map_addr = (uint64_t)(size_t)memmap;
+ stivale_struct.memory_map_addr = REPORTED_ADDR((uint64_t)(size_t)memmap);
stivale_spinup(bits, want_5lv, &pagemap,
- entry_point, &stivale_struct, stivale_hdr.stack);
+ entry_point, REPORTED_ADDR((uint64_t)(uintptr_t)&stivale_struct),
+ stivale_hdr.stack);
}
pagemap_t stivale_build_pagemap(bool level5pg, bool unmap_null) {
@@ -286,11 +299,12 @@ extern symbol ImageBase;
__attribute__((noreturn)) void stivale_spinup_32(
int bits, bool level5pg, uint32_t pagemap_top_lv,
uint32_t entry_point_lo, uint32_t entry_point_hi,
- void *stivale_struct, uint32_t stack_lo, uint32_t stack_hi);
+ uint32_t stivale_struct_lo, uint32_t stivale_struct_hi,
+ uint32_t stack_lo, uint32_t stack_hi);
__attribute__((noreturn)) void stivale_spinup(
int bits, bool level5pg, pagemap_t *pagemap,
- uint64_t entry_point, void *stivale_struct, uint64_t stack) {
+ uint64_t entry_point, uint64_t stivale_struct, uint64_t stack) {
#if defined (bios)
if (bits == 64) {
// If we're going 64, we might as well call this BIOS interrupt
@@ -307,17 +321,17 @@ __attribute__((noreturn)) void stivale_spinup(
pic_flush();
#if defined (uefi)
- do_32(stivale_spinup_32, 8,
+ do_32(stivale_spinup_32, 9,
bits, level5pg, (uint32_t)(uintptr_t)pagemap->top_level,
(uint32_t)entry_point, (uint32_t)(entry_point >> 32),
- stivale_struct,
+ (uint32_t)stivale_struct, (uint32_t)(stivale_struct >> 32),
(uint32_t)stack, (uint32_t)(stack >> 32));
#endif
#if defined (bios)
stivale_spinup_32(bits, level5pg, (uint32_t)(uintptr_t)pagemap->top_level,
(uint32_t)entry_point, (uint32_t)(entry_point >> 32),
- stivale_struct,
+ (uint32_t)stivale_struct, (uint32_t)(stivale_struct >> 32),
(uint32_t)stack, (uint32_t)(stack >> 32));
#endif
diff --git a/stage23/protos/stivale.h b/stage23/protos/stivale.h
index 45cd8fef..b1983b61 100644
--- a/stage23/protos/stivale.h
+++ b/stage23/protos/stivale.h
@@ -11,6 +11,6 @@ void stivale_load(char *config, char *cmdline);
pagemap_t stivale_build_pagemap(bool level5pg, bool unmap_null);
__attribute__((noreturn)) void stivale_spinup(
int bits, bool level5pg, pagemap_t *pagemap,
- uint64_t entry_point, void *stivale_struct, uint64_t stack);
+ uint64_t entry_point, uint64_t stivale_struct, uint64_t stack);
#endif
diff --git a/stage23/protos/stivale2.c b/stage23/protos/stivale2.c
index abf4a908..c859fe9d 100644
--- a/stage23/protos/stivale2.c
+++ b/stage23/protos/stivale2.c
@@ -494,5 +494,5 @@ skip_modeset:;
term_write("\e[2J\e[H", 7);
stivale_spinup(bits, level5pg && level5pg_requested, &pagemap,
- entry_point, &stivale2_struct, stivale2_hdr.stack);
+ entry_point, (uint64_t)(uintptr_t)&stivale2_struct, stivale2_hdr.stack);
}
diff --git a/test/stivale.c b/test/stivale.c
index d3b80a63..89133092 100644
--- a/test/stivale.c
+++ b/test/stivale.c
@@ -12,12 +12,13 @@ struct stivale_header header = {
.framebuffer_bpp = 0,
.framebuffer_width = 0,
.framebuffer_height = 0,
- .flags = 1,
+ .flags = 1 | (1 << 3),
.entry_point = (uint64_t)(uintptr_t)stivale_main
};
void stivale_main(struct stivale_struct *info) {
- // Print some info.
+ e9_printf("Stivale struct at %x", info);
+
e9_puts("Stivale information passed to the kernel:");
e9_printf("Cmdline: %s", (char*)info->cmdline);
e9_printf("Memory map at %x with contents:", info->memory_map_addr);
@@ -55,7 +56,7 @@ void stivale_main(struct stivale_struct *info) {
struct stivale_module *modules = ((struct stivale_module *)(info->modules));
for (size_t i = 0; i < info->module_count; i++) {
struct stivale_module e = *modules;
- e9_printf("\tModule %d: [%x+%x] %s", i, e.begin, e.end, e.string);
+ e9_printf("\tModule %d: [%x->%x] %s", i, e.begin, e.end, e.string);
modules = (struct stivale_module *)e.next;
}
