Back to a basic UEFI stub
This commit is contained in:
10
modules.yaml
10
modules.yaml
@@ -53,15 +53,11 @@ modules:
|
|||||||
boot:
|
boot:
|
||||||
kind: exe
|
kind: exe
|
||||||
target: boot
|
target: boot
|
||||||
output: boot.elf
|
output: boot.efi
|
||||||
source:
|
source:
|
||||||
- src/boot/crt0.s
|
|
||||||
- src/boot/console.cpp
|
|
||||||
- src/boot/guids.cpp
|
|
||||||
- src/boot/loader.cpp
|
|
||||||
- src/boot/main.cpp
|
- src/boot/main.cpp
|
||||||
- src/boot/memory.cpp
|
- src/boot/console.cpp
|
||||||
- src/boot/reloc.cpp
|
- src/boot/error.cpp
|
||||||
- src/boot/utility.cpp
|
- src/boot/utility.cpp
|
||||||
|
|
||||||
nulldrv:
|
nulldrv:
|
||||||
|
|||||||
@@ -4,22 +4,8 @@
|
|||||||
|
|
||||||
ccflags = $ccflags $
|
ccflags = $ccflags $
|
||||||
-DKERNEL_FILENAME=L\"jsix.elf\" $
|
-DKERNEL_FILENAME=L\"jsix.elf\" $
|
||||||
-DGNU_EFI_USE_MS_ABI $
|
-I${srcroot}/external/include $
|
||||||
-DHAVE_USE_MS_ABI $
|
-I${srcroot}/external/include/X64
|
||||||
-DEFI_DEBUG=0 $
|
|
||||||
-DEFI_DEBUG_CLEAR_MEMORY=0 $
|
|
||||||
-DBOOTLOADER_DEBUG
|
|
||||||
|
|
||||||
ldflags = $ldflags $
|
|
||||||
-T ${srcroot}/src/arch/x86_64/boot.ld $
|
|
||||||
-shared
|
|
||||||
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block extra %}
|
|
||||||
|
|
||||||
build $builddir/boot.efi : makeefi ${builddir}/{{ module.output }}
|
|
||||||
name = boot.efi
|
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
{% block binaries %}
|
{% block binaries %}
|
||||||
cc = clang
|
cc = clang
|
||||||
cxx = clang++
|
cxx = clang++
|
||||||
ld = ld
|
ld = clang++
|
||||||
ar = ar
|
ar = ar
|
||||||
nasm = nasm
|
nasm = nasm
|
||||||
objcopy = objcopy
|
objcopy = objcopy
|
||||||
@@ -12,27 +12,24 @@ objcopy = objcopy
|
|||||||
{% block variables %}
|
{% block variables %}
|
||||||
|
|
||||||
ccflags = $ccflags $
|
ccflags = $ccflags $
|
||||||
-ggdb $
|
--target=x86_64-unknown-windows $
|
||||||
-nostdlib $
|
|
||||||
-ffreestanding $
|
-ffreestanding $
|
||||||
-nodefaultlibs $
|
|
||||||
-fno-builtin $
|
|
||||||
-mno-sse $
|
|
||||||
-fno-omit-frame-pointer $
|
|
||||||
-mno-red-zone $
|
-mno-red-zone $
|
||||||
-fshort-wchar $
|
-fshort-wchar $
|
||||||
-D__ELF__ $
|
-fno-omit-frame-pointer $
|
||||||
-fPIC
|
-ggdb
|
||||||
|
|
||||||
cxxflags = $cxxflags $
|
cxxflags = $cxxflags $
|
||||||
-fno-exceptions $
|
-fno-rtti $
|
||||||
-fno-rtti $
|
-fno-exceptions
|
||||||
|
|
||||||
ldflags = $ldflags $
|
ldflags = $ldflags $
|
||||||
-g $
|
--target=x86_64-unknown-windows $
|
||||||
-nostdlib $
|
-nostdlib $
|
||||||
-Bsymbolic $
|
-Wl,-entry:efi_main $
|
||||||
-nostartfiles
|
-Wl,-subsystem:efi_application $
|
||||||
|
-fuse-ld=lld-link $
|
||||||
|
-g
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
|||||||
@@ -1,84 +1,94 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <uefi/types.h>
|
||||||
|
#include <uefi/boot_services.h>
|
||||||
|
#include <uefi/graphics.h>
|
||||||
|
#include <uefi/protos/graphics_output.h>
|
||||||
|
#include <uefi/protos/simple_text_output.h>
|
||||||
|
|
||||||
#include "console.h"
|
#include "console.h"
|
||||||
#include "guids.h"
|
//#include "guids.h"
|
||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
|
|
||||||
|
namespace boot {
|
||||||
|
|
||||||
size_t ROWS = 0;
|
size_t ROWS = 0;
|
||||||
size_t COLS = 0;
|
size_t COLS = 0;
|
||||||
|
|
||||||
static EFI_SIMPLE_TEXT_OUT_PROTOCOL *m_out = 0;
|
console *console::s_console = nullptr;
|
||||||
|
|
||||||
static const wchar_t digits[] = {u'0', u'1', u'2', u'3', u'4', u'5',
|
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'};
|
u'6', u'7', u'8', u'9', u'a', u'b', u'c', u'd', u'e', u'f'};
|
||||||
|
|
||||||
console::console(EFI_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_out(nullptr)
|
m_out(nullptr)
|
||||||
{
|
{
|
||||||
s_console = this;
|
s_console = this;
|
||||||
m_boot = system_table->BootServices;
|
m_boot = system_table->boot_services;
|
||||||
m_out = system_table->ConOut;
|
m_out = system_table->con_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
EFI_STATUS
|
uefi::status
|
||||||
console::initialize(const wchar_t *version)
|
console::initialize(const wchar_t *version)
|
||||||
{
|
{
|
||||||
EFI_STATUS status;
|
uefi::status status;
|
||||||
|
|
||||||
// Might not find a video device at all, so ignore not found errors
|
// Might not find a video device at all, so ignore not found errors
|
||||||
status = pick_mode();
|
status = pick_mode();
|
||||||
if (status != EFI_NOT_FOUND)
|
if (status != uefi::status::not_found)
|
||||||
CHECK_EFI_STATUS_OR_FAIL(status);
|
CHECK_EFI_STATUS_OR_FAIL(status);
|
||||||
|
|
||||||
status = m_out->QueryMode(m_out, m_out->Mode->Mode, &m_cols, &m_rows);
|
status = m_out->query_mode(m_out->mode->mode, &m_cols, &m_rows);
|
||||||
CHECK_EFI_STATUS_OR_RETURN(status, "QueryMode");
|
CHECK_EFI_STATUS_OR_RETURN(status, "QueryMode");
|
||||||
|
|
||||||
status = m_out->ClearScreen(m_out);
|
status = m_out->clear_screen();
|
||||||
CHECK_EFI_STATUS_OR_RETURN(status, "ClearScreen");
|
CHECK_EFI_STATUS_OR_RETURN(status, "ClearScreen");
|
||||||
|
|
||||||
m_out->SetAttribute(m_out, EFI_LIGHTCYAN);
|
m_out->set_attribute(uefi::attribute::light_cyan);
|
||||||
m_out->OutputString(m_out, (wchar_t *)L"jsix loader ");
|
m_out->output_string((wchar_t *)L"jsix loader ");
|
||||||
|
|
||||||
m_out->SetAttribute(m_out, EFI_LIGHTMAGENTA);
|
m_out->set_attribute(uefi::attribute::light_magenta);
|
||||||
m_out->OutputString(m_out, (wchar_t *)version);
|
m_out->output_string((wchar_t *)version);
|
||||||
|
|
||||||
m_out->SetAttribute(m_out, EFI_LIGHTGRAY);
|
m_out->set_attribute(uefi::attribute::light_gray);
|
||||||
m_out->OutputString(m_out, (wchar_t *)L" booting...\r\n\n");
|
m_out->output_string((wchar_t *)L" booting...\r\n\n");
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
EFI_STATUS
|
uefi::status
|
||||||
console::pick_mode()
|
console::pick_mode()
|
||||||
{
|
{
|
||||||
EFI_STATUS status;
|
uefi::status status;
|
||||||
EFI_GRAPHICS_OUTPUT_PROTOCOL *gfx_out_proto;
|
uefi::protos::graphics_output *gfx_out_proto;
|
||||||
status = m_boot->LocateProtocol(&guid_gfx_out, NULL, (void **)&gfx_out_proto);
|
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");
|
CHECK_EFI_STATUS_OR_RETURN(status, "LocateProtocol gfx");
|
||||||
|
|
||||||
const uint32_t modes = gfx_out_proto->Mode->MaxMode;
|
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;
|
||||||
|
|
||||||
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *info =
|
uefi::graphics_output_mode_info *info =
|
||||||
(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *)gfx_out_proto->Mode;
|
(uefi::graphics_output_mode_info *)gfx_out_proto->mode;
|
||||||
|
|
||||||
uint32_t res = info->HorizontalResolution * info->VerticalResolution;
|
uint32_t res = info->horizontal_resolution * info->vertical_resolution;
|
||||||
int is_fb = info->PixelFormat != PixelBltOnly;
|
int is_fb = info->pixel_format != uefi::pixel_format::blt_only;
|
||||||
|
|
||||||
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->QueryMode(gfx_out_proto, i, &size, &info);
|
status = gfx_out_proto->query_mode(i, &size, &info);
|
||||||
CHECK_EFI_STATUS_OR_RETURN(status, "QueryMode");
|
CHECK_EFI_STATUS_OR_RETURN(status, "QueryMode");
|
||||||
|
|
||||||
#ifdef MAX_HRES
|
#ifdef MAX_HRES
|
||||||
if (info->HorizontalResolution > MAX_HRES) continue;
|
if (info->horizontal_resolution > MAX_HRES) continue;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const uint32_t new_res = info->HorizontalResolution * info->VerticalResolution;
|
const uint32_t new_res = info->horizontal_resolution * info->vertical_resolution;
|
||||||
const int new_is_fb = info->PixelFormat == PixelBltOnly;
|
const int new_is_fb = info->pixel_format != uefi::pixel_format::blt_only;
|
||||||
|
|
||||||
if (new_is_fb > is_fb && new_res >= res) {
|
if (new_is_fb > is_fb && new_res >= res) {
|
||||||
best = i;
|
best = i;
|
||||||
@@ -86,9 +96,9 @@ console::pick_mode()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
status = gfx_out_proto->SetMode(gfx_out_proto, best);
|
status = gfx_out_proto->set_mode(best);
|
||||||
CHECK_EFI_STATUS_OR_RETURN(status, "SetMode %d/%d", best, modes);
|
CHECK_EFI_STATUS_OR_RETURN(status, "SetMode %d/%d", best, modes);
|
||||||
return EFI_SUCCESS;
|
return uefi::status::success;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
@@ -101,7 +111,7 @@ console::print_hex(uint32_t n) const
|
|||||||
*p++ = digits[nibble];
|
*p++ = digits[nibble];
|
||||||
}
|
}
|
||||||
*p = 0;
|
*p = 0;
|
||||||
m_out->OutputString(m_out, buffer);
|
m_out->output_string(buffer);
|
||||||
return 8;
|
return 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,7 +125,7 @@ console::print_long_hex(uint64_t n) const
|
|||||||
*p++ = digits[nibble];
|
*p++ = digits[nibble];
|
||||||
}
|
}
|
||||||
*p = 0;
|
*p = 0;
|
||||||
m_out->OutputString(m_out, buffer);
|
m_out->output_string(buffer);
|
||||||
return 16;
|
return 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,7 +140,7 @@ console::print_dec(uint32_t n) const
|
|||||||
n /= 10;
|
n /= 10;
|
||||||
} while (n != 0);
|
} while (n != 0);
|
||||||
|
|
||||||
m_out->OutputString(m_out, ++p);
|
m_out->output_string(++p);
|
||||||
return 10 - (p - buffer);
|
return 10 - (p - buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,7 +155,7 @@ console::print_long_dec(uint64_t n) const
|
|||||||
n /= 10;
|
n /= 10;
|
||||||
} while (n != 0);
|
} while (n != 0);
|
||||||
|
|
||||||
m_out->OutputString(m_out, ++p);
|
m_out->output_string(++p);
|
||||||
return 20 - (p - buffer);
|
return 20 - (p - buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,14 +175,14 @@ console::vprintf(const wchar_t *fmt, va_list args) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
*w = 0;
|
*w = 0;
|
||||||
m_out->OutputString(m_out, buffer);
|
m_out->output_string(buffer);
|
||||||
w = buffer;
|
w = buffer;
|
||||||
|
|
||||||
r++; // chomp the %
|
r++; // chomp the %
|
||||||
|
|
||||||
switch (*r++) {
|
switch (*r++) {
|
||||||
case L'%':
|
case L'%':
|
||||||
m_out->OutputString(m_out, const_cast<wchar_t*>(L"%"));
|
m_out->output_string(const_cast<wchar_t*>(L"%"));
|
||||||
count++;
|
count++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -189,7 +199,7 @@ console::vprintf(const wchar_t *fmt, va_list args) const
|
|||||||
{
|
{
|
||||||
wchar_t *s = va_arg(args, wchar_t*);
|
wchar_t *s = va_arg(args, wchar_t*);
|
||||||
count += wstrlen(s);
|
count += wstrlen(s);
|
||||||
m_out->OutputString(m_out, s);
|
m_out->output_string(s);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -215,7 +225,7 @@ console::vprintf(const wchar_t *fmt, va_list args) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
*w = 0;
|
*w = 0;
|
||||||
m_out->OutputString(m_out, buffer);
|
m_out->output_string(buffer);
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -244,40 +254,77 @@ console::print(const wchar_t *fmt, ...)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
console::status_begin(const wchar_t *message) const
|
console::status_begin(const wchar_t *message)
|
||||||
{
|
{
|
||||||
m_out->SetAttribute(m_out, EFI_LIGHTGRAY);
|
m_current_status_line = m_out->mode->cursor_row;
|
||||||
m_out->OutputString(m_out, (wchar_t *)message);
|
m_out->set_cursor_position(0, m_current_status_line);
|
||||||
|
m_out->set_attribute(uefi::attribute::light_gray);
|
||||||
|
m_out->output_string((wchar_t *)message);
|
||||||
|
m_out->output_string((wchar_t *)L"\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
console::status_ok() const
|
console::status_ok() const
|
||||||
{
|
{
|
||||||
m_out->SetAttribute(m_out, EFI_LIGHTGRAY);
|
int row = m_out->mode->cursor_row;
|
||||||
m_out->OutputString(m_out, (wchar_t *)L"[");
|
int col = m_out->mode->cursor_column;
|
||||||
m_out->SetAttribute(m_out, EFI_GREEN);
|
|
||||||
m_out->OutputString(m_out, (wchar_t *)L" ok ");
|
m_out->set_cursor_position(50, m_current_status_line);
|
||||||
m_out->SetAttribute(m_out, EFI_LIGHTGRAY);
|
|
||||||
m_out->OutputString(m_out, (wchar_t *)L"]\r\n");
|
m_out->set_attribute(uefi::attribute::light_gray);
|
||||||
|
m_out->output_string((wchar_t *)L"[");
|
||||||
|
m_out->set_attribute(uefi::attribute::green);
|
||||||
|
m_out->output_string((wchar_t *)L" ok ");
|
||||||
|
m_out->set_attribute(uefi::attribute::light_gray);
|
||||||
|
m_out->output_string((wchar_t *)L"]\r\n");
|
||||||
|
|
||||||
|
m_out->set_cursor_position(col, row);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
console::status_fail(const wchar_t *error) const
|
console::status_fail(const wchar_t *error) const
|
||||||
{
|
{
|
||||||
m_out->SetAttribute(m_out, EFI_LIGHTGRAY);
|
int row = m_out->mode->cursor_row;
|
||||||
m_out->OutputString(m_out, (wchar_t *)L"[");
|
m_out->set_cursor_position(50, m_current_status_line);
|
||||||
m_out->SetAttribute(m_out, EFI_LIGHTRED);
|
|
||||||
m_out->OutputString(m_out, (wchar_t *)L"failed");
|
|
||||||
m_out->SetAttribute(m_out, EFI_LIGHTGRAY);
|
|
||||||
m_out->OutputString(m_out, (wchar_t *)L"]\r\n");
|
|
||||||
|
|
||||||
m_out->SetAttribute(m_out, EFI_RED);
|
m_out->set_attribute(uefi::attribute::light_gray);
|
||||||
m_out->OutputString(m_out, (wchar_t *)error);
|
m_out->output_string((wchar_t *)L"[");
|
||||||
m_out->SetAttribute(m_out, EFI_LIGHTGRAY);
|
m_out->set_attribute(uefi::attribute::light_red);
|
||||||
m_out->OutputString(m_out, (wchar_t *)L"\r\n");
|
m_out->output_string((wchar_t *)L"failed");
|
||||||
|
m_out->set_attribute(uefi::attribute::light_gray);
|
||||||
|
m_out->output_string((wchar_t *)L"]");
|
||||||
|
|
||||||
|
m_out->set_cursor_position(4, row);
|
||||||
|
|
||||||
|
m_out->set_attribute(uefi::attribute::red);
|
||||||
|
m_out->output_string((wchar_t *)error);
|
||||||
|
m_out->set_attribute(uefi::attribute::light_gray);
|
||||||
|
m_out->output_string((wchar_t *)L"\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
EFI_STATUS
|
void
|
||||||
|
console::status_warn(const wchar_t *error) const
|
||||||
|
{
|
||||||
|
int row = m_out->mode->cursor_row;
|
||||||
|
m_out->set_cursor_position(50, m_current_status_line);
|
||||||
|
|
||||||
|
m_out->set_attribute(uefi::attribute::light_gray);
|
||||||
|
m_out->output_string((wchar_t *)L"[");
|
||||||
|
m_out->set_attribute(uefi::attribute::brown);
|
||||||
|
m_out->output_string((wchar_t *)L" warn ");
|
||||||
|
m_out->set_attribute(uefi::attribute::light_gray);
|
||||||
|
m_out->output_string((wchar_t *)L"]");
|
||||||
|
|
||||||
|
m_out->set_cursor_position(4, row);
|
||||||
|
|
||||||
|
m_out->set_attribute(uefi::attribute::yellow);
|
||||||
|
m_out->output_string((wchar_t *)error);
|
||||||
|
m_out->set_attribute(uefi::attribute::light_gray);
|
||||||
|
m_out->output_string((wchar_t *)L"\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
uefi::status
|
||||||
con_get_framebuffer(
|
con_get_framebuffer(
|
||||||
EFI_BOOT_SERVICES *bootsvc,
|
EFI_BOOT_SERVICES *bootsvc,
|
||||||
void **buffer,
|
void **buffer,
|
||||||
@@ -288,17 +335,17 @@ con_get_framebuffer(
|
|||||||
uint32_t *gmask,
|
uint32_t *gmask,
|
||||||
uint32_t *bmask)
|
uint32_t *bmask)
|
||||||
{
|
{
|
||||||
EFI_STATUS status;
|
uefi::status status;
|
||||||
|
|
||||||
EFI_GRAPHICS_OUTPUT_PROTOCOL *gop;
|
uefi::protos::graphics_output *gop;
|
||||||
status = bootsvc->LocateProtocol(&guid_gfx_out, NULL, (void **)&gop);
|
status = bootsvc->LocateProtocol(&guid_gfx_out, NULL, (void **)&gop);
|
||||||
if (status != EFI_NOT_FOUND) {
|
if (status != EFI_NOT_FOUND) {
|
||||||
CHECK_EFI_STATUS_OR_RETURN(status, "LocateProtocol gfx");
|
CHECK_EFI_STATUS_OR_RETURN(status, "LocateProtocol gfx");
|
||||||
|
|
||||||
*buffer = (void *)gop->Mode->FrameBufferBase;
|
*buffer = (void *)gop->Mode->FrameBufferBase;
|
||||||
*buffer_size = gop->Mode->FrameBufferSize;
|
*buffer_size = gop->Mode->FrameBufferSize;
|
||||||
*hres = gop->Mode->Info->HorizontalResolution;
|
*hres = gop->Mode->Info->horizontal_resolution;
|
||||||
*vres = gop->Mode->Info->VerticalResolution;
|
*vres = gop->Mode->Info->vertical_resolution;
|
||||||
|
|
||||||
switch (gop->Mode->Info->PixelFormat) {
|
switch (gop->Mode->Info->PixelFormat) {
|
||||||
case PixelRedGreenBlueReserved8BitPerColor:
|
case PixelRedGreenBlueReserved8BitPerColor:
|
||||||
@@ -331,3 +378,6 @@ con_get_framebuffer(
|
|||||||
*rmask = *gmask = *bmask = 0;
|
*rmask = *gmask = *bmask = 0;
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
} // namespace boot
|
||||||
|
|||||||
@@ -1,17 +1,20 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <efi/efi.h>
|
#include <uefi/tables.h>
|
||||||
|
|
||||||
|
namespace boot {
|
||||||
|
|
||||||
class console
|
class console
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
console(EFI_SYSTEM_TABLE *system_table);
|
console(uefi::system_table *system_table);
|
||||||
|
|
||||||
EFI_STATUS initialize(const wchar_t *version);
|
uefi::status initialize(const wchar_t *version);
|
||||||
|
|
||||||
void status_begin(const wchar_t *message) const;
|
void status_begin(const wchar_t *message);
|
||||||
void status_fail(const wchar_t *error) const;
|
void status_fail(const wchar_t *error) const;
|
||||||
|
void status_warn(const wchar_t *error) 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;
|
||||||
@@ -24,19 +27,20 @@ public:
|
|||||||
static size_t print(const wchar_t *fmt, ...);
|
static size_t print(const wchar_t *fmt, ...);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
EFI_STATUS pick_mode();
|
uefi::status 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;
|
||||||
EFI_BOOT_SERVICES *m_boot;
|
int m_current_status_line;
|
||||||
EFI_SIMPLE_TEXT_OUT_PROTOCOL *m_out;
|
uefi::boot_services *m_boot;
|
||||||
|
uefi::protos::simple_text_output *m_out;
|
||||||
|
|
||||||
static console *s_console;
|
static console *s_console;
|
||||||
};
|
};
|
||||||
|
|
||||||
EFI_STATUS
|
uefi::status
|
||||||
con_get_framebuffer(
|
con_get_framebuffer(
|
||||||
EFI_BOOT_SERVICES *bootsvc,
|
uefi::boot_services *bs,
|
||||||
void **buffer,
|
void **buffer,
|
||||||
size_t *buffer_size,
|
size_t *buffer_size,
|
||||||
uint32_t *hres,
|
uint32_t *hres,
|
||||||
@@ -44,3 +48,5 @@ con_get_framebuffer(
|
|||||||
uint32_t *rmask,
|
uint32_t *rmask,
|
||||||
uint32_t *gmask,
|
uint32_t *gmask,
|
||||||
uint32_t *bmask);
|
uint32_t *bmask);
|
||||||
|
|
||||||
|
} // namespace boot
|
||||||
|
|||||||
66
src/boot/error.cpp
Normal file
66
src/boot/error.cpp
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
#include "error.h"
|
||||||
|
#include "console.h"
|
||||||
|
|
||||||
|
namespace boot {
|
||||||
|
namespace error {
|
||||||
|
|
||||||
|
handler *handler::s_current = nullptr;
|
||||||
|
|
||||||
|
[[ 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)
|
||||||
|
{
|
||||||
|
m_con.status_fail(message);
|
||||||
|
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 *) {}
|
||||||
|
|
||||||
53
src/boot/error.h
Normal file
53
src/boot/error.h
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <uefi/types.h>
|
||||||
|
|
||||||
|
namespace boot {
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
/// Interface for error-handling functors
|
||||||
|
class handler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// Constructor must be called by implementing classes.
|
||||||
|
handler();
|
||||||
|
virtual ~handler();
|
||||||
|
|
||||||
|
/// Interface for implementations of error handling.
|
||||||
|
virtual void handle(uefi::status, const wchar_t*) = 0;
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend void raise(uefi::status, const wchar_t *);
|
||||||
|
|
||||||
|
handler *m_next;
|
||||||
|
static handler *s_current;
|
||||||
|
};
|
||||||
|
|
||||||
|
class uefi_handler :
|
||||||
|
public handler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
uefi_handler(console &con);
|
||||||
|
[[ noreturn ]] void handle(uefi::status, const wchar_t*) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
console &m_con;
|
||||||
|
};
|
||||||
|
|
||||||
|
class cpu_assert_handler :
|
||||||
|
public handler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
cpu_assert_handler();
|
||||||
|
[[ noreturn ]] void handle(uefi::status, const wchar_t*) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace error
|
||||||
|
} // namespace boot
|
||||||
@@ -1,9 +1,15 @@
|
|||||||
|
#include <uefi/types.h>
|
||||||
|
#include <uefi/guid.h>
|
||||||
|
#include <uefi/tables.h>
|
||||||
|
#include <uefi/protos/simple_text_output.h>
|
||||||
|
|
||||||
#include <stdalign.h>
|
#include <stdalign.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <efi/efi.h>
|
|
||||||
|
|
||||||
#include "console.h"
|
#include "console.h"
|
||||||
|
#include "error.h"
|
||||||
|
/*
|
||||||
#include "guids.h"
|
#include "guids.h"
|
||||||
#include "kernel_args.h"
|
#include "kernel_args.h"
|
||||||
#include "loader.h"
|
#include "loader.h"
|
||||||
@@ -13,11 +19,15 @@
|
|||||||
#ifndef SCRATCH_PAGES
|
#ifndef SCRATCH_PAGES
|
||||||
#define SCRATCH_PAGES 64
|
#define SCRATCH_PAGES 64
|
||||||
#endif
|
#endif
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef GIT_VERSION_WIDE
|
#ifndef GIT_VERSION_WIDE
|
||||||
#define GIT_VERSION_WIDE L"no version"
|
#define GIT_VERSION_WIDE L"no version"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
using namespace boot;
|
||||||
|
|
||||||
|
/*
|
||||||
#define KERNEL_HEADER_MAGIC 0x600db007
|
#define KERNEL_HEADER_MAGIC 0x600db007
|
||||||
#define KERNEL_HEADER_VERSION 1
|
#define KERNEL_HEADER_VERSION 1
|
||||||
|
|
||||||
@@ -45,7 +55,7 @@ type_to_wchar(wchar_t *into, uint32_t type)
|
|||||||
|
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
detect_debug_mode(EFI_RUNTIME_SERVICES *run, kernel_args *header) {
|
detect_debug_mode(EFI_RUNTIME_SERVICES *run, kernel_args *header) {
|
||||||
wchar_t var_name[] = L"debug";
|
CHAR16 var_name[] = L"debug";
|
||||||
|
|
||||||
EFI_STATUS status;
|
EFI_STATUS status;
|
||||||
uint8_t debug = 0;
|
uint8_t debug = 0;
|
||||||
@@ -79,15 +89,38 @@ detect_debug_mode(EFI_RUNTIME_SERVICES *run, kernel_args *header) {
|
|||||||
|
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
extern "C" EFI_STATUS
|
extern "C" uefi::status
|
||||||
efi_main(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table)
|
efi_main(uefi::handle image_handle, uefi::system_table *st)
|
||||||
{
|
{
|
||||||
EFI_STATUS status;
|
error::cpu_assert_handler handler;
|
||||||
EFI_BOOT_SERVICES *bootsvc = system_table->BootServices;
|
|
||||||
EFI_RUNTIME_SERVICES *runsvc = system_table->RuntimeServices;
|
|
||||||
|
|
||||||
console con(system_table);
|
uefi::boot_services *bs = st->boot_services;
|
||||||
|
uefi::runtime_services *rs = st->runtime_services;
|
||||||
|
|
||||||
|
console con(st);
|
||||||
|
con.initialize(GIT_VERSION_WIDE);
|
||||||
|
|
||||||
|
{
|
||||||
|
error::uefi_handler handler(con);
|
||||||
|
con.status_begin(L"Trying to do an easy thing...");
|
||||||
|
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);
|
||||||
|
return uefi::status::success;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
|
||||||
// When checking console initialization, use CHECK_EFI_STATUS_OR_RETURN
|
// When checking console initialization, use CHECK_EFI_STATUS_OR_RETURN
|
||||||
// because we can't be sure if the console was fully set up
|
// because we can't be sure if the console was fully set up
|
||||||
@@ -225,3 +258,4 @@ efi_main(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table)
|
|||||||
kernel_main(data_header);
|
kernel_main(data_header);
|
||||||
return EFI_LOAD_ERROR;
|
return EFI_LOAD_ERROR;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|||||||
@@ -1,61 +1,28 @@
|
|||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
|
|
||||||
struct error_code_desc {
|
struct error_code_desc {
|
||||||
EFI_STATUS code;
|
uefi::status code;
|
||||||
const wchar_t *name;
|
const wchar_t *name;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Based off the gnu-efi table
|
|
||||||
struct error_code_desc error_table[] = {
|
struct error_code_desc error_table[] = {
|
||||||
{ EFI_SUCCESS, L"Success" },
|
#define STATUS_ERROR(name, num) { uefi::status::name, L#name },
|
||||||
{ EFI_LOAD_ERROR, L"Load Error" },
|
#define STATUS_WARNING(name, num) { uefi::status::name, L#name },
|
||||||
{ EFI_INVALID_PARAMETER, L"Invalid Parameter" },
|
#include "uefi/errors.inc"
|
||||||
{ EFI_UNSUPPORTED, L"Unsupported" },
|
#undef STATUS_ERROR
|
||||||
{ EFI_BAD_BUFFER_SIZE, L"Bad Buffer Size" },
|
#undef STATUS_WARNING
|
||||||
{ EFI_BUFFER_TOO_SMALL, L"Buffer Too Small" },
|
{ uefi::status::success, nullptr }
|
||||||
{ EFI_NOT_READY, L"Not Ready" },
|
|
||||||
{ EFI_DEVICE_ERROR, L"Device Error" },
|
|
||||||
{ EFI_WRITE_PROTECTED, L"Write Protected" },
|
|
||||||
{ EFI_OUT_OF_RESOURCES, L"Out of Resources" },
|
|
||||||
{ EFI_VOLUME_CORRUPTED, L"Volume Corrupt" },
|
|
||||||
{ EFI_VOLUME_FULL, L"Volume Full" },
|
|
||||||
{ EFI_NO_MEDIA, L"No Media" },
|
|
||||||
{ EFI_MEDIA_CHANGED, L"Media changed" },
|
|
||||||
{ EFI_NOT_FOUND, L"Not Found" },
|
|
||||||
{ EFI_ACCESS_DENIED, L"Access Denied" },
|
|
||||||
{ EFI_NO_RESPONSE, L"No Response" },
|
|
||||||
{ EFI_NO_MAPPING, L"No mapping" },
|
|
||||||
{ EFI_TIMEOUT, L"Time out" },
|
|
||||||
{ EFI_NOT_STARTED, L"Not started" },
|
|
||||||
{ EFI_ALREADY_STARTED, L"Already started" },
|
|
||||||
{ EFI_ABORTED, L"Aborted" },
|
|
||||||
{ EFI_ICMP_ERROR, L"ICMP Error" },
|
|
||||||
{ EFI_TFTP_ERROR, L"TFTP Error" },
|
|
||||||
{ EFI_PROTOCOL_ERROR, L"Protocol Error" },
|
|
||||||
{ EFI_INCOMPATIBLE_VERSION, L"Incompatible Version" },
|
|
||||||
{ EFI_SECURITY_VIOLATION, L"Security Policy Violation" },
|
|
||||||
{ EFI_CRC_ERROR, L"CRC Error" },
|
|
||||||
{ EFI_END_OF_MEDIA, L"End of Media" },
|
|
||||||
{ EFI_END_OF_FILE, L"End of File" },
|
|
||||||
{ EFI_INVALID_LANGUAGE, L"Invalid Languages" },
|
|
||||||
{ EFI_COMPROMISED_DATA, L"Compromised Data" },
|
|
||||||
|
|
||||||
{ EFI_WARN_UNKOWN_GLYPH, L"Warning Unknown Glyph" },
|
|
||||||
{ EFI_WARN_DELETE_FAILURE, L"Warning Delete Failure" },
|
|
||||||
{ EFI_WARN_WRITE_FAILURE, L"Warning Write Failure" },
|
|
||||||
{ EFI_WARN_BUFFER_TOO_SMALL, L"Warning Buffer Too Small" },
|
|
||||||
{ 0, NULL }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const wchar_t *
|
const wchar_t *
|
||||||
util_error_message(EFI_STATUS status)
|
util_error_message(uefi::status status)
|
||||||
{
|
{
|
||||||
int32_t i = -1;
|
int32_t i = -1;
|
||||||
while (error_table[++i].name != NULL) {
|
while (error_table[++i].name != nullptr) {
|
||||||
if (error_table[i].code == status) return error_table[i].name;
|
if (error_table[i].code == status) return error_table[i].name;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (EFI_ERROR(status))
|
if (uefi::is_error(status))
|
||||||
return L"Unknown Error";
|
return L"Unknown Error";
|
||||||
else
|
else
|
||||||
return L"Unknown Warning";
|
return L"Unknown Warning";
|
||||||
|
|||||||
@@ -1,27 +1,27 @@
|
|||||||
#include <stddef.h>
|
#include <stdint.h>
|
||||||
#include <efi/efi.h>
|
#include <uefi/types.h>
|
||||||
|
|
||||||
#include "console.h"
|
#include "console.h"
|
||||||
|
|
||||||
#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(EFI_STATUS status);
|
const wchar_t *util_error_message(uefi::status status);
|
||||||
|
|
||||||
#define CHECK_EFI_STATUS_OR_RETURN(s, msg, ...) \
|
#define CHECK_EFI_STATUS_OR_RETURN(s, msg, ...) \
|
||||||
if (EFI_ERROR((s))) { \
|
if (uefi::is_error((s))) { \
|
||||||
console::print(L"ERROR: " msg L": %s\r\n", ##__VA_ARGS__, util_error_message(s)); \
|
console::print(L"ERROR: " msg L": %s\r\n", ##__VA_ARGS__, util_error_message(s)); \
|
||||||
return (s); \
|
return (s); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CHECK_EFI_STATUS_OR_FAIL(s) \
|
#define CHECK_EFI_STATUS_OR_FAIL(s) \
|
||||||
if (EFI_ERROR((s))) { \
|
if (uefi::is_error((s))) { \
|
||||||
console::get().status_fail(util_error_message(s)); \
|
console::get().status_fail(util_error_message(s)); \
|
||||||
while (1) __asm__("hlt"); \
|
while (1) __asm__("hlt"); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CHECK_EFI_STATUS_OR_ASSERT(s, d) \
|
#define CHECK_EFI_STATUS_OR_ASSERT(s, d) \
|
||||||
if (EFI_ERROR((s))) { \
|
if (uefi::is_error((s))) { \
|
||||||
__asm__ __volatile__( \
|
__asm__ __volatile__( \
|
||||||
"movq %0, %%r8;" \
|
"movq %0, %%r8;" \
|
||||||
"movq %1, %%r9;" \
|
"movq %1, %%r9;" \
|
||||||
|
|||||||
Reference in New Issue
Block a user