mirror of
https://github.com/justinian/jsix.git
synced 2025-12-10 08:24:32 -08:00
Re-add functionality to boot with new UEFI headers
- Pointer fixup event - ACPI searching - Move CHECK_* to using try_or_raise()
This commit is contained in:
@@ -58,6 +58,7 @@ modules:
|
|||||||
- src/boot/main.cpp
|
- src/boot/main.cpp
|
||||||
- src/boot/console.cpp
|
- src/boot/console.cpp
|
||||||
- src/boot/error.cpp
|
- src/boot/error.cpp
|
||||||
|
- src/boot/memory.cpp
|
||||||
- src/boot/utility.cpp
|
- src/boot/utility.cpp
|
||||||
|
|
||||||
nulldrv:
|
nulldrv:
|
||||||
|
|||||||
@@ -8,9 +8,13 @@
|
|||||||
#include <uefi/protos/simple_text_output.h>
|
#include <uefi/protos/simple_text_output.h>
|
||||||
|
|
||||||
#include "console.h"
|
#include "console.h"
|
||||||
//#include "guids.h"
|
#include "error.h"
|
||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
|
|
||||||
|
#ifndef GIT_VERSION_WIDE
|
||||||
|
#define GIT_VERSION_WIDE L"no version"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace boot {
|
namespace boot {
|
||||||
|
|
||||||
size_t ROWS = 0;
|
size_t ROWS = 0;
|
||||||
@@ -24,50 +28,44 @@ static const wchar_t digits[] = {u'0', u'1', u'2', u'3', u'4', u'5',
|
|||||||
console::console(uefi::system_table *system_table) :
|
console::console(uefi::system_table *system_table) :
|
||||||
m_rows(0),
|
m_rows(0),
|
||||||
m_cols(0),
|
m_cols(0),
|
||||||
m_current_status_line(0),
|
m_current_status_line(0)
|
||||||
m_out(nullptr)
|
|
||||||
{
|
|
||||||
s_console = this;
|
|
||||||
m_boot = system_table->boot_services;
|
|
||||||
m_out = system_table->con_out;
|
|
||||||
}
|
|
||||||
|
|
||||||
uefi::status
|
|
||||||
console::initialize(const wchar_t *version)
|
|
||||||
{
|
{
|
||||||
uefi::status status;
|
uefi::status status;
|
||||||
|
|
||||||
// Might not find a video device at all, so ignore not found errors
|
s_console = this;
|
||||||
status = pick_mode();
|
m_boot = system_table->boot_services;
|
||||||
if (status != uefi::status::not_found)
|
m_out = system_table->con_out;
|
||||||
CHECK_EFI_STATUS_OR_FAIL(status);
|
|
||||||
|
|
||||||
status = m_out->query_mode(m_out->mode->mode, &m_cols, &m_rows);
|
pick_mode();
|
||||||
CHECK_EFI_STATUS_OR_RETURN(status, "QueryMode");
|
|
||||||
|
|
||||||
status = m_out->clear_screen();
|
try_or_raise(
|
||||||
CHECK_EFI_STATUS_OR_RETURN(status, "ClearScreen");
|
m_out->query_mode(m_out->mode->mode, &m_cols, &m_rows),
|
||||||
|
L"Failed to get text output mode.");
|
||||||
|
|
||||||
|
try_or_raise(
|
||||||
|
m_out->clear_screen(),
|
||||||
|
L"Failed to clear screen");
|
||||||
|
|
||||||
m_out->set_attribute(uefi::attribute::light_cyan);
|
m_out->set_attribute(uefi::attribute::light_cyan);
|
||||||
m_out->output_string((wchar_t *)L"jsix loader ");
|
m_out->output_string(L"jsix loader ");
|
||||||
|
|
||||||
m_out->set_attribute(uefi::attribute::light_magenta);
|
m_out->set_attribute(uefi::attribute::light_magenta);
|
||||||
m_out->output_string((wchar_t *)version);
|
m_out->output_string(GIT_VERSION_WIDE);
|
||||||
|
|
||||||
m_out->set_attribute(uefi::attribute::light_gray);
|
m_out->set_attribute(uefi::attribute::light_gray);
|
||||||
m_out->output_string((wchar_t *)L" booting...\r\n\n");
|
m_out->output_string(L" booting...\r\n\n");
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uefi::status
|
void
|
||||||
console::pick_mode()
|
console::pick_mode()
|
||||||
{
|
{
|
||||||
uefi::status status;
|
uefi::status status;
|
||||||
uefi::protos::graphics_output *gfx_out_proto;
|
uefi::protos::graphics_output *gfx_out_proto;
|
||||||
uefi::guid guid = uefi::protos::graphics_output::guid;
|
uefi::guid guid = uefi::protos::graphics_output::guid;
|
||||||
status = m_boot->locate_protocol(&guid, nullptr, (void **)&gfx_out_proto);
|
|
||||||
CHECK_EFI_STATUS_OR_RETURN(status, "LocateProtocol gfx");
|
try_or_raise(
|
||||||
|
m_boot->locate_protocol(&guid, nullptr, (void **)&gfx_out_proto),
|
||||||
|
L"Failed to find a Graphics Output Protocol handle");
|
||||||
|
|
||||||
const uint32_t modes = gfx_out_proto->mode->max_mode;
|
const uint32_t modes = gfx_out_proto->mode->max_mode;
|
||||||
uint32_t best = gfx_out_proto->mode->mode;
|
uint32_t best = gfx_out_proto->mode->mode;
|
||||||
@@ -80,8 +78,10 @@ console::pick_mode()
|
|||||||
|
|
||||||
for (uint32_t i = 0; i < modes; ++i) {
|
for (uint32_t i = 0; i < modes; ++i) {
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
status = gfx_out_proto->query_mode(i, &size, &info);
|
|
||||||
CHECK_EFI_STATUS_OR_RETURN(status, "QueryMode");
|
try_or_raise(
|
||||||
|
gfx_out_proto->query_mode(i, &size, &info),
|
||||||
|
L"Failed to find a graphics mode the driver claimed to support");
|
||||||
|
|
||||||
#ifdef MAX_HRES
|
#ifdef MAX_HRES
|
||||||
if (info->horizontal_resolution > MAX_HRES) continue;
|
if (info->horizontal_resolution > MAX_HRES) continue;
|
||||||
@@ -96,9 +96,9 @@ console::pick_mode()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
status = gfx_out_proto->set_mode(best);
|
try_or_raise(
|
||||||
CHECK_EFI_STATUS_OR_RETURN(status, "SetMode %d/%d", best, modes);
|
gfx_out_proto->set_mode(best),
|
||||||
return uefi::status::success;
|
L"Failed to set graphics mode");
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
@@ -259,8 +259,8 @@ console::status_begin(const wchar_t *message)
|
|||||||
m_current_status_line = m_out->mode->cursor_row;
|
m_current_status_line = m_out->mode->cursor_row;
|
||||||
m_out->set_cursor_position(0, m_current_status_line);
|
m_out->set_cursor_position(0, m_current_status_line);
|
||||||
m_out->set_attribute(uefi::attribute::light_gray);
|
m_out->set_attribute(uefi::attribute::light_gray);
|
||||||
m_out->output_string((wchar_t *)message);
|
m_out->output_string(message);
|
||||||
m_out->output_string((wchar_t *)L"\r\n");
|
m_out->output_string(L"\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -272,55 +272,67 @@ console::status_ok() const
|
|||||||
m_out->set_cursor_position(50, m_current_status_line);
|
m_out->set_cursor_position(50, m_current_status_line);
|
||||||
|
|
||||||
m_out->set_attribute(uefi::attribute::light_gray);
|
m_out->set_attribute(uefi::attribute::light_gray);
|
||||||
m_out->output_string((wchar_t *)L"[");
|
m_out->output_string(L"[");
|
||||||
m_out->set_attribute(uefi::attribute::green);
|
m_out->set_attribute(uefi::attribute::green);
|
||||||
m_out->output_string((wchar_t *)L" ok ");
|
m_out->output_string(L" ok ");
|
||||||
m_out->set_attribute(uefi::attribute::light_gray);
|
m_out->set_attribute(uefi::attribute::light_gray);
|
||||||
m_out->output_string((wchar_t *)L"]\r\n");
|
m_out->output_string(L"]\r\n");
|
||||||
|
|
||||||
m_out->set_cursor_position(col, row);
|
m_out->set_cursor_position(col, row);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
console::status_fail(const wchar_t *error) const
|
console::status_fail(const wchar_t *message, const wchar_t *error) const
|
||||||
{
|
{
|
||||||
int row = m_out->mode->cursor_row;
|
int row = m_out->mode->cursor_row;
|
||||||
m_out->set_cursor_position(50, m_current_status_line);
|
m_out->set_cursor_position(50, m_current_status_line);
|
||||||
|
|
||||||
m_out->set_attribute(uefi::attribute::light_gray);
|
m_out->set_attribute(uefi::attribute::light_gray);
|
||||||
m_out->output_string((wchar_t *)L"[");
|
m_out->output_string(L"[");
|
||||||
m_out->set_attribute(uefi::attribute::light_red);
|
m_out->set_attribute(uefi::attribute::light_red);
|
||||||
m_out->output_string((wchar_t *)L"failed");
|
m_out->output_string(L"failed");
|
||||||
m_out->set_attribute(uefi::attribute::light_gray);
|
m_out->set_attribute(uefi::attribute::light_gray);
|
||||||
m_out->output_string((wchar_t *)L"]");
|
m_out->output_string(L"]");
|
||||||
|
|
||||||
m_out->set_cursor_position(4, row);
|
m_out->set_cursor_position(4, row);
|
||||||
|
|
||||||
m_out->set_attribute(uefi::attribute::red);
|
m_out->set_attribute(uefi::attribute::red);
|
||||||
m_out->output_string((wchar_t *)error);
|
m_out->output_string(message);
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
m_out->output_string(L": ");
|
||||||
|
m_out->output_string(error);
|
||||||
|
}
|
||||||
|
|
||||||
m_out->set_attribute(uefi::attribute::light_gray);
|
m_out->set_attribute(uefi::attribute::light_gray);
|
||||||
m_out->output_string((wchar_t *)L"\r\n");
|
m_out->output_string(L"\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
console::status_warn(const wchar_t *error) const
|
console::status_warn(const wchar_t *message, const wchar_t *error) const
|
||||||
{
|
{
|
||||||
int row = m_out->mode->cursor_row;
|
int row = m_out->mode->cursor_row;
|
||||||
m_out->set_cursor_position(50, m_current_status_line);
|
m_out->set_cursor_position(50, m_current_status_line);
|
||||||
|
|
||||||
m_out->set_attribute(uefi::attribute::light_gray);
|
m_out->set_attribute(uefi::attribute::light_gray);
|
||||||
m_out->output_string((wchar_t *)L"[");
|
m_out->output_string(L"[");
|
||||||
m_out->set_attribute(uefi::attribute::brown);
|
m_out->set_attribute(uefi::attribute::brown);
|
||||||
m_out->output_string((wchar_t *)L" warn ");
|
m_out->output_string(L" warn ");
|
||||||
m_out->set_attribute(uefi::attribute::light_gray);
|
m_out->set_attribute(uefi::attribute::light_gray);
|
||||||
m_out->output_string((wchar_t *)L"]");
|
m_out->output_string(L"]");
|
||||||
|
|
||||||
m_out->set_cursor_position(4, row);
|
m_out->set_cursor_position(4, row);
|
||||||
|
|
||||||
m_out->set_attribute(uefi::attribute::yellow);
|
m_out->set_attribute(uefi::attribute::yellow);
|
||||||
m_out->output_string((wchar_t *)error);
|
m_out->output_string(message);
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
m_out->output_string(L": ");
|
||||||
|
m_out->output_string(error);
|
||||||
|
}
|
||||||
|
|
||||||
m_out->set_attribute(uefi::attribute::light_gray);
|
m_out->set_attribute(uefi::attribute::light_gray);
|
||||||
m_out->output_string((wchar_t *)L"\r\n");
|
m_out->output_string(L"\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -10,11 +10,9 @@ class console
|
|||||||
public:
|
public:
|
||||||
console(uefi::system_table *system_table);
|
console(uefi::system_table *system_table);
|
||||||
|
|
||||||
uefi::status initialize(const wchar_t *version);
|
|
||||||
|
|
||||||
void status_begin(const wchar_t *message);
|
void status_begin(const wchar_t *message);
|
||||||
void status_fail(const wchar_t *error) const;
|
void status_fail(const wchar_t *message, const wchar_t *error=nullptr) const;
|
||||||
void status_warn(const wchar_t *error) const;
|
void status_warn(const wchar_t *message, const wchar_t *error=nullptr) const;
|
||||||
void status_ok() const;
|
void status_ok() const;
|
||||||
|
|
||||||
size_t print_hex(uint32_t n) const;
|
size_t print_hex(uint32_t n) const;
|
||||||
@@ -27,7 +25,7 @@ public:
|
|||||||
static size_t print(const wchar_t *fmt, ...);
|
static size_t print(const wchar_t *fmt, ...);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uefi::status pick_mode();
|
void pick_mode();
|
||||||
size_t vprintf(const wchar_t *fmt, va_list args) const;
|
size_t vprintf(const wchar_t *fmt, va_list args) const;
|
||||||
|
|
||||||
size_t m_rows, m_cols;
|
size_t m_rows, m_cols;
|
||||||
|
|||||||
@@ -6,6 +6,34 @@ namespace error {
|
|||||||
|
|
||||||
handler *handler::s_current = nullptr;
|
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
|
[[ noreturn ]] void
|
||||||
raise(uefi::status status, const wchar_t *message)
|
raise(uefi::status status, const wchar_t *message)
|
||||||
{
|
{
|
||||||
@@ -38,7 +66,7 @@ uefi_handler::uefi_handler(console &con) :
|
|||||||
[[ noreturn ]] void
|
[[ noreturn ]] void
|
||||||
uefi_handler::handle(uefi::status s, const wchar_t *message)
|
uefi_handler::handle(uefi::status s, const wchar_t *message)
|
||||||
{
|
{
|
||||||
m_con.status_fail(message);
|
m_con.status_fail(message, error_message(s));
|
||||||
while (1) asm("hlt");
|
while (1) asm("hlt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -51,3 +51,10 @@ public:
|
|||||||
|
|
||||||
} // namespace error
|
} // namespace error
|
||||||
} // namespace boot
|
} // namespace boot
|
||||||
|
|
||||||
|
#define try_or_raise(s, m) \
|
||||||
|
do { \
|
||||||
|
uefi::status _s = (s); \
|
||||||
|
if (uefi::is_error(_s)) ::boot::error::raise(_s, (m)); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
|||||||
@@ -9,25 +9,17 @@
|
|||||||
|
|
||||||
#include "console.h"
|
#include "console.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
|
#include "memory.h"
|
||||||
/*
|
/*
|
||||||
#include "guids.h"
|
#include "guids.h"
|
||||||
#include "kernel_args.h"
|
#include "kernel_args.h"
|
||||||
#include "loader.h"
|
#include "loader.h"
|
||||||
#include "memory.h"
|
|
||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
|
|
||||||
#ifndef SCRATCH_PAGES
|
#ifndef SCRATCH_PAGES
|
||||||
#define SCRATCH_PAGES 64
|
#define SCRATCH_PAGES 64
|
||||||
#endif
|
#endif
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef GIT_VERSION_WIDE
|
|
||||||
#define GIT_VERSION_WIDE L"no version"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
using namespace boot;
|
|
||||||
|
|
||||||
/*
|
|
||||||
#define KERNEL_HEADER_MAGIC 0x600db007
|
#define KERNEL_HEADER_MAGIC 0x600db007
|
||||||
#define KERNEL_HEADER_VERSION 1
|
#define KERNEL_HEADER_VERSION 1
|
||||||
|
|
||||||
@@ -43,9 +35,13 @@ struct kernel_header {
|
|||||||
uint32_t gitsha;
|
uint32_t gitsha;
|
||||||
};
|
};
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
using kernel_entry = void (*)(kernel_args *);
|
using kernel_entry = void (*)(kernel_args *);
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace boot {
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
static void
|
static void
|
||||||
type_to_wchar(wchar_t *into, uint32_t type)
|
type_to_wchar(wchar_t *into, uint32_t type)
|
||||||
{
|
{
|
||||||
@@ -91,30 +87,54 @@ detect_debug_mode(EFI_RUNTIME_SERVICES *run, kernel_args *header) {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
extern "C" uefi::status
|
uefi::status
|
||||||
efi_main(uefi::handle image_handle, uefi::system_table *st)
|
bootloader_main_uefi(uefi::system_table *st, console &con)
|
||||||
{
|
{
|
||||||
error::cpu_assert_handler handler;
|
error::uefi_handler handler(con);
|
||||||
|
|
||||||
uefi::boot_services *bs = st->boot_services;
|
uefi::boot_services *bs = st->boot_services;
|
||||||
uefi::runtime_services *rs = st->runtime_services;
|
uefi::runtime_services *rs = st->runtime_services;
|
||||||
|
|
||||||
console con(st);
|
/*
|
||||||
con.initialize(GIT_VERSION_WIDE);
|
con.status_begin(L"Trying to do a harder thing...");
|
||||||
|
con.status_warn(L"First warning");
|
||||||
|
con.status_warn(L"Second warning");
|
||||||
|
|
||||||
{
|
con.status_begin(L"Trying to do the impossible...");
|
||||||
error::uefi_handler handler(con);
|
con.status_warn(L"we're not going to make it");
|
||||||
con.status_begin(L"Trying to do an easy thing...");
|
|
||||||
|
error::raise(uefi::status::unsupported, L"OH NO");
|
||||||
|
*/
|
||||||
|
|
||||||
|
con.status_begin(L"Initializing pointer fixup for virtualization");
|
||||||
|
memory::init_pointer_fixup(bs, rs);
|
||||||
|
con.status_ok();
|
||||||
|
|
||||||
|
// Find ACPI tables. Ignore ACPI 1.0 if a 2.0 table is found.
|
||||||
|
//
|
||||||
|
con.status_begin(L"Searching for ACPI table");
|
||||||
|
uintptr_t acpi_table = 0;
|
||||||
|
for (size_t i = 0; i < st->number_of_table_entries; ++i) {
|
||||||
|
uefi::configuration_table *table = &st->configuration_table[i];
|
||||||
|
|
||||||
|
if (table->vendor_guid == uefi::vendor_guids::acpi2) {
|
||||||
|
acpi_table = reinterpret_cast<uintptr_t>(table->vendor_table);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (table->vendor_guid == uefi::vendor_guids::acpi1) {
|
||||||
|
// Mark a v1 table with the LSB high
|
||||||
|
acpi_table = reinterpret_cast<uintptr_t>(table->vendor_table);
|
||||||
|
acpi_table |= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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");
|
||||||
|
} else {
|
||||||
con.status_ok();
|
con.status_ok();
|
||||||
|
|
||||||
con.status_begin(L"Trying to do a harder thing...");
|
|
||||||
con.status_warn(L"First warning");
|
|
||||||
con.status_warn(L"Second warning");
|
|
||||||
|
|
||||||
con.status_begin(L"Trying to do the impossible...");
|
|
||||||
con.status_warn(L"we're not going to make it");
|
|
||||||
|
|
||||||
error::raise(uefi::status::unsupported, L"OH NO");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while(1);
|
while(1);
|
||||||
@@ -122,28 +142,6 @@ efi_main(uefi::handle image_handle, uefi::system_table *st)
|
|||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
|
||||||
// When checking console initialization, use CHECK_EFI_STATUS_OR_RETURN
|
|
||||||
// because we can't be sure if the console was fully set up
|
|
||||||
status = con.initialize(GIT_VERSION_WIDE);
|
|
||||||
CHECK_EFI_STATUS_OR_RETURN(status, "console::initialize");
|
|
||||||
// From here on out, we can use CHECK_EFI_STATUS_OR_FAIL instead
|
|
||||||
|
|
||||||
memory_init_pointer_fixup(bootsvc, runsvc, SCRATCH_PAGES);
|
|
||||||
|
|
||||||
// Find ACPI tables. Ignore ACPI 1.0 if a 2.0 table is found.
|
|
||||||
//
|
|
||||||
void *acpi_table = NULL;
|
|
||||||
for (size_t i=0; i<system_table->NumberOfTableEntries; ++i) {
|
|
||||||
EFI_CONFIGURATION_TABLE *efi_table = &system_table->ConfigurationTable[i];
|
|
||||||
if (is_guid(&efi_table->VendorGuid, &guid_acpi2)) {
|
|
||||||
acpi_table = efi_table->VendorTable;
|
|
||||||
break;
|
|
||||||
} else if (is_guid(&efi_table->VendorGuid, &guid_acpi1)) {
|
|
||||||
// Mark a v1 table with the LSB high
|
|
||||||
acpi_table = (void *)((intptr_t)efi_table->VendorTable | 0x1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compute necessary number of data pages
|
// Compute necessary number of data pages
|
||||||
//
|
//
|
||||||
size_t data_length = 0;
|
size_t data_length = 0;
|
||||||
@@ -259,3 +257,16 @@ efi_main(uefi::handle image_handle, uefi::system_table *st)
|
|||||||
return EFI_LOAD_ERROR;
|
return EFI_LOAD_ERROR;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
} // namespace boot
|
||||||
|
|
||||||
|
extern "C" uefi::status
|
||||||
|
efi_main(uefi::handle image_handle, uefi::system_table *st)
|
||||||
|
{
|
||||||
|
using namespace boot;
|
||||||
|
|
||||||
|
error::cpu_assert_handler handler;
|
||||||
|
console con(st);
|
||||||
|
|
||||||
|
return bootloader_main_uefi(st, con);
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,20 +1,27 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <uefi/types.h>
|
||||||
|
|
||||||
#include "loader.h"
|
#include "error.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
|
|
||||||
const EFI_MEMORY_TYPE memtype_kernel = static_cast<EFI_MEMORY_TYPE>(0x80000000);
|
namespace boot {
|
||||||
const EFI_MEMORY_TYPE memtype_data = static_cast<EFI_MEMORY_TYPE>(0x80000001);
|
namespace memory {
|
||||||
const EFI_MEMORY_TYPE memtype_initrd = static_cast<EFI_MEMORY_TYPE>(0x80000002);
|
|
||||||
const EFI_MEMORY_TYPE memtype_scratch = static_cast<EFI_MEMORY_TYPE>(0x80000003);
|
/*
|
||||||
|
const EFI_MEMORY_TYPE memtype_kernel = static_cast<EFI_MEMORY_TYPE>(0x80000000ul);
|
||||||
|
const EFI_MEMORY_TYPE memtype_data = static_cast<EFI_MEMORY_TYPE>(0x80000001ul);
|
||||||
|
const EFI_MEMORY_TYPE memtype_initrd = static_cast<EFI_MEMORY_TYPE>(0x80000002ul);
|
||||||
|
const EFI_MEMORY_TYPE memtype_scratch = static_cast<EFI_MEMORY_TYPE>(0x80000003ul);
|
||||||
|
|
||||||
#define INCREMENT_DESC(p, b) (EFI_MEMORY_DESCRIPTOR*)(((uint8_t*)(p))+(b))
|
#define INCREMENT_DESC(p, b) (EFI_MEMORY_DESCRIPTOR*)(((uint8_t*)(p))+(b))
|
||||||
|
*/
|
||||||
|
|
||||||
size_t fixup_pointer_index = 0;
|
size_t fixup_pointer_index = 0;
|
||||||
void **fixup_pointers[64];
|
void **fixup_pointers[64];
|
||||||
uint64_t *new_pml4 = 0;
|
uint64_t *new_pml4 = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
const wchar_t *memory_type_names[] = {
|
const wchar_t *memory_type_names[] = {
|
||||||
L"EfiReservedMemoryType",
|
L"EfiReservedMemoryType",
|
||||||
L"EfiLoaderCode",
|
L"EfiLoaderCode",
|
||||||
@@ -47,44 +54,52 @@ memory_type_name(UINT32 value)
|
|||||||
}
|
}
|
||||||
return memory_type_names[value];
|
return memory_type_names[value];
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
void EFIAPI
|
void
|
||||||
memory_update_marked_addresses(EFI_EVENT UNUSED *event, void *context)
|
update_marked_addresses(uefi::event, void *context)
|
||||||
{
|
{
|
||||||
EFI_RUNTIME_SERVICES *runsvc = (EFI_RUNTIME_SERVICES*)context;
|
uefi::runtime_services *rs =
|
||||||
|
reinterpret_cast<uefi::runtime_services*>(context);
|
||||||
|
|
||||||
for (size_t i = 0; i < fixup_pointer_index; ++i) {
|
for (size_t i = 0; i < fixup_pointer_index; ++i) {
|
||||||
if (fixup_pointers[i])
|
if (fixup_pointers[i])
|
||||||
runsvc->ConvertPointer(0, fixup_pointers[i]);
|
rs->convert_pointer(0, fixup_pointers[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EFI_STATUS
|
void
|
||||||
memory_init_pointer_fixup(EFI_BOOT_SERVICES *bootsvc, EFI_RUNTIME_SERVICES *runsvc, unsigned scratch_pages)
|
init_pointer_fixup(uefi::boot_services *bs, uefi::runtime_services *rs)
|
||||||
{
|
{
|
||||||
EFI_STATUS status;
|
uefi::event event;
|
||||||
EFI_EVENT event;
|
|
||||||
|
|
||||||
status = bootsvc->CreateEvent(
|
try_or_raise(
|
||||||
EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE,
|
bs->create_event(
|
||||||
TPL_CALLBACK,
|
uefi::evt::signal_virtual_address_change,
|
||||||
(EFI_EVENT_NOTIFY)&memory_update_marked_addresses,
|
uefi::tpl::callback,
|
||||||
runsvc,
|
(uefi::event_notify)&update_marked_addresses,
|
||||||
&event);
|
rs,
|
||||||
|
&event),
|
||||||
|
L"Error creating memory virtualization event");
|
||||||
|
|
||||||
CHECK_EFI_STATUS_OR_RETURN(status, "Failed to initialize pointer update event.");
|
uefi::memory_type memtype = static_cast<uefi::memory_type>(0x80000003ul);
|
||||||
|
|
||||||
// Reserve a page for our replacement PML4, plus some pages for the kernel to use
|
// Reserve a page for our replacement PML4, plus some pages for the kernel to use
|
||||||
// as page tables while it gets started.
|
// as page tables while it gets started.
|
||||||
EFI_PHYSICAL_ADDRESS addr = 0;
|
uintptr_t addr = 0;
|
||||||
status = bootsvc->AllocatePages(AllocateAnyPages, memtype_scratch, scratch_pages, &addr);
|
try_or_raise(
|
||||||
CHECK_EFI_STATUS_OR_RETURN(status, "Failed to allocate page table pages.");
|
bs->allocate_pages(
|
||||||
|
uefi::allocate_type::any_pages,
|
||||||
|
memtype,
|
||||||
|
64,
|
||||||
|
&addr),
|
||||||
|
L"Error allocating page table pages.");
|
||||||
|
|
||||||
new_pml4 = (uint64_t *)addr;
|
new_pml4 = (uint64_t *)addr;
|
||||||
return EFI_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
memory_mark_pointer_fixup(void **p)
|
mark_pointer_fixup(void **p)
|
||||||
{
|
{
|
||||||
if (fixup_pointer_index == 0) {
|
if (fixup_pointer_index == 0) {
|
||||||
const size_t count = sizeof(fixup_pointers) / sizeof(void*);
|
const size_t count = sizeof(fixup_pointers) / sizeof(void*);
|
||||||
@@ -93,6 +108,7 @@ memory_mark_pointer_fixup(void **p)
|
|||||||
fixup_pointers[fixup_pointer_index++] = p;
|
fixup_pointers[fixup_pointer_index++] = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
void
|
void
|
||||||
copy_desc(EFI_MEMORY_DESCRIPTOR *src, EFI_MEMORY_DESCRIPTOR *dst, size_t len)
|
copy_desc(EFI_MEMORY_DESCRIPTOR *src, EFI_MEMORY_DESCRIPTOR *dst, size_t len)
|
||||||
{
|
{
|
||||||
@@ -213,3 +229,7 @@ memory_virtualize(EFI_RUNTIME_SERVICES *runsvc, struct memory_map *map)
|
|||||||
|
|
||||||
runsvc->SetVirtualAddressMap(map->length, map->size, map->version, map->entries);
|
runsvc->SetVirtualAddressMap(map->length, map->size, map->version, map->entries);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
} // namespace boot
|
||||||
|
} // namespace memory
|
||||||
|
|||||||
@@ -1,6 +1,15 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <efi/efi.h>
|
#include <uefi/boot_services.h>
|
||||||
|
#include <uefi/runtime_services.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
namespace boot {
|
||||||
|
namespace memory {
|
||||||
|
|
||||||
|
void init_pointer_fixup(uefi::boot_services *bs, uefi::runtime_services *rs);
|
||||||
|
void mark_pointer_fixup(void **p);
|
||||||
|
|
||||||
|
/*
|
||||||
extern const EFI_MEMORY_TYPE memtype_kernel;
|
extern const EFI_MEMORY_TYPE memtype_kernel;
|
||||||
extern const EFI_MEMORY_TYPE memtype_data;
|
extern const EFI_MEMORY_TYPE memtype_data;
|
||||||
extern const EFI_MEMORY_TYPE memtype_initrd;
|
extern const EFI_MEMORY_TYPE memtype_initrd;
|
||||||
@@ -14,14 +23,12 @@ struct memory_map {
|
|||||||
EFI_MEMORY_DESCRIPTOR *entries;
|
EFI_MEMORY_DESCRIPTOR *entries;
|
||||||
};
|
};
|
||||||
|
|
||||||
EFI_STATUS memory_init_pointer_fixup(
|
|
||||||
EFI_BOOT_SERVICES *bootsvc,
|
|
||||||
EFI_RUNTIME_SERVICES *runsvc,
|
|
||||||
unsigned scratch_pages);
|
|
||||||
void memory_mark_pointer_fixup(void **p);
|
|
||||||
|
|
||||||
EFI_STATUS memory_get_map_length(EFI_BOOT_SERVICES *bootsvc, size_t *size);
|
EFI_STATUS memory_get_map_length(EFI_BOOT_SERVICES *bootsvc, size_t *size);
|
||||||
EFI_STATUS memory_get_map(EFI_BOOT_SERVICES *bootsvc, struct memory_map *map);
|
EFI_STATUS memory_get_map(EFI_BOOT_SERVICES *bootsvc, struct memory_map *map);
|
||||||
EFI_STATUS memory_dump_map(struct memory_map *map);
|
EFI_STATUS memory_dump_map(struct memory_map *map);
|
||||||
|
|
||||||
void memory_virtualize(EFI_RUNTIME_SERVICES *runsvc, struct memory_map *map);
|
void memory_virtualize(EFI_RUNTIME_SERVICES *runsvc, struct memory_map *map);
|
||||||
|
*/
|
||||||
|
|
||||||
|
} // namespace boot
|
||||||
|
} // namespace memory
|
||||||
|
|||||||
@@ -1,33 +1,5 @@
|
|||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
|
|
||||||
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 }
|
|
||||||
};
|
|
||||||
|
|
||||||
const wchar_t *
|
|
||||||
util_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";
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
wstrlen(const wchar_t *s)
|
wstrlen(const wchar_t *s)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,32 +6,6 @@
|
|||||||
#define UNUSED __attribute__((unused))
|
#define UNUSED __attribute__((unused))
|
||||||
|
|
||||||
size_t wstrlen(const wchar_t *s);
|
size_t wstrlen(const wchar_t *s);
|
||||||
const wchar_t *util_error_message(uefi::status status);
|
|
||||||
|
|
||||||
#define CHECK_EFI_STATUS_OR_RETURN(s, msg, ...) \
|
|
||||||
if (uefi::is_error((s))) { \
|
|
||||||
console::print(L"ERROR: " msg L": %s\r\n", ##__VA_ARGS__, util_error_message(s)); \
|
|
||||||
return (s); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define CHECK_EFI_STATUS_OR_FAIL(s) \
|
|
||||||
if (uefi::is_error((s))) { \
|
|
||||||
console::get().status_fail(util_error_message(s)); \
|
|
||||||
while (1) __asm__("hlt"); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define CHECK_EFI_STATUS_OR_ASSERT(s, d) \
|
|
||||||
if (uefi::is_error((s))) { \
|
|
||||||
__asm__ __volatile__( \
|
|
||||||
"movq %0, %%r8;" \
|
|
||||||
"movq %1, %%r9;" \
|
|
||||||
"movq %2, %%r10;" \
|
|
||||||
"movq $0, %%rdx;" \
|
|
||||||
"divq %%rdx;" \
|
|
||||||
: \
|
|
||||||
: "r"((uint64_t)s), "r"((uint64_t)d), "r"((uint64_t)__LINE__) \
|
|
||||||
: "rax", "rdx", "r8", "r9", "r10"); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef BOOTLOADER_DEBUG
|
#ifdef BOOTLOADER_DEBUG
|
||||||
#define con_debug(msg, ...) console::print(L"DEBUG: " msg L"\r\n", __VA_ARGS__)
|
#define con_debug(msg, ...) console::print(L"DEBUG: " msg L"\r\n", __VA_ARGS__)
|
||||||
|
|||||||
Reference in New Issue
Block a user