Allow debug option to be communicated at boot

This commit is contained in:
Justin C. Miller
2019-03-11 03:04:57 -07:00
parent 74a5c301f8
commit 870ca1db45
20 changed files with 128 additions and 68 deletions

Binary file not shown.

12
qemu.sh
View File

@@ -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
tmux split-window "sleep 1; telnet localhost 45454" & if [[ -n $debug ]]; then
tmux split-window "gdb ${build}/popcorn.elf" &
else
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 \

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -5,3 +5,6 @@
ccflags = $ccflags -ggdb ccflags = $ccflags -ggdb
{% endblock %} {% endblock %}
# vim: ft=ninja et ts=4 sts=4 sw=4

View File

@@ -1 +1,4 @@
{% extends "module.base.j2" %} {% extends "module.base.j2" %}
# vim: ft=ninja et ts=4 sts=4 sw=4

View File

@@ -1,35 +1,41 @@
{% 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 %}
ccflags = $ccflags $ ccflags = $ccflags $
-ggdb $ -ggdb $
-nostdlib $ -nostdlib $
-ffreestanding $ -ffreestanding $
-nodefaultlibs $ -nodefaultlibs $
-fno-builtin $ -fno-builtin $
-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 $
-nostdlib $ -nostdlib $
-znocombreloc $ -znocombreloc $
-Bsymbolic $ -Bsymbolic $
-nostartfiles -nostartfiles
{% endblock %} {% endblock %}
# vim: ft=ninja et ts=4 sts=4 sw=4

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -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);

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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) {