[boot] Improve non-printing error handling
Add an implicit __LINE__ to the try_or_raise macro, which gets set in r11 on cpu_assert. Also made status lines smarter about when to call cpu_assert.
This commit is contained in:
@@ -35,27 +35,28 @@ message(uefi::status status)
|
|||||||
}
|
}
|
||||||
|
|
||||||
[[ noreturn ]] static void
|
[[ noreturn ]] static void
|
||||||
cpu_assert(uefi::status s, const wchar_t *message)
|
cpu_assert(uefi::status s, const wchar_t *message, size_t line)
|
||||||
{
|
{
|
||||||
asm volatile (
|
asm volatile (
|
||||||
"movq $0xeeeeeeebadbadbad, %%r8;"
|
"movq $0xeeeeeeebadbadbad, %%r8;"
|
||||||
"movq %0, %%r9;"
|
"movq %0, %%r9;"
|
||||||
"movq %1, %%r10;"
|
"movq %1, %%r10;"
|
||||||
|
"movq %2, %%r11;"
|
||||||
"movq $0, %%rdx;"
|
"movq $0, %%rdx;"
|
||||||
"divq %%rdx;"
|
"divq %%rdx;"
|
||||||
:
|
:
|
||||||
: "r"((uint64_t)s), "r"(message)
|
: "r"((uint64_t)s), "r"(message), "r"(line)
|
||||||
: "rax", "rdx", "r8", "r9", "r10");
|
: "rax", "rdx", "r8", "r9", "r10");
|
||||||
while (1) asm("hlt");
|
while (1) asm("hlt");
|
||||||
}
|
}
|
||||||
|
|
||||||
[[ noreturn ]] void
|
[[ noreturn ]] void
|
||||||
raise(uefi::status status, const wchar_t *message)
|
raise(uefi::status status, const wchar_t *message, size_t line)
|
||||||
{
|
{
|
||||||
if(status_line::fail(message, status))
|
if(status_line::fail(message, status))
|
||||||
while (1) asm("hlt");
|
while (1) asm("hlt");
|
||||||
else
|
else
|
||||||
cpu_assert(status, message);
|
cpu_assert(status, message, line);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ class console;
|
|||||||
namespace error {
|
namespace error {
|
||||||
|
|
||||||
/// Halt or exit the program with the given error status/message
|
/// Halt or exit the program with the given error status/message
|
||||||
[[ noreturn ]] void raise(uefi::status status, const wchar_t *message);
|
[[ noreturn ]] void raise(uefi::status status, const wchar_t *message, size_t line = 0);
|
||||||
|
|
||||||
const wchar_t * message(uefi::status status);
|
const wchar_t * message(uefi::status status);
|
||||||
|
|
||||||
@@ -28,6 +28,6 @@ void debug_break();
|
|||||||
#define try_or_raise(s, m) \
|
#define try_or_raise(s, m) \
|
||||||
do { \
|
do { \
|
||||||
uefi::status _s = (s); \
|
uefi::status _s = (s); \
|
||||||
if (uefi::is_error(_s)) ::boot::error::raise(_s, (m)); \
|
if (uefi::is_error(_s)) ::boot::error::raise(_s, (m), __LINE__); \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
|
|||||||
@@ -163,7 +163,7 @@ uefi_preboot(uefi::handle image, uefi::system_table *st)
|
|||||||
memory::efi_mem_map
|
memory::efi_mem_map
|
||||||
uefi_exit(args::header *args, uefi::handle image, uefi::boot_services *bs)
|
uefi_exit(args::header *args, uefi::handle image, uefi::boot_services *bs)
|
||||||
{
|
{
|
||||||
status_line status {L"Exiting UEFI"};
|
status_line status {L"Exiting UEFI", nullptr, false};
|
||||||
|
|
||||||
memory::efi_mem_map map =
|
memory::efi_mem_map map =
|
||||||
memory::build_kernel_mem_map(args, bs);
|
memory::build_kernel_mem_map(args, bs);
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ private:
|
|||||||
|
|
||||||
if (!(parent_ent & 1)) {
|
if (!(parent_ent & 1)) {
|
||||||
if (!m_cache_count--)
|
if (!m_cache_count--)
|
||||||
error::raise(uefi::status::out_of_resources, L"Page table cache empty");
|
error::raise(uefi::status::out_of_resources, L"Page table cache empty", 0x7ab1e5);
|
||||||
|
|
||||||
page_table *table = reinterpret_cast<page_table*>(m_page_cache);
|
page_table *table = reinterpret_cast<page_table*>(m_page_cache);
|
||||||
m_page_cache = offset_ptr<void>(m_page_cache, page_size);
|
m_page_cache = offset_ptr<void>(m_page_cache, page_size);
|
||||||
|
|||||||
@@ -30,7 +30,8 @@ status *status::s_current = nullptr;
|
|||||||
unsigned status::s_current_type = 0;
|
unsigned status::s_current_type = 0;
|
||||||
unsigned status_bar::s_count = 0;
|
unsigned status_bar::s_count = 0;
|
||||||
|
|
||||||
status_line::status_line(const wchar_t *message, const wchar_t *context) :
|
status_line::status_line(const wchar_t *message, const wchar_t *context, bool fails_clean) :
|
||||||
|
status(fails_clean),
|
||||||
m_level(level_ok),
|
m_level(level_ok),
|
||||||
m_depth(0),
|
m_depth(0),
|
||||||
m_outer(nullptr)
|
m_outer(nullptr)
|
||||||
@@ -148,6 +149,7 @@ status_line::do_fail(const wchar_t *message, uefi::status status)
|
|||||||
|
|
||||||
|
|
||||||
status_bar::status_bar(kernel::args::framebuffer const &fb) :
|
status_bar::status_bar(kernel::args::framebuffer const &fb) :
|
||||||
|
status(fb.size),
|
||||||
m_outer(nullptr)
|
m_outer(nullptr)
|
||||||
{
|
{
|
||||||
m_size = (fb.vertical / num_boxes) - 1;
|
m_size = (fb.vertical / num_boxes) - 1;
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ namespace boot {
|
|||||||
class status
|
class status
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
status(bool fails_clean = true) : m_fails_clean(fails_clean) {}
|
||||||
|
|
||||||
virtual void do_warn(const wchar_t *message, uefi::status status) = 0;
|
virtual void do_warn(const wchar_t *message, uefi::status status) = 0;
|
||||||
virtual void do_fail(const wchar_t *message, uefi::status status) = 0;
|
virtual void do_fail(const wchar_t *message, uefi::status status) = 0;
|
||||||
|
|
||||||
@@ -28,7 +30,7 @@ public:
|
|||||||
inline static bool warn(const wchar_t *message, uefi::status status = uefi::status::success) {
|
inline static bool warn(const wchar_t *message, uefi::status status = uefi::status::success) {
|
||||||
if (!s_current) return false;
|
if (!s_current) return false;
|
||||||
s_current->do_warn(message, status);
|
s_current->do_warn(message, status);
|
||||||
return true;
|
return s_current->m_fails_clean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the state to error, and print a message. If the state is already at
|
/// Set the state to error, and print a message. If the state is already at
|
||||||
@@ -39,12 +41,15 @@ public:
|
|||||||
inline static bool fail(const wchar_t *message, uefi::status status) {
|
inline static bool fail(const wchar_t *message, uefi::status status) {
|
||||||
if (!s_current) return false;
|
if (!s_current) return false;
|
||||||
s_current->do_fail(message, status);
|
s_current->do_fail(message, status);
|
||||||
return true;
|
return s_current->m_fails_clean;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static status *s_current;
|
static status *s_current;
|
||||||
static unsigned s_current_type;
|
static unsigned s_current_type;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_fails_clean;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Scoped status line reporter. Prints a message and an "OK" if no errors
|
/// Scoped status line reporter. Prints a message and an "OK" if no errors
|
||||||
@@ -59,7 +64,11 @@ public:
|
|||||||
/// Constructor.
|
/// Constructor.
|
||||||
/// \arg message Description of the operation in progress
|
/// \arg message Description of the operation in progress
|
||||||
/// \arg context If non-null, printed after `message` and a colon
|
/// \arg context If non-null, printed after `message` and a colon
|
||||||
status_line(const wchar_t *message, const wchar_t *context = nullptr);
|
/// \arg fails_clean If true, this object can handle printing failure
|
||||||
|
status_line(
|
||||||
|
const wchar_t *message,
|
||||||
|
const wchar_t *context = nullptr,
|
||||||
|
bool fails_clean = true);
|
||||||
~status_line();
|
~status_line();
|
||||||
|
|
||||||
virtual void do_warn(const wchar_t *message, uefi::status status) override;
|
virtual void do_warn(const wchar_t *message, uefi::status status) override;
|
||||||
|
|||||||
Reference in New Issue
Block a user