diff --git a/assets/ovmf/x64/OVMF.fd b/assets/ovmf/x64/ovmf.fd similarity index 99% rename from assets/ovmf/x64/OVMF.fd rename to assets/ovmf/x64/ovmf.fd index 88fd978..96d7e09 100644 Binary files a/assets/ovmf/x64/OVMF.fd and b/assets/ovmf/x64/ovmf.fd differ diff --git a/assets/ovmf/x64/ovmf_debug.fd b/assets/ovmf/x64/ovmf_debug.fd new file mode 100644 index 0000000..c13c912 Binary files /dev/null and b/assets/ovmf/x64/ovmf_debug.fd differ diff --git a/qemu.sh b/qemu.sh index 2f98de2..2aee946 100755 --- a/qemu.sh +++ b/qemu.sh @@ -1,13 +1,16 @@ #!/usr/bin/env bash build="$(dirname $0)/build" +assets="$(dirname $0)/assets" debug="" +flash_name="ovmf.fd" gfx="-nographic" for arg in $@; do case "${arg}" in --debug) debug="-s" + flash_name="ovmf_debug.fd" ;; --gfx) gfx="" @@ -28,11 +31,16 @@ if ! ninja -C "${build}"; then fi 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 +touch "${build}/popd_table.data" 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" \ -monitor telnet:localhost:45454,server,nowait \ -smp 1 \ diff --git a/scripts/templates/build.ninja.j2 b/scripts/templates/build.ninja.j2 index f421b79..11b4568 100644 --- a/scripts/templates/build.ninja.j2 +++ b/scripts/templates/build.ninja.j2 @@ -152,8 +152,11 @@ build $ $modulefile $ {{ generator }} -build $builddir/flash.img : cp $srcroot/assets/ovmf/x64/OVMF.fd - name = flash.img +build $builddir/ovmf.fd : cp $srcroot/assets/ovmf/x64/ovmf.fd + 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 name = kernel @@ -177,5 +180,5 @@ build $builddir/popcorn.img : makefat | $ $builddir/fatroot/efi/boot/bootx64.efi name = popcorn.img -# vim: et ts=4 sts=4 sw=4 +# vim: ft=ninja et ts=4 sts=4 sw=4 diff --git a/scripts/templates/exe.boot.j2 b/scripts/templates/exe.boot.j2 index 0e3155e..7d69764 100644 --- a/scripts/templates/exe.boot.j2 +++ b/scripts/templates/exe.boot.j2 @@ -2,18 +2,13 @@ {% block variables %} {{ super() }} -ld = ld -cc = clang -cxx = clang++ - ccflags = $ccflags $ -DKERNEL_FILENAME=L\"popcorn.elf\" $ -DGNU_EFI_USE_MS_ABI $ -DHAVE_USE_MS_ABI $ -DEFI_DEBUG=0 $ -DEFI_DEBUG_CLEAR_MEMORY=0 $ - -DBOOTLOADER_DEBUG $ - -fPIC + -DBOOTLOADER_DEBUG ldflags = $ldflags $ -T ${srcroot}/src/arch/x86_64/boot.ld $ @@ -27,3 +22,6 @@ build $builddir/boot.efi : makeefi ${builddir}/{{ module.output }} name = boot.efi {% endblock %} + +# vim: ft=ninja et ts=4 sts=4 sw=4 + diff --git a/scripts/templates/exe.default.j2 b/scripts/templates/exe.default.j2 index f3c0b8f..90c7395 100644 --- a/scripts/templates/exe.default.j2 +++ b/scripts/templates/exe.default.j2 @@ -2,11 +2,7 @@ {% block variables %} {{ super() }} -libs = $ - -L${builddir} $ - {%- for dep in module.libdeps %} - -l{{ dep.name }} $ - {%- endfor %} - $libs - {% endblock %} + +# vim: ft=ninja et ts=4 sts=4 sw=4 + diff --git a/scripts/templates/exe.kernel.j2 b/scripts/templates/exe.kernel.j2 index 02a95e5..fa8a8a6 100644 --- a/scripts/templates/exe.kernel.j2 +++ b/scripts/templates/exe.kernel.j2 @@ -7,3 +7,6 @@ libs = $libs ldflags = $ldflags -T ${srcroot}/src/arch/x86_64/kernel.ld {% endblock %} + +# vim: ft=ninja et ts=4 sts=4 sw=4 + diff --git a/scripts/templates/exe.tests.j2 b/scripts/templates/exe.tests.j2 index 2c197c8..af8e2c2 100644 --- a/scripts/templates/exe.tests.j2 +++ b/scripts/templates/exe.tests.j2 @@ -5,3 +5,6 @@ ccflags = $ccflags -ggdb {% endblock %} + +# vim: ft=ninja et ts=4 sts=4 sw=4 + diff --git a/scripts/templates/lib.default.j2 b/scripts/templates/lib.default.j2 index 858923e..ccc74b7 100644 --- a/scripts/templates/lib.default.j2 +++ b/scripts/templates/lib.default.j2 @@ -1 +1,4 @@ {% extends "module.base.j2" %} + +# vim: ft=ninja et ts=4 sts=4 sw=4 + diff --git a/scripts/templates/target.boot.j2 b/scripts/templates/target.boot.j2 index e266d98..15787ca 100644 --- a/scripts/templates/target.boot.j2 +++ b/scripts/templates/target.boot.j2 @@ -1,35 +1,41 @@ {% extends "target.default.j2" %} {% block binaries %} -ld = ld cc = clang cxx = clang++ +ld = ld +ar = ar nasm = nasm +objcopy = objcopy {% endblock %} {% block variables %} ccflags = $ccflags $ - -ggdb $ - -nostdlib $ - -ffreestanding $ - -nodefaultlibs $ - -fno-builtin $ - -mno-sse $ - -fno-omit-frame-pointer $ - -mno-red-zone $ - -fshort-wchar + -ggdb $ + -nostdlib $ + -ffreestanding $ + -nodefaultlibs $ + -fno-builtin $ + -mno-sse $ + -fno-omit-frame-pointer $ + -mno-red-zone $ + -fshort-wchar $ + -D__ELF__ $ + -fPIC cxxflags = $cxxflags $ - -nostdlibinc $ - -fno-exceptions $ - -fno-rtti + -fno-exceptions $ + -fno-rtti $ ldflags = $ldflags $ - -g $ - -nostdlib $ - -znocombreloc $ + -g $ + -nostdlib $ + -znocombreloc $ -Bsymbolic $ - -nostartfiles + -nostartfiles {% endblock %} + +# vim: ft=ninja et ts=4 sts=4 sw=4 + diff --git a/scripts/templates/target.default.j2 b/scripts/templates/target.default.j2 index 31c9191..5142434 100644 --- a/scripts/templates/target.default.j2 +++ b/scripts/templates/target.default.j2 @@ -22,3 +22,5 @@ build ${builddir}/cxx.defs : dump_cxx_defs | {{ buildfile }} build ${builddir}/cc.run : dump_cc_run | {{ buildfile }} build ${builddir}/cxx.run : dump_cxx_run | {{ buildfile }} +# vim: ft=ninja et ts=4 sts=4 sw=4 + diff --git a/scripts/templates/target.host.j2 b/scripts/templates/target.host.j2 index f12db58..413b1a7 100644 --- a/scripts/templates/target.host.j2 +++ b/scripts/templates/target.host.j2 @@ -40,4 +40,6 @@ ldflags = $ldflags $ -Bstatic {% endblock %} -# vim: et ts=4 sts=4 sw=4 + +# vim: ft=ninja et ts=4 sts=4 sw=4 + diff --git a/scripts/templates/target.native.j2 b/scripts/templates/target.native.j2 index a1adeca..e631b5c 100644 --- a/scripts/templates/target.native.j2 +++ b/scripts/templates/target.native.j2 @@ -5,4 +5,6 @@ ccflags = $ccflags -g -ggdb {% endblock %} -# vim: et ts=4 sts=4 sw=4 + +# vim: ft=ninja et ts=4 sts=4 sw=4 + diff --git a/src/boot/guids.inc b/src/boot/guids.inc index 3cf742b..d925f5a 100644 --- a/src/boot/guids.inc +++ b/src/boot/guids.inc @@ -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(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 diff --git a/src/boot/loader.cpp b/src/boot/loader.cpp index d0b630f..1261c5b 100644 --- a/src/boot/loader.cpp +++ b/src/boot/loader.cpp @@ -143,7 +143,7 @@ loader_load_elf( header.machine != 0x3e) 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; diff --git a/src/boot/main.cpp b/src/boot/main.cpp index f1a250c..bc5e2bd 100644 --- a/src/boot/main.cpp +++ b/src/boot/main.cpp @@ -5,7 +5,7 @@ #include "console.h" #include "guids.h" -#include "kernel_data.h" +#include "kernel_args.h" #include "loader.h" #include "memory.h" #include "utility.h" @@ -34,7 +34,51 @@ struct kernel_header { }; #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(reinterpret_cast(&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 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); CHECK_EFI_STATUS_OR_FAIL(status); - size_t header_size = sizeof(popcorn_data); - const size_t header_align = alignof(popcorn_data); + size_t header_size = sizeof(kernel_args); + const size_t header_align = alignof(kernel_args); if (header_size % header_align) header_size += header_align - (header_size % header_align); data_length += header_size; - // Load the kernel image from disk and check it // 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 // - 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); data_header->magic = DATA_HEADER_MAGIC; 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->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_desc_size = map.size; + detect_debug_mode(runsvc, data_header); + // bootsvc->Stall(5000000); status = bootsvc->ExitBootServices(image_handle, map.key); diff --git a/src/include/kernel_data.h b/src/include/kernel_args.h similarity index 91% rename from src/include/kernel_data.h rename to src/include/kernel_args.h index 113e692..f7300a6 100644 --- a/src/include/kernel_data.h +++ b/src/include/kernel_args.h @@ -7,8 +7,10 @@ #define DATA_HEADER_MAGIC 0x600dda7a #define DATA_HEADER_VERSION 1 +#define POPCORN_FLAG_DEBUG 0x00000001 + #pragma pack(push, 1) -struct popcorn_data { +struct kernel_args { uint32_t magic; uint16_t version; uint16_t length; diff --git a/src/kernel/assert.cpp b/src/kernel/assert.cpp index 9465b62..263b953 100644 --- a/src/kernel/assert.cpp +++ b/src/kernel/assert.cpp @@ -18,9 +18,3 @@ __kernel_assert(const char *file, unsigned line, const char *message) __asm__ ( "int $0e7h" ); 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); -} diff --git a/src/kernel/main.cpp b/src/kernel/main.cpp index bde4557..9524e43 100644 --- a/src/kernel/main.cpp +++ b/src/kernel/main.cpp @@ -11,7 +11,7 @@ #include "gdt.h" #include "interrupts.h" #include "io.h" -#include "kernel_data.h" +#include "kernel_args.h" #include "log.h" #include "page_manager.h" #include "scheduler.h" @@ -20,7 +20,7 @@ #include "syscall.h" extern "C" { - void kernel_main(popcorn_data *header); + void kernel_main(kernel_args *header); void *__bss_start, *__bss_end; } @@ -39,28 +39,21 @@ init_console() log::init(cons); 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::memory, log::level::debug); log::enable(logs::fs, log::level::debug); log::enable(logs::task, log::level::debug); log::enable(logs::boot, log::level::debug); - log::enable(logs::paging, log::level::debug); } void -kernel_main(popcorn_data *header) +kernel_main(kernel_args *header) { -#ifdef 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; + bool waiting = header && (header->flags && POPCORN_FLAG_DEBUG); while (waiting); -#endif kutil::assert_set_callback(__kernel_assert); diff --git a/src/libraries/kutil/frame_allocator.cpp b/src/libraries/kutil/frame_allocator.cpp index 59d8b6c..a56450e 100644 --- a/src/libraries/kutil/frame_allocator.cpp +++ b/src/libraries/kutil/frame_allocator.cpp @@ -1,5 +1,3 @@ -#include - #include "kutil/frame_allocator.h" namespace kutil { @@ -81,7 +79,7 @@ frame_allocator::allocate(size_t count, uintptr_t *address) auto *first = m_free.front(); - unsigned n = std::min(count, static_cast(first->count)); + unsigned n = count < first->count ? count : first->count; *address = first->address; if (count >= first->count) {