95 lines
1.8 KiB
C++
95 lines
1.8 KiB
C++
#include "error.h"
|
|
#include "console.h"
|
|
|
|
namespace boot {
|
|
namespace error {
|
|
|
|
handler *handler::s_current = nullptr;
|
|
|
|
struct error_code_desc {
|
|
uefi::status code;
|
|
const wchar_t *name;
|
|
};
|
|
|
|
struct error_code_desc error_table[] = {
|
|
#define STATUS_ERROR(name, num) { uefi::status::name, L#name },
|
|
#define STATUS_WARNING(name, num) { uefi::status::name, L#name },
|
|
#include "uefi/errors.inc"
|
|
#undef STATUS_ERROR
|
|
#undef STATUS_WARNING
|
|
{ uefi::status::success, nullptr }
|
|
};
|
|
|
|
static const wchar_t *
|
|
error_message(uefi::status status)
|
|
{
|
|
int32_t i = -1;
|
|
while (error_table[++i].name != nullptr) {
|
|
if (error_table[i].code == status) return error_table[i].name;
|
|
}
|
|
|
|
if (uefi::is_error(status))
|
|
return L"Unknown Error";
|
|
else
|
|
return L"Unknown Warning";
|
|
}
|
|
|
|
[[ noreturn ]] void
|
|
raise(uefi::status status, const wchar_t *message)
|
|
{
|
|
if (handler::s_current) {
|
|
handler::s_current->handle(status, message);
|
|
}
|
|
while (1) asm("hlt");
|
|
}
|
|
|
|
handler::handler() :
|
|
m_next(s_current)
|
|
{
|
|
s_current = this;
|
|
}
|
|
|
|
handler::~handler()
|
|
{
|
|
if (s_current != this)
|
|
raise(uefi::status::warn_stale_data,
|
|
L"Non-current error handler destructing");
|
|
s_current = m_next;
|
|
}
|
|
|
|
uefi_handler::uefi_handler(console &con) :
|
|
handler(),
|
|
m_con(con)
|
|
{
|
|
}
|
|
|
|
[[ noreturn ]] void
|
|
uefi_handler::handle(uefi::status s, const wchar_t *message)
|
|
{
|
|
status_line::fail(message, error_message(s));
|
|
while (1) asm("hlt");
|
|
}
|
|
|
|
cpu_assert_handler::cpu_assert_handler() : handler() {}
|
|
|
|
[[ noreturn ]] void
|
|
cpu_assert_handler::handle(uefi::status s, const wchar_t *message)
|
|
{
|
|
asm volatile (
|
|
"movq $0xeeeeeeebadbadbad, %%r8;"
|
|
"movq %0, %%r9;"
|
|
"movq $0, %%rdx;"
|
|
"divq %%rdx;"
|
|
:
|
|
: "r"((uint64_t)s)
|
|
: "rax", "rdx", "r8", "r9");
|
|
while (1) asm("hlt");
|
|
}
|
|
|
|
} // namespace error
|
|
} // namespace boot
|
|
|
|
extern "C" int _purecall() { ::boot::error::raise(uefi::status::unsupported, L"Pure virtual call"); }
|
|
void operator delete (void *) {}
|
|
|