diff --git a/configs/kernel-debug.yaml b/configs/kernel-debug.yaml index 77fd39f..1d60d7b 100644 --- a/configs/kernel-debug.yaml +++ b/configs/kernel-debug.yaml @@ -15,11 +15,14 @@ variables: "-ffreestanding", "-nodefaultlibs", "-fno-builtin", + "-fno-plt", "-mno-sse", "-fno-omit-frame-pointer", "-mno-red-zone", "-mcmodel=kernel", + "-fvisibility=hidden", + "-fvisibility-inlines-hidden", "-g3", "-ggdb", diff --git a/configs/rules.ninja b/configs/rules.ninja index ad32296..ecfe1df 100644 --- a/configs/rules.ninja +++ b/configs/rules.ninja @@ -75,7 +75,7 @@ rule strip command = $ cp $in $out; $ objcopy --only-keep-debug $out $debug; $ - strip -g $out; $ + strip --discard-all -g $out; $ objcopy --add-gnu-debuglink=$debug $out rule touch diff --git a/external/uefi/boot_services.h b/external/uefi/boot_services.h index 363a9bb..2ac9f61 100644 --- a/external/uefi/boot_services.h +++ b/external/uefi/boot_services.h @@ -22,7 +22,7 @@ namespace bs_impl { using create_event = status (*)(evt, tpl, event_notify, void*, event*); using exit_boot_services = status (*)(handle, size_t); using locate_protocol = status (*)(const guid*, void*, void**); - using copy_mem = void (*)(void*, void*, size_t); + using copy_mem = void (*)(void*, const void*, size_t); using set_mem = void (*)(void*, uint64_t, uint8_t); } diff --git a/src/boot/allocator.cpp b/src/boot/allocator.cpp index e1ac31a..7bdc7c0 100644 --- a/src/boot/allocator.cpp +++ b/src/boot/allocator.cpp @@ -155,7 +155,7 @@ allocator::memset(void *start, size_t size, uint8_t value) } void -allocator::copy(void *to, void *from, size_t size) +allocator::copy(void *to, const void *from, size_t size) { m_bs.copy_mem(to, from, size); } diff --git a/src/boot/allocator.h b/src/boot/allocator.h index d0b0f7e..fcb53ff 100644 --- a/src/boot/allocator.h +++ b/src/boot/allocator.h @@ -35,7 +35,7 @@ public: module * allocate_module(); void memset(void *start, size_t size, uint8_t value); - void copy(void *to, void *from, size_t size); + void copy(void *to, const void *from, size_t size); inline void zero(void *start, size_t size) { memset(start, size, 0); } diff --git a/src/boot/loader.cpp b/src/boot/loader.cpp index 63b4075..7d0d3c9 100644 --- a/src/boot/loader.cpp +++ b/src/boot/loader.cpp @@ -35,15 +35,42 @@ load_file( return b; } +void +verify_kernel_header(elf::file &kernel, util::const_buffer data) +{ + status_line status {L"Verifying kernel header"}; + + // The header should be the first non-null section + const elf::section_header § = kernel.sections()[1]; + + const bootproto::header *header = + reinterpret_cast( + util::offset_pointer(data.pointer, sect.offset)); + + if (header->magic != bootproto::header_magic) + error::raise(uefi::status::load_error, L"Bad kernel magic number"); + + if (header->length < sizeof(bootproto::header)) + error::raise(uefi::status::load_error, L"Bad kernel header length"); + + if (header->version < bootproto::min_header_version) + error::raise(uefi::status::unsupported, L"Kernel header version not supported"); + + console::print(L" Loaded kernel vserion: %d.%d.%d %x\r\n", + header->version_major, header->version_minor, header->version_patch, + header->version_gitsha); +} + bootproto::program * load_program( fs::file &disk, const wchar_t *name, - const descriptor &desc) + const descriptor &desc, + bool verify) { status_line status(L"Loading program", name); - util::buffer data = load_file(disk, desc.path); + util::const_buffer data = load_file(disk, desc.path); elf::file program(data.pointer, data.count); if (!program.valid()) { @@ -60,6 +87,9 @@ load_program( error::raise(uefi::status::load_error, L"ELF file not valid"); } + if (verify) + verify_kernel_header(program, data); + size_t num_sections = 0; for (auto &seg : program.programs()) { if (seg.type == elf::segment_type::load) @@ -85,7 +115,7 @@ load_program( size_t page_count = memory::bytes_to_pages(mem_size); void *pages = g_alloc.allocate_pages(page_count, alloc_type::program, true); - void *source = util::offset_pointer(data.pointer, seg.offset); + const void *source = util::offset_pointer(data.pointer, seg.offset); g_alloc.copy(util::offset_pointer(pages, prelude), source, seg.file_size); section.phys_addr = reinterpret_cast(pages); section.virt_addr = virt_addr; @@ -116,33 +146,5 @@ load_module( mod->data = load_file(disk, path); } -void -verify_kernel_header(bootproto::program &program) -{ - status_line status(L"Verifying kernel header"); - - const bootproto::header *header = - reinterpret_cast(program.sections[0].phys_addr); - - if (header->magic != bootproto::header_magic) - error::raise(uefi::status::load_error, L"Bad kernel magic number"); - - if (header->length < sizeof(bootproto::header)) - error::raise(uefi::status::load_error, L"Bad kernel header length"); - - if (header->version < bootproto::min_header_version) - error::raise(uefi::status::unsupported, L"Kernel header version not supported"); - - console::print(L" Loaded kernel vserion: %d.%d.%d %x\r\n", - header->version_major, header->version_minor, header->version_patch, - header->version_gitsha); - - /* - for (auto §ion : program.sections) - console::print(L" Section: p:0x%lx v:0x%lx fs:0x%x ms:0x%x\r\n", - section.phys_addr, section.virt_addr, section.file_size, section.mem_size); - */ -} - } // namespace loader } // namespace boot diff --git a/src/boot/loader.h b/src/boot/loader.h index 3f6d9c1..7b713c2 100644 --- a/src/boot/loader.h +++ b/src/boot/loader.h @@ -28,14 +28,16 @@ load_file( const wchar_t *path); /// Parse and load an ELF file in memory into a loaded image. -/// \arg disk The opened UEFI filesystem to load from -/// \arg desc The descriptor identifying the program -/// \arg name The human-readable name of the program to load +/// \arg disk The opened UEFI filesystem to load from +/// \arg desc The descriptor identifying the program +/// \arg name The human-readable name of the program to load +/// \arg verify If this is the kernel and should have its header verified bootproto::program * load_program( fs::file &disk, const wchar_t *name, - const descriptor &desc); + const descriptor &desc, + bool verify = false); /// Load a file from disk into memory, creating an init args module /// \arg disk The opened UEFI filesystem to load from @@ -51,10 +53,5 @@ load_module( bootproto::module_type type, uint16_t subtype); -/// Verify that a loaded ELF has the j6 kernel header -/// \arg program The program to check for a header -void -verify_kernel_header(bootproto::program &program); - } // namespace loader } // namespace boot diff --git a/src/boot/main.cpp b/src/boot/main.cpp index 8dd03d9..029023b 100644 --- a/src/boot/main.cpp +++ b/src/boot/main.cpp @@ -75,7 +75,7 @@ load_resources(bootproto::args *args, video::screen *screen, uefi::handle image, fs::file bc_data = disk.open(L"jsix\\boot.conf"); bootconfig bc {bc_data.load(), bs}; - args->kernel = loader::load_program(disk, L"kernel", bc.kernel()); + args->kernel = loader::load_program(disk, L"kernel", bc.kernel(), true); args->init = loader::load_program(disk, L"init server", bc.init()); args->flags = static_cast(bc.flags()); @@ -106,8 +106,6 @@ load_resources(bootproto::args *args, video::screen *screen, uefi::handle image, } } } - - loader::verify_kernel_header(*args->kernel); } memory::efi_mem_map diff --git a/src/kernel/boot.s b/src/kernel/boot.s index 1ec9049..b8075c9 100644 --- a/src/kernel/boot.s +++ b/src/kernel/boot.s @@ -2,7 +2,7 @@ MAGIC equ 'j6KERNEL' ; jsix kernel header magic number section .header align 8 -global _kernel_header +global _kernel_header: data hidden _kernel_header: dq MAGIC ; Kernel header magic dw 32 ; Kernel header length @@ -16,8 +16,8 @@ _kernel_header: section .text align 16 -global _kernel_start:function (_kernel_start.end - _kernel_start) -global _kernel_start.real +global _kernel_start: function hidden (_kernel_start.end - _kernel_start) +global _kernel_start.real: function hidden _kernel_start: push rbp ; Never executed, fake function prelude mov rbp, rsp ; to calm down gdb @@ -36,18 +36,18 @@ _kernel_start: ; the scheduler to take over .end: -global bsp_idle:function (bsp_idle.end - bsp_idle) +global bsp_idle: function hidden (bsp_idle.end - bsp_idle) bsp_idle: hlt jmp bsp_idle .end: -global interrupts_enable +global interrupts_enable: function hidden interrupts_enable: sti ret -global interrupts_disable +global interrupts_disable: function hidden interrupts_disable: cli ret @@ -57,5 +57,5 @@ align 0x100 idle_stack_begin: resb 0x4000 ; 16KiB stack space -global idle_stack_end +global idle_stack_end: data hidden idle_stack_end: diff --git a/src/kernel/debug.s b/src/kernel/debug.s index f86130b..e7558ff 100644 --- a/src/kernel/debug.s +++ b/src/kernel/debug.s @@ -1,32 +1,32 @@ -global get_rsp +global get_rsp: function hidden get_rsp: mov rax, rsp ret -global get_rip +global get_rip: function hidden get_rip: pop rax ; do the same thing as 'ret', except with 'jmp' jmp rax ; with the return address still in rax -global get_caller +global get_caller: function hidden get_caller: ; No prelude - don't touch rsp or rbp mov rax, [rbp+8] ret -global get_grandcaller +global get_grandcaller: function hidden get_grandcaller: ; No prelude - don't touch rsp or rbp mov rax, [rbp] mov rax, [rax+8] ret -global get_gsbase +global get_gsbase: function hidden get_gsbase: rdgsbase rax ret -global _halt +global _halt: function hidden _halt: hlt jmp _halt diff --git a/src/kernel/gdtidt.s b/src/kernel/gdtidt.s index 33fd4db..5490263 100644 --- a/src/kernel/gdtidt.s +++ b/src/kernel/gdtidt.s @@ -1,15 +1,15 @@ -global idt_write +global idt_write: function hidden idt_write: lidt [rdi] ; first arg is the IDT pointer location ret -global idt_load +global idt_load: function hidden idt_load: sidt [rdi] ; first arg is where to write the idtr value ret -global gdt_write +global gdt_write: function hidden gdt_write: lgdt [rdi] ; first arg is the GDT pointer location @@ -28,7 +28,7 @@ gdt_write: ltr cx ; fourth arg is the TSS ret -global gdt_load +global gdt_load: function hidden gdt_load: sgdt [rdi] ; first arg is where to write the gdtr value ret diff --git a/src/kernel/interrupts.s b/src/kernel/interrupts.s index 67eae7a..abf4c19 100644 --- a/src/kernel/interrupts.s +++ b/src/kernel/interrupts.s @@ -3,7 +3,7 @@ section .text extern isr_handler -global isr_handler_prelude:function (isr_handler_prelude.end - isr_handler_prelude) +global isr_handler_prelude: function hidden (isr_handler_prelude.end - isr_handler_prelude) isr_handler_prelude: push rbp ; Never executed, fake function prelude mov rbp, rsp ; to calm down gdb @@ -19,7 +19,7 @@ isr_handler_prelude: .end: extern irq_handler -global irq_handler_prelude:function (irq_handler_prelude.end - irq_handler_prelude) +global irq_handler_prelude: function hidden (irq_handler_prelude.end - irq_handler_prelude) irq_handler_prelude: push rbp ; Never executed, fake function prelude mov rbp, rsp ; to calm down gdb @@ -35,7 +35,7 @@ irq_handler_prelude: ; fall through to isr_handler_return .end: -global isr_handler_return:function (isr_handler_return.end - isr_handler_return) +global isr_handler_return: function hidden (isr_handler_return.end - isr_handler_return) isr_handler_return: check_swap_gs pop_all @@ -45,7 +45,7 @@ isr_handler_return: .end: %macro EMIT_ISR 2 - global %1:function (%1.end - %1) + global %1:function hidden (%1.end - %1) %1: push 0 push %2 @@ -54,7 +54,7 @@ isr_handler_return: %endmacro %macro EMIT_EISR 2 - global %1:function (%1.end - %1) + global %1:function hidden (%1.end - %1) %1: push %2 jmp isr_handler_prelude.real @@ -62,7 +62,7 @@ isr_handler_return: %endmacro %macro EMIT_IRQ 2 - global %1:function (%1.end - %1) + global %1:function hidden (%1.end - %1) %1: push 0 push %2 diff --git a/src/kernel/kernel.ld b/src/kernel/kernel.ld index 3c4807d..34ef3fa 100755 --- a/src/kernel/kernel.ld +++ b/src/kernel/kernel.ld @@ -1,53 +1,59 @@ +PHDRS +{ + rodata PT_LOAD PHDRS FILEHDR FLAGS (4) /* read-only */; + text PT_LOAD ; + rwdata PT_LOAD ; + bss PT_LOAD ; +} + +MEMORY +{ + kernel (rwxa) : ORIGIN = 0xFFFF800000000000, LENGTH = 256M +} + ENTRY(_kernel_start.real) + SECTIONS { - . = 0xFFFF800000000000; - - .header : { - __header_start = .; + .header ORIGIN(kernel) + SIZEOF_HEADERS : { + HIDDEN(__header_start = .); KEEP(*(.header)) - __header_end = .; - } + HIDDEN(__header_end = .); + } :rodata - .text ALIGN(4096) : { - *(.text*) - KEEP(*(.isrs)) - } - - .data ALIGN(4096) : { - *(.data*) + .rodata : { *(.rodata*) - } + } :rodata - .ctors : ALIGN(8) { - __ctors = .; + .ap_startup : { + *(.ap_startup*) + } :rodata + + .ctors ALIGN(8) : { + HIDDEN(__ctors = .); KEEP(*(.ctors)) KEEP(*(.init_array)) - __ctors_end = .; - } + HIDDEN(__ctors_end = .); + } :rodata - .bss ALIGN(4096) : { - __bss_start = .; + .text ALIGN(4K) : { + *(.text*) + KEEP(*(.isrs)) + } :text + + .data ALIGN(4K) : { + *(.data*) + } :rwdata + + .syscall_registry : { + *(.syscall_registry*) + } :rwdata + + .bss ALIGN(4K) : { + HIDDEN(__bss_start = .); *(.bss*) - __bss_end = .; - } + HIDDEN(__bss_end = .); + } :bss - .note : { - *(.note.*) - } - - .eh_frame : { - __eh_frame_start = .; - KEEP(*(.eh_frame)) - __eh_frame_end = .; - } - - .eh_frame_hdr : { - KEEP(*(.eh_frame_hdr)) - } - - __eh_frame_hdr_start = SIZEOF(.eh_frame_hdr) > 0 ? ADDR(.eh_frame_hdr) : 0; - __eh_frame_hdr_end = SIZEOF(.eh_frame_hdr) > 0 ? . : 0; - - kernel_end = ALIGN(4096); + HIDDEN(__kernel_end = ALIGN(4096)); } diff --git a/src/kernel/smp.s b/src/kernel/smp.s index d0a4611..1ed33d3 100644 --- a/src/kernel/smp.s +++ b/src/kernel/smp.s @@ -26,7 +26,7 @@ bits 16 default rel align 8 -global ap_startup +global ap_startup: function hidden ap_startup: jmp .start_real @@ -104,13 +104,13 @@ align 8 jmp rax -global ap_startup_code_size +global ap_startup_code_size: function hidden ap_startup_code_size: dq ($ - ap_startup) section .text -global init_ap_trampoline +global init_ap_trampoline: function hidden init_ap_trampoline: push rbp mov rbp, rsp @@ -131,7 +131,7 @@ init_ap_trampoline: ret extern long_ap_startup -global ap_idle:function (ap_idle.end - ap_idle) +global ap_idle:function hidden (ap_idle.end - ap_idle) ap_idle: call long_ap_startup sti diff --git a/src/kernel/syscall.s b/src/kernel/syscall.s index 69a4253..d4eb245 100644 --- a/src/kernel/syscall.s +++ b/src/kernel/syscall.s @@ -22,7 +22,7 @@ extern syscall_registry extern syscall_invalid -global syscall_handler_prelude:function (syscall_handler_prelude.end - syscall_handler_prelude) +global syscall_handler_prelude: function hidden (syscall_handler_prelude.end - syscall_handler_prelude) syscall_handler_prelude: push rbp ; Never executed, fake function prelude mov rbp, rsp ; to calm down gdb @@ -77,7 +77,7 @@ syscall_handler_prelude: call syscall_invalid .end: -global kernel_to_user_trampoline:function (kernel_to_user_trampoline.end - kernel_to_user_trampoline) +global kernel_to_user_trampoline: function hidden (kernel_to_user_trampoline.end - kernel_to_user_trampoline) kernel_to_user_trampoline: pop r15 pop r14 @@ -98,7 +98,7 @@ kernel_to_user_trampoline: o64 sysret .end: -global syscall_enable:function (syscall_enable.end - syscall_enable) +global syscall_enable: function hidden (syscall_enable.end - syscall_enable) syscall_enable: push rbp mov rbp, rsp diff --git a/src/kernel/task.s b/src/kernel/task.s index 0796ceb..6095c36 100644 --- a/src/kernel/task.s +++ b/src/kernel/task.s @@ -1,6 +1,6 @@ %include "tasking.inc" -global task_switch +global task_switch: function hidden task_switch: push rbp mov rbp, rsp @@ -61,7 +61,7 @@ task_switch: pop rbp ret -global _current_gsbase +global _current_gsbase: function hidden _current_gsbase: mov rax, [gs:CPU_DATA.self] ret diff --git a/src/libraries/elf/elf/file.h b/src/libraries/elf/elf/file.h index 6ce72d1..7b9edda 100644 --- a/src/libraries/elf/elf/file.h +++ b/src/libraries/elf/elf/file.h @@ -22,7 +22,7 @@ public: inline size_t size() const { return m_size; } inline unsigned count() const { return m_count; } - inline const T & operator [] (int i) const { return *util::offset_pointer(m_start, m_size*i); } + inline const T & operator [] (int i) const { return *util::offset_pointer(m_start, m_size*i); } inline const iterator begin() const { return iterator(m_start, m_size); } inline const iterator end() const { return util::offset_pointer(m_start, m_size*m_count); }