mirror of
https://github.com/justinian/jsix.git
synced 2025-12-10 00:14:32 -08:00
[boot] Fix call to exit_boot_services
Exiting boot services can't actually be done from inside `bootloader_uefi_main`, because there are objects in that scope that run code requiring boot services in their destructors. Also added `support.cpp` with `memcpy` because clang will emit references to `memcpy` even in freestanding mode. Added a `debug_break` function to allow for faking breakpoints when connecting to the bootloader with GDB. Tags: debug
This commit is contained in:
@@ -62,6 +62,7 @@ modules:
|
|||||||
- src/boot/hardware.cpp
|
- src/boot/hardware.cpp
|
||||||
- src/boot/loader.cpp
|
- src/boot/loader.cpp
|
||||||
- src/boot/memory.cpp
|
- src/boot/memory.cpp
|
||||||
|
- src/boot/support.cpp
|
||||||
|
|
||||||
nulldrv:
|
nulldrv:
|
||||||
kind: exe
|
kind: exe
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
{{ super() }}
|
{{ super() }}
|
||||||
|
|
||||||
ccflags = $ccflags $
|
ccflags = $ccflags $
|
||||||
|
-g3 $
|
||||||
-DKERNEL_FILENAME=L\"jsix.elf\" $
|
-DKERNEL_FILENAME=L\"jsix.elf\" $
|
||||||
-I${srcroot}/external/include $
|
-I${srcroot}/external/include $
|
||||||
-I${srcroot}/external/include/X64
|
-I${srcroot}/external/include/X64
|
||||||
|
|||||||
@@ -89,6 +89,8 @@ cpu_assert_handler::handle(uefi::status s, const wchar_t *message)
|
|||||||
} // namespace error
|
} // namespace error
|
||||||
} // namespace boot
|
} // namespace boot
|
||||||
|
|
||||||
extern "C" int _purecall() { ::boot::error::raise(uefi::status::unsupported, L"Pure virtual call"); }
|
void debug_break()
|
||||||
void operator delete (void *) {}
|
{
|
||||||
|
volatile int go = 0;
|
||||||
|
while (!go);
|
||||||
|
}
|
||||||
|
|||||||
@@ -58,6 +58,9 @@ public:
|
|||||||
} // namespace error
|
} // namespace error
|
||||||
} // namespace boot
|
} // namespace boot
|
||||||
|
|
||||||
|
/// Debugging psuedo-breakpoint.
|
||||||
|
void debug_break();
|
||||||
|
|
||||||
/// Helper macro to raise an error if an operation fails.
|
/// Helper macro to raise an error if an operation fails.
|
||||||
/// \arg s An expression evaluating to a UEFI status
|
/// \arg s An expression evaluating to a UEFI status
|
||||||
/// \arg m The error message to use on failure
|
/// \arg m The error message to use on failure
|
||||||
|
|||||||
@@ -144,7 +144,7 @@ load_module(
|
|||||||
/// UEFI is still in control of the machine. (ie, while the loader still
|
/// UEFI is still in control of the machine. (ie, while the loader still
|
||||||
/// has access to boot services.
|
/// has access to boot services.
|
||||||
loader::loaded_elf
|
loader::loaded_elf
|
||||||
bootloader_main_uefi(uefi::handle image, uefi::system_table *st, console &con)
|
bootloader_main_uefi(uefi::handle image, uefi::system_table *st, console &con, size_t *map_key)
|
||||||
{
|
{
|
||||||
error::uefi_handler handler(con);
|
error::uefi_handler handler(con);
|
||||||
|
|
||||||
@@ -174,6 +174,9 @@ bootloader_main_uefi(uefi::handle image, uefi::system_table *st, console &con)
|
|||||||
memory::efi_mem_map efi_map = memory::get_uefi_mappings(bs);
|
memory::efi_mem_map efi_map = memory::get_uefi_mappings(bs);
|
||||||
memory::build_kernel_mem_map(efi_map, args, bs);
|
memory::build_kernel_mem_map(efi_map, args, bs);
|
||||||
|
|
||||||
|
efi_map = memory::get_uefi_mappings(bs);
|
||||||
|
*map_key = efi_map.key;
|
||||||
|
|
||||||
return kernel_elf;
|
return kernel_elf;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -288,10 +291,15 @@ efi_main(uefi::handle image_handle, uefi::system_table *st)
|
|||||||
error::cpu_assert_handler handler;
|
error::cpu_assert_handler handler;
|
||||||
console con(st->boot_services, st->con_out);
|
console con(st->boot_services, st->con_out);
|
||||||
|
|
||||||
|
size_t map_key;
|
||||||
loader::loaded_elf kernel =
|
loader::loaded_elf kernel =
|
||||||
bootloader_main_uefi(image_handle, st, con);
|
bootloader_main_uefi(image_handle, st, con, &map_key);
|
||||||
|
|
||||||
while(1);
|
try_or_raise(
|
||||||
|
st->boot_services->exit_boot_services(image_handle, map_key),
|
||||||
|
L"Failed to exit boot services");
|
||||||
|
|
||||||
|
debug_break();
|
||||||
return uefi::status::unsupported;
|
return uefi::status::unsupported;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -67,6 +67,8 @@ init_pointer_fixup(uefi::boot_services *bs, uefi::runtime_services *rs)
|
|||||||
status_line status(L"Initializing pointer virtualization event");
|
status_line status(L"Initializing pointer virtualization event");
|
||||||
|
|
||||||
uefi::event event;
|
uefi::event event;
|
||||||
|
bs->set_mem(&fixup_pointers, sizeof(fixup_pointers), 0);
|
||||||
|
fixup_pointer_index = 0;
|
||||||
|
|
||||||
try_or_raise(
|
try_or_raise(
|
||||||
bs->create_event(
|
bs->create_event(
|
||||||
|
|||||||
27
src/boot/support.cpp
Normal file
27
src/boot/support.cpp
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "error.h"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
/// Basic memcpy() implementation for clang. Clang requires freestanding code
|
||||||
|
/// implement memcpy(), as it may emit references to it. This basic memcpy is
|
||||||
|
/// not the most efficient, but will get linked if no other memcpy exists.
|
||||||
|
__attribute__ ((__weak__))
|
||||||
|
void *memcpy(void *dest, const void *src, size_t n)
|
||||||
|
{
|
||||||
|
uint8_t *cdest = reinterpret_cast<uint8_t*>(dest);
|
||||||
|
const uint8_t *csrc = reinterpret_cast<const uint8_t*>(src);
|
||||||
|
for (size_t i = 0; i < n; ++i)
|
||||||
|
cdest[i] = csrc[i];
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _purecall()
|
||||||
|
{
|
||||||
|
::boot::error::raise(uefi::status::unsupported, L"Pure virtual call");
|
||||||
|
}
|
||||||
|
|
||||||
|
} // extern "C"
|
||||||
|
|
||||||
|
void operator delete (void *) {}
|
||||||
Reference in New Issue
Block a user