diff --git a/src/boot/error.cpp b/src/boot/error.cpp index eaf220c..3af8f9b 100644 --- a/src/boot/error.cpp +++ b/src/boot/error.cpp @@ -35,27 +35,28 @@ message(uefi::status status) } [[ 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 ( "movq $0xeeeeeeebadbadbad, %%r8;" "movq %0, %%r9;" "movq %1, %%r10;" + "movq %2, %%r11;" "movq $0, %%rdx;" "divq %%rdx;" : - : "r"((uint64_t)s), "r"(message) + : "r"((uint64_t)s), "r"(message), "r"(line) : "rax", "rdx", "r8", "r9", "r10"); while (1) asm("hlt"); } [[ 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)) while (1) asm("hlt"); else - cpu_assert(status, message); + cpu_assert(status, message, line); } diff --git a/src/boot/error.h b/src/boot/error.h index a39ec13..6ce90ad 100644 --- a/src/boot/error.h +++ b/src/boot/error.h @@ -12,7 +12,7 @@ class console; namespace error { /// 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); @@ -28,6 +28,6 @@ void debug_break(); #define try_or_raise(s, m) \ do { \ 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) diff --git a/src/boot/main.cpp b/src/boot/main.cpp index f48e3b8..7021340 100644 --- a/src/boot/main.cpp +++ b/src/boot/main.cpp @@ -163,7 +163,7 @@ uefi_preboot(uefi::handle image, uefi::system_table *st) memory::efi_mem_map 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::build_kernel_mem_map(args, bs); diff --git a/src/boot/paging.cpp b/src/boot/paging.cpp index b1423fb..9675d08 100644 --- a/src/boot/paging.cpp +++ b/src/boot/paging.cpp @@ -118,7 +118,7 @@ private: if (!(parent_ent & 1)) { 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(m_page_cache); m_page_cache = offset_ptr(m_page_cache, page_size); diff --git a/src/boot/status.cpp b/src/boot/status.cpp index b8170c3..aeeab20 100644 --- a/src/boot/status.cpp +++ b/src/boot/status.cpp @@ -30,7 +30,8 @@ status *status::s_current = nullptr; unsigned status::s_current_type = 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_depth(0), 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(fb.size), m_outer(nullptr) { m_size = (fb.vertical / num_boxes) - 1; diff --git a/src/boot/status.h b/src/boot/status.h index 04132e1..0c94fca 100644 --- a/src/boot/status.h +++ b/src/boot/status.h @@ -17,6 +17,8 @@ namespace boot { class status { 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_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) { if (!s_current) return false; 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 @@ -39,12 +41,15 @@ public: inline static bool fail(const wchar_t *message, uefi::status status) { if (!s_current) return false; s_current->do_fail(message, status); - return true; + return s_current->m_fails_clean; } protected: static status *s_current; static unsigned s_current_type; + +private: + bool m_fails_clean; }; /// Scoped status line reporter. Prints a message and an "OK" if no errors @@ -59,7 +64,11 @@ public: /// Constructor. /// \arg message Description of the operation in progress /// \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(); virtual void do_warn(const wchar_t *message, uefi::status status) override;