diff --git a/src/boot/console.cpp b/src/boot/console.cpp index 5571fac..ab4d38b 100644 --- a/src/boot/console.cpp +++ b/src/boot/console.cpp @@ -22,7 +22,19 @@ static constexpr int level_ok = 0; static constexpr int level_warn = 1; static constexpr int level_fail = 2; +static const wchar_t *level_tags[] = { + L" ok ", + L" warn ", + L"failed" +}; +static const uefi::attribute level_colors[] = { + uefi::attribute::green, + uefi::attribute::brown, + uefi::attribute::light_red +}; + console *console::s_console = nullptr; +status_line *status_line::s_current = nullptr; static const wchar_t digits[] = {u'0', u'1', u'2', u'3', u'4', u'5', u'6', u'7', u'8', u'9', u'a', u'b', u'c', u'd', u'e', u'f'}; @@ -30,8 +42,6 @@ static const wchar_t digits[] = {u'0', u'1', u'2', u'3', u'4', u'5', console::console(uefi::boot_services *bs, uefi::protos::simple_text_output *out) : m_rows(0), m_cols(0), - m_status_level(0), - m_status_line(0), m_out(out) { pick_mode(bs); @@ -253,98 +263,113 @@ console::print(const wchar_t *fmt, ...) return result; } -void -console::status_begin(const wchar_t *message) +status_line::status_line(const wchar_t *message) : + m_level(level_ok) { - m_status_line = m_out->mode->cursor_row; - m_status_level = level_ok; + auto out = console::get().m_out; + m_line = out->mode->cursor_row; + m_depth = (s_current ? 1 + s_current->m_depth : 0); - m_out->set_cursor_position(0, m_status_line); - m_out->set_attribute(uefi::attribute::light_gray); - m_out->output_string(message); - m_out->output_string(L"\r\n"); + int indent = 2 * m_depth; + out->set_cursor_position(indent, m_line); + out->set_attribute(uefi::attribute::light_gray); + out->output_string(message); + out->output_string(L"\r\n"); + + m_next = s_current; + s_current = this; +} + +status_line::~status_line() +{ + if (s_current != this) + error::raise(uefi::status::unsupported, L"Destroying non-current status_line"); + + finish(); + if (m_next && m_level > m_next->m_level) { + m_next->m_level = m_level; + m_next->print_status_tag(); + } + s_current = m_next; } void -console::status_end() +status_line::print_status_tag() { - if (m_status_level > level_ok) - return; + auto out = console::get().m_out; + int row = out->mode->cursor_row; + int col = out->mode->cursor_column; - int row = m_out->mode->cursor_row; - int col = m_out->mode->cursor_column; + uefi::attribute color = level_colors[m_level]; + const wchar_t *tag = level_tags[m_level]; - m_out->set_cursor_position(50, m_status_line); + out->set_cursor_position(50, m_line); - m_out->set_attribute(uefi::attribute::light_gray); - m_out->output_string(L"["); - m_out->set_attribute(uefi::attribute::green); - m_out->output_string(L" ok "); - m_out->set_attribute(uefi::attribute::light_gray); - m_out->output_string(L"]\r\n"); + out->set_attribute(uefi::attribute::light_gray); + out->output_string(L"["); + out->set_attribute(color); + out->output_string(tag); + out->set_attribute(uefi::attribute::light_gray); + out->output_string(L"]\r\n"); - m_out->set_cursor_position(col, row); + out->set_cursor_position(col, row); } void -console::status_warn(const wchar_t *message, const wchar_t *error) +status_line::do_warn(const wchar_t *message, const wchar_t *error) { - int row = m_out->mode->cursor_row; + auto out = console::get().m_out; + int row = out->mode->cursor_row; - if (m_status_level <= level_warn) { - m_status_level = level_warn; - - m_out->set_cursor_position(50, m_status_line); - - m_out->set_attribute(uefi::attribute::light_gray); - m_out->output_string(L"["); - m_out->set_attribute(uefi::attribute::brown); - m_out->output_string(L" warn "); - m_out->set_attribute(uefi::attribute::light_gray); - m_out->output_string(L"]"); + if (m_level < level_warn) { + m_level = level_warn; + print_status_tag(); } - m_out->set_cursor_position(4, row); - - m_out->set_attribute(uefi::attribute::yellow); - m_out->output_string(message); + int indent = 2 + 2 * m_depth; + out->set_cursor_position(indent, row); + out->set_attribute(uefi::attribute::yellow); + out->output_string(message); if (error) { - m_out->output_string(L": "); - m_out->output_string(error); + out->output_string(L": "); + out->output_string(error); } - m_out->set_attribute(uefi::attribute::light_gray); - m_out->output_string(L"\r\n"); + out->set_attribute(uefi::attribute::light_gray); + out->output_string(L"\r\n"); } void -console::status_fail(const wchar_t *message, const wchar_t *error) +status_line::do_fail(const wchar_t *message, const wchar_t *error) { - m_status_level = level_fail; + auto out = console::get().m_out; + int row = out->mode->cursor_row; - int row = m_out->mode->cursor_row; - m_out->set_cursor_position(50, m_status_line); - - m_out->set_attribute(uefi::attribute::light_gray); - m_out->output_string(L"["); - m_out->set_attribute(uefi::attribute::light_red); - m_out->output_string(L"failed"); - m_out->set_attribute(uefi::attribute::light_gray); - m_out->output_string(L"]"); - - m_out->set_cursor_position(4, row); - - m_out->set_attribute(uefi::attribute::red); - m_out->output_string(message); - - if (error) { - m_out->output_string(L": "); - m_out->output_string(error); + if (s_current->m_level < level_fail) { + m_level = level_fail; + print_status_tag(); } - m_out->set_attribute(uefi::attribute::light_gray); - m_out->output_string(L"\r\n"); + int indent = 2 + 2 * m_depth; + out->set_cursor_position(indent, row); + out->set_attribute(uefi::attribute::red); + out->output_string(message); + + if (error) { + out->output_string(L": "); + out->output_string(error); + } + + out->set_attribute(uefi::attribute::light_gray); + out->output_string(L"\r\n"); +} + +void +status_line::finish() +{ + if (m_level <= level_ok) + print_status_tag(); } /* diff --git a/src/boot/console.h b/src/boot/console.h index f54fac2..c5a70ad 100644 --- a/src/boot/console.h +++ b/src/boot/console.h @@ -11,11 +11,6 @@ class console public: console(uefi::boot_services *bs, uefi::protos::simple_text_output *out); - void status_begin(const wchar_t *message); - void status_warn(const wchar_t *message, const wchar_t *error=nullptr); - void status_fail(const wchar_t *message, const wchar_t *error=nullptr); - void status_end(); - size_t print_hex(uint32_t n) const; size_t print_dec(uint32_t n) const; size_t print_long_hex(uint64_t n) const; @@ -26,19 +21,45 @@ public: static size_t print(const wchar_t *fmt, ...); private: + friend class status_line; + void pick_mode(uefi::boot_services *bs); size_t vprintf(const wchar_t *fmt, va_list args) const; size_t m_rows, m_cols; - - int m_status_level; - int m_status_line; - uefi::protos::simple_text_output *m_out; static console *s_console; }; +class status_line +{ +public: + status_line(const wchar_t *message); + ~status_line(); + + inline static void warn(const wchar_t *message, const wchar_t *error=nullptr) { + if (s_current) s_current->do_warn(message, error); + } + + inline static void fail(const wchar_t *message, const wchar_t *error=nullptr) { + if (s_current) s_current->do_fail(message, error); + } + +private: + void print_status_tag(); + void do_warn(const wchar_t *message, const wchar_t *error); + void do_fail(const wchar_t *message, const wchar_t *error); + void finish(); + + size_t m_line; + int m_level; + int m_depth; + + status_line *m_next; + static status_line *s_current; +}; + uefi::status con_get_framebuffer( uefi::boot_services *bs, diff --git a/src/boot/error.cpp b/src/boot/error.cpp index c93ae65..18dcd5d 100644 --- a/src/boot/error.cpp +++ b/src/boot/error.cpp @@ -66,7 +66,7 @@ uefi_handler::uefi_handler(console &con) : [[ noreturn ]] void uefi_handler::handle(uefi::status s, const wchar_t *message) { - m_con.status_fail(message, error_message(s)); + status_line::fail(message, error_message(s)); while (1) asm("hlt"); } diff --git a/src/boot/main.cpp b/src/boot/main.cpp index f3a4c4d..d6d1e15 100644 --- a/src/boot/main.cpp +++ b/src/boot/main.cpp @@ -83,9 +83,11 @@ detect_debug_mode(EFI_RUNTIME_SERVICES *run, kernel_args *header) { } */ -uintptr_t +void * find_acpi_table(uefi::system_table *st) { + status_line status(L"Searching for ACPI table"); + // Find ACPI tables. Ignore ACPI 1.0 if a 2.0 table is found. uintptr_t acpi1_table = 0; @@ -94,7 +96,7 @@ find_acpi_table(uefi::system_table *st) // If we find an ACPI 2.0 table, return it immediately if (table->vendor_guid == uefi::vendor_guids::acpi2) - return reinterpret_cast(table->vendor_table); + return table->vendor_table; if (table->vendor_guid == uefi::vendor_guids::acpi1) { // Mark a v1 table with the LSB high @@ -103,7 +105,13 @@ find_acpi_table(uefi::system_table *st) } } - return acpi1_table; + if (!acpi1_table) { + error::raise(uefi::status::not_found, L"Could not find ACPI table"); + } else if (acpi1_table & 1) { + status_line::warn(L"Only found ACPI 1.0 table"); + } + + return reinterpret_cast(acpi1_table); } uefi::status @@ -114,53 +122,51 @@ bootloader_main_uefi(uefi::system_table *st, console &con) uefi::boot_services *bs = st->boot_services; uefi::runtime_services *rs = st->runtime_services; - con.status_begin(L"Initializing pointer fixup for virtualization"); memory::init_pointer_fixup(bs, rs); - con.status_end(); - con.status_begin(L"Searching for ACPI table"); - uintptr_t acpi_table = find_acpi_table(st); - if (!acpi_table) { - error::raise(uefi::status::not_found, L"Could not find ACPI table"); - } else if (acpi_table & 1) { - con.status_warn(L"Only found ACPI 1.0 table"); - } - con.status_end(); + void *acpi_table = find_acpi_table(st); - con.status_begin(L"Setting up kernel args memory"); kernel::args::header *args = nullptr; + kernel::args::module *modules = nullptr; - size_t args_size = - sizeof(kernel::args::header) + // The header itself - max_modules * sizeof(kernel::args::module); // The module structures + { + status_line status(L"Setting up kernel args memory"); - try_or_raise( - bs->allocate_pool( - uefi::memory_type::loader_data, - args_size, - reinterpret_cast(&args)), - L"Could not allocate argument memory"); + size_t args_size = + sizeof(kernel::args::header) + // The header itself + max_modules * sizeof(kernel::args::module); // The module structures - kernel::args::module *modules = - reinterpret_cast(args + 1); + try_or_raise( + bs->allocate_pool( + uefi::memory_type::loader_data, + args_size, + reinterpret_cast(&args)), + L"Could not allocate argument memory"); - args->magic = kernel::args::magic; - args->version = kernel::args::version; - args->runtime_services = rs; - args->acpi_table = reinterpret_cast(acpi_table); - args->modules = modules; - args->num_modules = 0; + modules = reinterpret_cast(args + 1); - con.status_end(); + args->magic = kernel::args::magic; + args->version = kernel::args::version; + args->runtime_services = rs; + args->acpi_table = reinterpret_cast(acpi_table); + args->modules = modules; + args->num_modules = 0; + } - con.status_begin(L"Loading initrd into memory"); - kernel::args::module &initrd = modules[args->num_modules++]; - initrd.type = kernel::args::type::initrd; - con.status_end(); + { + status_line status(L"Loading modules"); + { + status_line status(L"Finding boot device"); + } + { + status_line status(L"Loading initrd into memory"); + status_line::warn(L"I can't even"); + kernel::args::module &initrd = modules[args->num_modules++]; + initrd.type = kernel::args::type::initrd; + } + } - - while(1); return uefi::status::success; } @@ -290,6 +296,9 @@ efi_main(uefi::handle image_handle, uefi::system_table *st) error::cpu_assert_handler handler; console con(st->boot_services, st->con_out); - return bootloader_main_uefi(st, con); + /*return*/ bootloader_main_uefi(st, con); + + while(1); + return uefi::status::success; } diff --git a/src/boot/memory.cpp b/src/boot/memory.cpp index a827b83..3666c69 100644 --- a/src/boot/memory.cpp +++ b/src/boot/memory.cpp @@ -2,6 +2,7 @@ #include #include "error.h" +#include "console.h" #include "memory.h" #include "utility.h" @@ -71,6 +72,8 @@ update_marked_addresses(uefi::event, void *context) void init_pointer_fixup(uefi::boot_services *bs, uefi::runtime_services *rs) { + status_line status(L"Initializing pointer virtualization event"); + uefi::event event; try_or_raise(