Allow debug option to be communicated at boot
This commit is contained in:
Binary file not shown.
BIN
assets/ovmf/x64/ovmf_debug.fd
Normal file
BIN
assets/ovmf/x64/ovmf_debug.fd
Normal file
Binary file not shown.
10
qemu.sh
10
qemu.sh
@@ -1,13 +1,16 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
build="$(dirname $0)/build"
|
build="$(dirname $0)/build"
|
||||||
|
assets="$(dirname $0)/assets"
|
||||||
debug=""
|
debug=""
|
||||||
|
flash_name="ovmf.fd"
|
||||||
gfx="-nographic"
|
gfx="-nographic"
|
||||||
|
|
||||||
for arg in $@; do
|
for arg in $@; do
|
||||||
case "${arg}" in
|
case "${arg}" in
|
||||||
--debug)
|
--debug)
|
||||||
debug="-s"
|
debug="-s"
|
||||||
|
flash_name="ovmf_debug.fd"
|
||||||
;;
|
;;
|
||||||
--gfx)
|
--gfx)
|
||||||
gfx=""
|
gfx=""
|
||||||
@@ -28,11 +31,16 @@ if ! ninja -C "${build}"; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -n $TMUX ]]; then
|
if [[ -n $TMUX ]]; then
|
||||||
|
if [[ -n $debug ]]; then
|
||||||
|
tmux split-window "gdb ${build}/popcorn.elf" &
|
||||||
|
else
|
||||||
tmux split-window "sleep 1; telnet localhost 45454" &
|
tmux split-window "sleep 1; telnet localhost 45454" &
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
touch "${build}/popd_table.data"
|
||||||
exec qemu-system-x86_64 \
|
exec qemu-system-x86_64 \
|
||||||
-drive "if=pflash,format=raw,file=${build}/flash.img" \
|
-drive "if=pflash,format=raw,file=${build}/${flash_name}" \
|
||||||
-drive "format=raw,file=${build}/popcorn.img" \
|
-drive "format=raw,file=${build}/popcorn.img" \
|
||||||
-monitor telnet:localhost:45454,server,nowait \
|
-monitor telnet:localhost:45454,server,nowait \
|
||||||
-smp 1 \
|
-smp 1 \
|
||||||
|
|||||||
@@ -152,8 +152,11 @@ build $
|
|||||||
$modulefile $
|
$modulefile $
|
||||||
{{ generator }}
|
{{ generator }}
|
||||||
|
|
||||||
build $builddir/flash.img : cp $srcroot/assets/ovmf/x64/OVMF.fd
|
build $builddir/ovmf.fd : cp $srcroot/assets/ovmf/x64/ovmf.fd
|
||||||
name = flash.img
|
name = ovmf.fd
|
||||||
|
|
||||||
|
build $builddir/ovmf_debug.fd : cp $srcroot/assets/ovmf/x64/ovmf_debug.fd
|
||||||
|
name = ovmf_debug.fd
|
||||||
|
|
||||||
build $builddir/popcorn.elf | $builddir/popcorn.elf.debug : strip $builddir/host/popcorn.elf
|
build $builddir/popcorn.elf | $builddir/popcorn.elf.debug : strip $builddir/host/popcorn.elf
|
||||||
name = kernel
|
name = kernel
|
||||||
@@ -177,5 +180,5 @@ build $builddir/popcorn.img : makefat | $
|
|||||||
$builddir/fatroot/efi/boot/bootx64.efi
|
$builddir/fatroot/efi/boot/bootx64.efi
|
||||||
name = popcorn.img
|
name = popcorn.img
|
||||||
|
|
||||||
# vim: et ts=4 sts=4 sw=4
|
# vim: ft=ninja et ts=4 sts=4 sw=4
|
||||||
|
|
||||||
|
|||||||
@@ -2,18 +2,13 @@
|
|||||||
{% block variables %}
|
{% block variables %}
|
||||||
{{ super() }}
|
{{ super() }}
|
||||||
|
|
||||||
ld = ld
|
|
||||||
cc = clang
|
|
||||||
cxx = clang++
|
|
||||||
|
|
||||||
ccflags = $ccflags $
|
ccflags = $ccflags $
|
||||||
-DKERNEL_FILENAME=L\"popcorn.elf\" $
|
-DKERNEL_FILENAME=L\"popcorn.elf\" $
|
||||||
-DGNU_EFI_USE_MS_ABI $
|
-DGNU_EFI_USE_MS_ABI $
|
||||||
-DHAVE_USE_MS_ABI $
|
-DHAVE_USE_MS_ABI $
|
||||||
-DEFI_DEBUG=0 $
|
-DEFI_DEBUG=0 $
|
||||||
-DEFI_DEBUG_CLEAR_MEMORY=0 $
|
-DEFI_DEBUG_CLEAR_MEMORY=0 $
|
||||||
-DBOOTLOADER_DEBUG $
|
-DBOOTLOADER_DEBUG
|
||||||
-fPIC
|
|
||||||
|
|
||||||
ldflags = $ldflags $
|
ldflags = $ldflags $
|
||||||
-T ${srcroot}/src/arch/x86_64/boot.ld $
|
-T ${srcroot}/src/arch/x86_64/boot.ld $
|
||||||
@@ -27,3 +22,6 @@ build $builddir/boot.efi : makeefi ${builddir}/{{ module.output }}
|
|||||||
name = boot.efi
|
name = boot.efi
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
# vim: ft=ninja et ts=4 sts=4 sw=4
|
||||||
|
|
||||||
|
|||||||
@@ -2,11 +2,7 @@
|
|||||||
{% block variables %}
|
{% block variables %}
|
||||||
{{ super() }}
|
{{ super() }}
|
||||||
|
|
||||||
libs = $
|
|
||||||
-L${builddir} $
|
|
||||||
{%- for dep in module.libdeps %}
|
|
||||||
-l{{ dep.name }} $
|
|
||||||
{%- endfor %}
|
|
||||||
$libs
|
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
# vim: ft=ninja et ts=4 sts=4 sw=4
|
||||||
|
|
||||||
|
|||||||
@@ -7,3 +7,6 @@ libs = $libs
|
|||||||
ldflags = $ldflags -T ${srcroot}/src/arch/x86_64/kernel.ld
|
ldflags = $ldflags -T ${srcroot}/src/arch/x86_64/kernel.ld
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
# vim: ft=ninja et ts=4 sts=4 sw=4
|
||||||
|
|
||||||
|
|||||||
@@ -5,3 +5,6 @@
|
|||||||
ccflags = $ccflags -ggdb
|
ccflags = $ccflags -ggdb
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
# vim: ft=ninja et ts=4 sts=4 sw=4
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1,4 @@
|
|||||||
{% extends "module.base.j2" %}
|
{% extends "module.base.j2" %}
|
||||||
|
|
||||||
|
# vim: ft=ninja et ts=4 sts=4 sw=4
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
{% extends "target.default.j2" %}
|
{% extends "target.default.j2" %}
|
||||||
|
|
||||||
{% block binaries %}
|
{% block binaries %}
|
||||||
ld = ld
|
|
||||||
cc = clang
|
cc = clang
|
||||||
cxx = clang++
|
cxx = clang++
|
||||||
|
ld = ld
|
||||||
|
ar = ar
|
||||||
nasm = nasm
|
nasm = nasm
|
||||||
|
objcopy = objcopy
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block variables %}
|
{% block variables %}
|
||||||
@@ -18,12 +20,13 @@ ccflags = $ccflags $
|
|||||||
-mno-sse $
|
-mno-sse $
|
||||||
-fno-omit-frame-pointer $
|
-fno-omit-frame-pointer $
|
||||||
-mno-red-zone $
|
-mno-red-zone $
|
||||||
-fshort-wchar
|
-fshort-wchar $
|
||||||
|
-D__ELF__ $
|
||||||
|
-fPIC
|
||||||
|
|
||||||
cxxflags = $cxxflags $
|
cxxflags = $cxxflags $
|
||||||
-nostdlibinc $
|
|
||||||
-fno-exceptions $
|
-fno-exceptions $
|
||||||
-fno-rtti
|
-fno-rtti $
|
||||||
|
|
||||||
ldflags = $ldflags $
|
ldflags = $ldflags $
|
||||||
-g $
|
-g $
|
||||||
@@ -33,3 +36,6 @@ ldflags = $ldflags $
|
|||||||
-nostartfiles
|
-nostartfiles
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
# vim: ft=ninja et ts=4 sts=4 sw=4
|
||||||
|
|
||||||
|
|||||||
@@ -22,3 +22,5 @@ build ${builddir}/cxx.defs : dump_cxx_defs | {{ buildfile }}
|
|||||||
build ${builddir}/cc.run : dump_cc_run | {{ buildfile }}
|
build ${builddir}/cc.run : dump_cc_run | {{ buildfile }}
|
||||||
build ${builddir}/cxx.run : dump_cxx_run | {{ buildfile }}
|
build ${builddir}/cxx.run : dump_cxx_run | {{ buildfile }}
|
||||||
|
|
||||||
|
# vim: ft=ninja et ts=4 sts=4 sw=4
|
||||||
|
|
||||||
|
|||||||
@@ -40,4 +40,6 @@ ldflags = $ldflags $
|
|||||||
-Bstatic
|
-Bstatic
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
# vim: et ts=4 sts=4 sw=4
|
|
||||||
|
# vim: ft=ninja et ts=4 sts=4 sw=4
|
||||||
|
|
||||||
|
|||||||
@@ -5,4 +5,6 @@
|
|||||||
ccflags = $ccflags -g -ggdb
|
ccflags = $ccflags -g -ggdb
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
# vim: et ts=4 sts=4 sw=4
|
|
||||||
|
# vim: ft=ninja et ts=4 sts=4 sw=4
|
||||||
|
|
||||||
|
|||||||
@@ -6,4 +6,6 @@ GUID(0x964e5b22,0x6459,0x11d2,0x8e,0x39,0x00,0xa0,0xc9,0x69,0x72,0x3b, guid_simp
|
|||||||
GUID(0x09576e91,0x6d3f,0x11d2,0x8e,0x39,0x00,0xa0,0xc9,0x69,0x72,0x3b, guid_device_path);
|
GUID(0x09576e91,0x6d3f,0x11d2,0x8e,0x39,0x00,0xa0,0xc9,0x69,0x72,0x3b, guid_device_path);
|
||||||
GUID(0x8b843e20,0x8132,0x4852,0x90,0xcc,0x55,0x1a,0x4e,0x4a,0x7f,0x1c, guid_device_path_to_text);
|
GUID(0x8b843e20,0x8132,0x4852,0x90,0xcc,0x55,0x1a,0x4e,0x4a,0x7f,0x1c, guid_device_path_to_text);
|
||||||
|
|
||||||
|
GUID(0x10d0669c,0x9ec6,0x4268,0xbc,0x48,0xff,0x74,0x75,0x21,0xfe,0x07, guid_popcorn_vendor);
|
||||||
|
|
||||||
// vim: ft=c
|
// vim: ft=c
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ loader_load_elf(
|
|||||||
header.machine != 0x3e)
|
header.machine != 0x3e)
|
||||||
CHECK_EFI_STATUS_OR_RETURN(EFI_LOAD_ERROR, L"ELF load error: wrong machine architecture");
|
CHECK_EFI_STATUS_OR_RETURN(EFI_LOAD_ERROR, L"ELF load error: wrong machine architecture");
|
||||||
|
|
||||||
con_debug(L"ELF is valid, entrypoint %lu\r\n", header.entrypoint);
|
con_debug(L"ELF is valid, entrypoint %lx\r\n", header.entrypoint);
|
||||||
|
|
||||||
data->kernel_entry = (void *)header.entrypoint;
|
data->kernel_entry = (void *)header.entrypoint;
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
#include "console.h"
|
#include "console.h"
|
||||||
#include "guids.h"
|
#include "guids.h"
|
||||||
#include "kernel_data.h"
|
#include "kernel_args.h"
|
||||||
#include "loader.h"
|
#include "loader.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
@@ -34,7 +34,51 @@ struct kernel_header {
|
|||||||
};
|
};
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
using kernel_entry = void (*)(popcorn_data *);
|
using kernel_entry = void (*)(kernel_args *);
|
||||||
|
|
||||||
|
static void
|
||||||
|
type_to_wchar(wchar_t *into, uint32_t type)
|
||||||
|
{
|
||||||
|
for (int j=0; j<4; ++j)
|
||||||
|
into[j] = static_cast<wchar_t>(reinterpret_cast<char *>(&type)[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
detect_debug_mode(EFI_RUNTIME_SERVICES *run, kernel_args *header) {
|
||||||
|
wchar_t var_name[] = L"debug";
|
||||||
|
|
||||||
|
EFI_STATUS status;
|
||||||
|
uint8_t debug = 0;
|
||||||
|
UINTN var_size = sizeof(debug);
|
||||||
|
|
||||||
|
#ifdef __POPCORN_SET_DEBUG_UEFI_VAR__
|
||||||
|
debug = __POPCORN_SET_DEBUG_UEFI_VAR__;
|
||||||
|
uint32_t attrs =
|
||||||
|
EFI_VARIABLE_NON_VOLATILE |
|
||||||
|
EFI_VARIABLE_BOOTSERVICE_ACCESS |
|
||||||
|
EFI_VARIABLE_RUNTIME_ACCESS;
|
||||||
|
status = run->SetVariable(
|
||||||
|
var_name,
|
||||||
|
&guid_popcorn_vendor,
|
||||||
|
attrs,
|
||||||
|
var_size,
|
||||||
|
&debug);
|
||||||
|
CHECK_EFI_STATUS_OR_RETURN(status, "detect_debug_mode::SetVariable");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
status = run->GetVariable(
|
||||||
|
var_name,
|
||||||
|
&guid_popcorn_vendor,
|
||||||
|
nullptr,
|
||||||
|
&var_size,
|
||||||
|
&debug);
|
||||||
|
CHECK_EFI_STATUS_OR_RETURN(status, "detect_debug_mode::GetVariable");
|
||||||
|
|
||||||
|
if (debug)
|
||||||
|
header->flags |= POPCORN_FLAG_DEBUG;
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" EFI_STATUS
|
extern "C" EFI_STATUS
|
||||||
efi_main(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table)
|
efi_main(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table)
|
||||||
@@ -73,14 +117,13 @@ efi_main(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table)
|
|||||||
status = memory_get_map_length(bootsvc, &data_length);
|
status = memory_get_map_length(bootsvc, &data_length);
|
||||||
CHECK_EFI_STATUS_OR_FAIL(status);
|
CHECK_EFI_STATUS_OR_FAIL(status);
|
||||||
|
|
||||||
size_t header_size = sizeof(popcorn_data);
|
size_t header_size = sizeof(kernel_args);
|
||||||
const size_t header_align = alignof(popcorn_data);
|
const size_t header_align = alignof(kernel_args);
|
||||||
if (header_size % header_align)
|
if (header_size % header_align)
|
||||||
header_size += header_align - (header_size % header_align);
|
header_size += header_align - (header_size % header_align);
|
||||||
|
|
||||||
data_length += header_size;
|
data_length += header_size;
|
||||||
|
|
||||||
|
|
||||||
// Load the kernel image from disk and check it
|
// Load the kernel image from disk and check it
|
||||||
//
|
//
|
||||||
console::print(L"Loading kernel into memory...\r\n");
|
console::print(L"Loading kernel into memory...\r\n");
|
||||||
@@ -111,12 +154,12 @@ efi_main(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table)
|
|||||||
|
|
||||||
// Set up the kernel data pages to pass to the kernel
|
// Set up the kernel data pages to pass to the kernel
|
||||||
//
|
//
|
||||||
struct popcorn_data *data_header = (struct popcorn_data *)load.data;
|
struct kernel_args *data_header = (struct kernel_args *)load.data;
|
||||||
memory_mark_pointer_fixup((void **)&data_header);
|
memory_mark_pointer_fixup((void **)&data_header);
|
||||||
|
|
||||||
data_header->magic = DATA_HEADER_MAGIC;
|
data_header->magic = DATA_HEADER_MAGIC;
|
||||||
data_header->version = DATA_HEADER_VERSION;
|
data_header->version = DATA_HEADER_VERSION;
|
||||||
data_header->length = sizeof(struct popcorn_data);
|
data_header->length = sizeof(struct kernel_args);
|
||||||
|
|
||||||
data_header->scratch_pages = SCRATCH_PAGES;
|
data_header->scratch_pages = SCRATCH_PAGES;
|
||||||
data_header->flags = 0;
|
data_header->flags = 0;
|
||||||
@@ -168,6 +211,8 @@ efi_main(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table)
|
|||||||
data_header->memory_map_length = map.length;
|
data_header->memory_map_length = map.length;
|
||||||
data_header->memory_map_desc_size = map.size;
|
data_header->memory_map_desc_size = map.size;
|
||||||
|
|
||||||
|
detect_debug_mode(runsvc, data_header);
|
||||||
|
|
||||||
// bootsvc->Stall(5000000);
|
// bootsvc->Stall(5000000);
|
||||||
|
|
||||||
status = bootsvc->ExitBootServices(image_handle, map.key);
|
status = bootsvc->ExitBootServices(image_handle, map.key);
|
||||||
|
|||||||
@@ -7,8 +7,10 @@
|
|||||||
#define DATA_HEADER_MAGIC 0x600dda7a
|
#define DATA_HEADER_MAGIC 0x600dda7a
|
||||||
#define DATA_HEADER_VERSION 1
|
#define DATA_HEADER_VERSION 1
|
||||||
|
|
||||||
|
#define POPCORN_FLAG_DEBUG 0x00000001
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
struct popcorn_data {
|
struct kernel_args {
|
||||||
uint32_t magic;
|
uint32_t magic;
|
||||||
uint16_t version;
|
uint16_t version;
|
||||||
uint16_t length;
|
uint16_t length;
|
||||||
@@ -18,9 +18,3 @@ __kernel_assert(const char *file, unsigned line, const char *message)
|
|||||||
__asm__ ( "int $0e7h" );
|
__asm__ ( "int $0e7h" );
|
||||||
while (1) __asm__ ("hlt");
|
while (1) __asm__ ("hlt");
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" [[noreturn]] void
|
|
||||||
__assert_fail(const char *message, const char *file, unsigned int line, const char *function)
|
|
||||||
{
|
|
||||||
__kernel_assert(file, line, message);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
#include "gdt.h"
|
#include "gdt.h"
|
||||||
#include "interrupts.h"
|
#include "interrupts.h"
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
#include "kernel_data.h"
|
#include "kernel_args.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "page_manager.h"
|
#include "page_manager.h"
|
||||||
#include "scheduler.h"
|
#include "scheduler.h"
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
#include "syscall.h"
|
#include "syscall.h"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
void kernel_main(popcorn_data *header);
|
void kernel_main(kernel_args *header);
|
||||||
void *__bss_start, *__bss_end;
|
void *__bss_start, *__bss_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,28 +39,21 @@ init_console()
|
|||||||
|
|
||||||
log::init(cons);
|
log::init(cons);
|
||||||
log::enable(logs::apic, log::level::info);
|
log::enable(logs::apic, log::level::info);
|
||||||
log::enable(logs::device, log::level::info);
|
log::enable(logs::device, log::level::debug);
|
||||||
|
log::enable(logs::paging, log::level::info);
|
||||||
|
|
||||||
log::enable(logs::driver, log::level::debug);
|
log::enable(logs::driver, log::level::debug);
|
||||||
log::enable(logs::memory, log::level::debug);
|
log::enable(logs::memory, log::level::debug);
|
||||||
log::enable(logs::fs, log::level::debug);
|
log::enable(logs::fs, log::level::debug);
|
||||||
log::enable(logs::task, log::level::debug);
|
log::enable(logs::task, log::level::debug);
|
||||||
log::enable(logs::boot, log::level::debug);
|
log::enable(logs::boot, log::level::debug);
|
||||||
log::enable(logs::paging, log::level::debug);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
kernel_main(popcorn_data *header)
|
kernel_main(kernel_args *header)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
bool waiting = header && (header->flags && POPCORN_FLAG_DEBUG);
|
||||||
// Run `waf configure --debug` to enable compiling with DEBUG turned on.
|
|
||||||
// Then attach to QEMU's gdb server and `set waiting = false` to start
|
|
||||||
// the kernel. This compensates for GDB's poor handling of QEMU going
|
|
||||||
// through the x86 PC startup and switching to 64 bit mode when you
|
|
||||||
// attach to qemu with the -S option.
|
|
||||||
bool waiting = true;
|
|
||||||
while (waiting);
|
while (waiting);
|
||||||
#endif
|
|
||||||
|
|
||||||
kutil::assert_set_callback(__kernel_assert);
|
kutil::assert_set_callback(__kernel_assert);
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
#include <algorithm>
|
|
||||||
|
|
||||||
#include "kutil/frame_allocator.h"
|
#include "kutil/frame_allocator.h"
|
||||||
|
|
||||||
namespace kutil {
|
namespace kutil {
|
||||||
@@ -81,7 +79,7 @@ frame_allocator::allocate(size_t count, uintptr_t *address)
|
|||||||
|
|
||||||
auto *first = m_free.front();
|
auto *first = m_free.front();
|
||||||
|
|
||||||
unsigned n = std::min(count, static_cast<size_t>(first->count));
|
unsigned n = count < first->count ? count : first->count;
|
||||||
*address = first->address;
|
*address = first->address;
|
||||||
|
|
||||||
if (count >= first->count) {
|
if (count >= first->count) {
|
||||||
|
|||||||
Reference in New Issue
Block a user