From bdb1d06145d37293863e7cc4d95153fb8f3a5dac Mon Sep 17 00:00:00 2001 From: Ian Kronquist Date: Thu, 29 Jun 2017 18:48:29 -0400 Subject: [PATCH 01/51] Don't truncate module when signing --- tools/truesign.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/truesign.c b/tools/truesign.c index a2700d6..1b4bc27 100644 --- a/tools/truesign.c +++ b/tools/truesign.c @@ -231,7 +231,7 @@ int sign_file(char *secret_key_name, char *file_name, char *out_file_name) { goto out; } - written = fwrite(file_contents, read, 1, out_file); + written = fwrite(file_contents, file_size, 1, out_file); if (ferror(out_file) != 0) { perror("Writing out file"); error = -1; From ece4e822d360e471dea7ef5faa20f47ec99cc02b Mon Sep 17 00:00:00 2001 From: Ian Kronquist Date: Sat, 8 Jul 2017 15:17:45 -0400 Subject: [PATCH 02/51] First stab at the loader Bootstraps itself to 64 bit more where it can execute C code. --- Makefile | 29 ++++ loader/Makefile | 1 + loader/generate_kernel_header.py | 26 +++ loader/x64/Makefile | 2 + loader/x64/boot.S | 268 +++++++++++++++++++++++++++++++ loader/x64/boot.c | 99 ++++++++++++ loader/x64/link.ld | 23 +++ 7 files changed, 448 insertions(+) create mode 100644 loader/Makefile create mode 100644 loader/generate_kernel_header.py create mode 100644 loader/x64/Makefile create mode 100644 loader/x64/boot.S create mode 100644 loader/x64/boot.c create mode 100644 loader/x64/link.ld diff --git a/Makefile b/Makefile index 8298a98..7082985 100644 --- a/Makefile +++ b/Makefile @@ -18,9 +18,11 @@ BUILD_DIR := build KERNEL := $(BUILD_DIR)/truth.$(ARCH).elf OBJ := +LOADER_OBJS := MODULES := MODULE_CFLAGS := -std=c11 -MP -MMD -ffreestanding -O2 -Wall -Wextra \ -fpic -nostdlib -I ../../include -D __C__ -mno-sse +include loader/$(ARCH)/Makefile include kernel/arch/$(ARCH)/Makefile include kernel/core/Makefile include kernel/crypto/Makefile @@ -30,6 +32,14 @@ include modules/Makefile PYTHON := python +LOADER_FLAGS := -O2 -MP -MMD \ + -ffreestanding \ + -Wall -Wextra \ + -I ./include -mno-sse + +LOADER_CFLAGS := $(LOADER_FLAGS) -D __C__ -std=c11 +LOADER_ASFLAGS := $(LOADER_FLAGS) -D __ASM__ + CC := $(TRIPLE)-gcc @@ -68,6 +78,16 @@ MAKE := make all: $(KERNEL) tools +include/loader/kernel.h: $(KERNEL) + $(PYTHON) loader/generate_kernel_header.py $@ $< + +$(BUILD_DIR)/truth_loader.$(ARCH).elf64: loader/$(ARCH)/link.ld $(KERNEL)64 $(LOADER_OBJS) + $(CC) -T loader/$(ARCH)/link.ld $(LOADER_OBJS) $(LOADER_CFLAGS) -o $@ $< -nostdlib + +$(BUILD_DIR)/truth_loader.$(ARCH).elf: $(BUILD_DIR)/truth_loader.$(ARCH).elf64 + $(OBJCOPY) $< -O elf32-i386 $@ + + tools: $(BUILD_DIR)/tools/truesign $(BUILD_DIR)/tools/truesign: @@ -96,6 +116,15 @@ $(BUILD_DIR)/%.S.o: kernel/%.S mkdir -p $(shell dirname $@) $(AS) -c $< -o $@ $(ASFLAGS) +$(BUILD_DIR)/loader/%.S.o: loader/%.S + mkdir -p $(shell dirname $@) + $(AS) -c $< -o $@ $(LOADER_ASFLAGS) + +$(BUILD_DIR)/loader/%.c.o: loader/%.c + mkdir -p $(shell dirname $@) + $(CC) -c $< -o $@ $(LOADER_CFLAGS) + + $(BUILD_DIR)/key.pub: $(BUILD_DIR)/tools/truesign $(BUILD_DIR)/tools/truesign generate $(BUILD_DIR)/key.priv $@ diff --git a/loader/Makefile b/loader/Makefile new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/loader/Makefile @@ -0,0 +1 @@ + diff --git a/loader/generate_kernel_header.py b/loader/generate_kernel_header.py new file mode 100644 index 0000000..29ce51e --- /dev/null +++ b/loader/generate_kernel_header.py @@ -0,0 +1,26 @@ +import sys + +prefix = ''' +#pragma once + +#include + +uint8_t Kernel_ELF[] = { +''' + +suffix = ''' +}; + +''' + +if __name__ == '__main__': + if len(sys.argv) != 3: + sys.stderr.write('Usage: {} elf_file header_file\n'.format(sys.argv[0])) + exit(-1) + + with open(sys.argv[1], 'w') as header: + header.write(prefix) + with open(sys.argv[2], 'r') as elf: + for byte in elf.read(): + header.write('{}, '.format(hex(ord(byte)))) + header.write(suffix) diff --git a/loader/x64/Makefile b/loader/x64/Makefile new file mode 100644 index 0000000..53d435d --- /dev/null +++ b/loader/x64/Makefile @@ -0,0 +1,2 @@ +LOADER_OBJS += $(BUILD_DIR)/loader/$(ARCH)/boot.S.o +LOADER_OBJS += $(BUILD_DIR)/loader/$(ARCH)/boot.c.o diff --git a/loader/x64/boot.S b/loader/x64/boot.S new file mode 100644 index 0000000..73b250c --- /dev/null +++ b/loader/x64/boot.S @@ -0,0 +1,268 @@ +#include +#include + +#define Boot_VGA_Window_Start 0xb8000 +#define CPU_Flags_ID 0x00200000 +#define CPUId_Leaf_Manufacturer 0x0 +#define CPUId_Leaf_Processor_Info 0x80000001 +#define CPUId_EDX_Long_Mode (1 << 29) +#define CPUId_EDX_Time_Step_Counter (1 << 4) +#define CPUId_EDX_Not_Executable_Pages (1 << 20) +#define CPUId_EDX_Syscall (1 << 11) +#define MSR_IA32_EFER_Long_Mode 0x100 +#define MSR_IA32_EFER_Execute_Disable 0x800 +.section .text + +# MB header. +.align MB_Alignment +.long MB_Magic +.long MB_Flags +.long MB_Checksum + +.section .bss, "aw", @nobits +.align Page_Small + +.global init_pl4 +init_pl4: + .skip Page_Small + +.global init_pl3 +init_pl3: + .skip Page_Small + +.global init_pl2 +init_pl2: + .skip Page_Small + +.global init_pl1 +init_pl1: + .skip Page_Small + +.global _init_stack_top +init_stack: + .skip (16 * KB) +_init_stack_top: + +.section .text + +.code32 + +Function(_start) + # Initialize stack pointer. + movl $_init_stack_top, %esp + + # Save Multiboot info table physical address. + pushl %ebx + + # Is this a multiboot compatible bootloader? + cmpl $Multiboot_Register_Magic, %eax + je .compat_multiboot_magic_ok + # If not, clear the screen, print an error message, and hang. + call boot_vga_clear + movl $Boot_Bad_Multiboot_Magic_String, %edi + jmp .bad_boot + + +.compat_multiboot_magic_ok: + + call boot_vga_clear + + # Is cpuid supported? It is if the eax register is not 0. + call boot_cpuid_available + testl %eax, %eax + jnz .compat_cpuid_available + movl $Boot_No_CPUId, %edi + jmp .bad_boot + +.compat_cpuid_available: + movl $CPUId_Leaf_Processor_Info, %eax + cpuid + + movl %edx, %edi + andl $CPUId_EDX_Long_Mode, %edi + jnz .compat_long_mode_supported + movl $Boot_No_Long_Mode_String, %edi + jmp .bad_boot + +.compat_long_mode_supported: + movl %edx, %edi + andl $CPUId_EDX_Time_Step_Counter, %edi + jnz .compat_time_step_counter_available + movl $Boot_No_RDTSC_String, %edi + jmp .bad_boot + +.compat_time_step_counter_available: + movl %edx, %edi + andl $CPUId_EDX_Not_Executable_Pages, %edi + jnz .compat_nx_bit_available + movl $Boot_No_NX_Bit_String, %edi + jmp .bad_boot + +.compat_nx_bit_available: + movl %edx, %edi + andl $CPUId_EDX_Syscall, %edi + jnz .compat_syscall_available + movl $Boot_No_Syscall_String, %edi + jmp .bad_boot + +.compat_syscall_available: + call boot_map_page_table + + # Enable PAE. + movl %cr4, %eax + orl $CR4_PAE, %eax + movl %eax, %cr4 + + + # Enable long mode and the No-Execute bit. + movl $IA32_EFER_MSR, %ecx + rdmsr + orl $(MSR_IA32_EFER_Long_Mode | MSR_IA32_EFER_Execute_Disable), %eax + wrmsr + + # Enable paging (with write protection) and enter long mode. + # Note that we are still in a 32 bit code segment. + movl %cr0, %eax + orl $(CR0_Paging | CR0_Write_Protect), %eax + movl %eax, %cr0 + + + lgdt Boot_GDT_Register + ljmp $Segment_Kernel_Code, $long_mode + +.code64 +long_mode: + # Clear upper 32 bits of stack pointer. + movl %esp, %esp + + # Load kernel data segment. + movw $Segment_Kernel_Data, %cx + movw %cx, %ds + movw %cx, %es + movw %cx, %ss + + movl $Boot_Loader_String, %edi + call boot_vga_log64 + jmp boot_halt +.bad_boot: + call boot_vga_log + jmp boot_halt + +# void boot_vga_log64(char *edi); +Function(boot_vga_log64) + movl (Boot_VGA_Pointer), %ebx +.write_char64: + movl (%edi), %eax + testb %al, %al + jz .out64 + movb $0x0f, %ah + movw %ax, (%ebx) + addl $2, %ebx + inc %edi + jmp .write_char64 +.out64: + movl %ebx, (Boot_VGA_Pointer) + ret + + +.code32 + +Function(boot_map_page_table) + movl $init_pl4, %edi + movl %edi, %cr3 + + movl $(init_pl3 + (Page_User | Page_Write | Page_Present)), init_pl4 + + movl $(init_pl2 + (Page_User | Page_Write | Page_Present)), init_pl3 + + movl $(init_pl1 + (Page_Write | Page_Present)), init_pl2 + + # Fractal mapping. + movl $(init_pl4 + (Page_Write | Page_Present)), init_pl4 + Kernel_Fractal_Page_Table_Index * 8 + # Map first 4 MB except for the NULL page. + movl $(init_pl1 + 8), %edi + movl $(0x1000 | Page_Present | Page_Write), %esi + movl $0x1ff, %ecx +1: + movl %esi, (%edi) + addl $8, %edi + addl $Page_Small, %esi + loop 1b + ret + + +Function(boot_vga_clear) + movl $(80*24), %ecx + movl $Boot_VGA_Window_Start, %eax +1: + movl $0, (%eax) + addl $4, %eax + loop 1b + ret + +# void boot_vga_log(char *edi); +Function(boot_vga_log) + movl (Boot_VGA_Pointer), %ebx +.write_char: + movl (%edi), %eax + testb %al, %al + jz .out + movb $0x0f, %ah + movw %ax, (%ebx) + addl $2, %ebx + inc %edi + jmp .write_char +.out: + movl %ebx, (Boot_VGA_Pointer) + ret + +Function(boot_halt) + cli + hlt + pause + jmp boot_halt + + +Function(boot_cpuid_available) + # Save original flags. + pushf + # Save them again. We'll manipulate these ones. + pushf + # Flip the ID bit. + xorl $CPU_Flags_ID, (%esp) + # Restore the manipulated flags. If cpuid is supported the bit will be set. + popf + # Move flags to eax. + pushf + pop %eax + # Mask everything but the id bit. + andl $CPU_Flags_ID, %eax + # Restore original flags. + popf + ret + +.section .data +Boot_VGA_Pointer: +.long Boot_VGA_Window_Start + + +Boot_Loader_String: +.asciz "Kernel of Truth Loader" + +Boot_Bad_Multiboot_Magic_String: +.asciz "Bad multiboot magic. Incompatible bootloader." + +Boot_No_CPUId: +.asciz "cpuid instruction not supported. Incompatible hardware." + +Boot_No_Long_Mode_String: +.asciz "64 bit not supported. Incompatible hardware." + +Boot_No_RDTSC_String: +.asciz "Time Step Counter not supported. Incompatible hardware." + +Boot_No_NX_Bit_String: +.asciz "Non-executable pages not supported. Incompatible hardware." + +Boot_No_Syscall_String: +.asciz "Syscall instruction not supported. Incompatible hardware." diff --git a/loader/x64/boot.c b/loader/x64/boot.c new file mode 100644 index 0000000..e08d7cf --- /dev/null +++ b/loader/x64/boot.c @@ -0,0 +1,99 @@ +#include + +struct tss_entry { + uint32_t reserved0; + uint64_t stack0; + uint64_t stack1; + uint64_t stack2; + uint64_t reserved1; + uint64_t ist[7]; + uint64_t reserved2; + uint16_t reserved3; + uint16_t iomap_base; +} pack; + +struct tss_entry Boot_TSS = { + .reserved0 = 0, + .stack0 = 0, + .stack1 = 0, + .stack2 = 0, + .reserved1 = 0, + .ist = { 0, 0, 0, 0, 0, 0, 0}, + .reserved2 = 0, + .reserved3 = 0, + .iomap_base = 0, +}; + +struct gdt_entry { + uint16_t limit_low; + uint16_t base_low; + uint8_t base_middle; + uint8_t access; + uint8_t granularity; + uint8_t base_high; +}; + +#define Gran_64_Bit_Mode (1 << 5) +#define Gran_32_Bit_Mode (1 << 6) +#define Gran_4_KB_BLocks (1 << 7) + +#define gdt_entry(base, limit, access, granularity) \ + { (limit) & 0xffff, \ + (uint16_t) ((base) >> 0 & 0xffff), \ + (uint8_t) ((base) >> 16 & 0xff), \ + (access) & 0xff, \ + ((limit) >> 16 & 0x0f) | ((granularity) & 0xf0), \ + (uint8_t) ((base) >> 24 & 0xff), \ + } + +#define gdt_entry64(base, limit, access, granularity) \ + { (limit) & 0xffff, \ + (uint16_t) ((base) >> 0 & 0xffff), \ + (uint8_t) ((base) >> 16 & 0xff), \ + (access) & 0xff, \ + ((limit) >> 16 & 0x0f) | ((granularity) & 0xf0), \ + (uint8_t) ((base) >> 24 & 0xff), \ + }, \ + { (uint16_t) ((base) >> 32 & 0xffff), \ + (uint16_t) ((base) >> 48 & 0xffff), \ + 0, \ + 0, \ + 0, \ + 0, \ + } \ + +struct gdt_entry Boot_GDT[] = { + // NULL segment + gdt_entry(0, 0, 0, 0), + + // Kernel Code Segment. + gdt_entry(0, 0xffffffff, 0x9a, Gran_64_Bit_Mode | Gran_4_KB_BLocks), + + // Kernel Data Segment. + gdt_entry(0, 0xffffffff, 0x92, Gran_64_Bit_Mode | Gran_4_KB_BLocks), + + // User code and data segments would go here, but we don't need them in + // early boot. + // Still put dummy values here so we can reuse the same TSS segment + // number as the kernel proper. + {0}, + + {0}, + + // Task Switch Segment. + gdt_entry64(0ull, sizeof(Boot_TSS) - 1, 0xe9, 0x00), +}; + +struct gdt_register { + uint16_t limit; + uint64_t base; +} pack; + +struct gdt_register Boot_GDT_Register = { + .limit = sizeof(Boot_GDT) - 1, + .base = (uint64_t)&Boot_GDT, +}; + + +void loader_main(uint64_t multiboot_magic, uint64_t multiboot_info_physical) { +} diff --git a/loader/x64/link.ld b/loader/x64/link.ld new file mode 100644 index 0000000..a684cc6 --- /dev/null +++ b/loader/x64/link.ld @@ -0,0 +1,23 @@ +ENTRY(_start) + +SECTIONS { + + . = 1M; + .text : AT(1M) { + *(.text) + } + + .data BLOCK(4K) : ALIGN(4K) { + *(.data) + } + + .rodata BLOCK(4K) : ALIGN(4K) { + *(.rodata) + } + + .bss BLOCK(4K) : ALIGN(4K) { + *(.bss) + } + + . = ALIGN(4K); +} From f0cca1e84dbecf83ec2958bebac94af8bff82cc8 Mon Sep 17 00:00:00 2001 From: Ian Kronquist Date: Sun, 9 Jul 2017 01:45:44 -0400 Subject: [PATCH 03/51] Relocation successful --- Makefile | 48 ++--- build_symbol_table.py | 2 + include/arch/x64/boot.h | 1 + kernel/arch/x64/boot.S | 329 +++++++++++++++--------------- kernel/arch/x64/isr.S | 4 +- kernel/arch/x64/link.ld | 4 +- kernel/core/main.c | 2 +- kernel/core/physical_allocator.c | 2 +- loader/x64/boot.S | 76 ++++--- loader/x64/boot.c | 332 ++++++++++++++++++++++++++++++- 10 files changed, 576 insertions(+), 224 deletions(-) diff --git a/Makefile b/Makefile index 7082985..43e9bf2 100644 --- a/Makefile +++ b/Makefile @@ -16,6 +16,9 @@ MACROS := -dD \ BUILD_DIR := build KERNEL := $(BUILD_DIR)/truth.$(ARCH).elf +KERNEL64 := $(BUILD_DIR)/truth.$(ARCH).elf64 +LOADER := $(BUILD_DIR)/truth_loader.$(ARCH).elf +LOADER64 := $(BUILD_DIR)/truth_loader.$(ARCH).elf64 OBJ := LOADER_OBJS := @@ -31,31 +34,27 @@ include modules/Makefile PYTHON := python +OD := od LOADER_FLAGS := -O2 -MP -MMD \ -ffreestanding \ -Wall -Wextra \ -I ./include -mno-sse -LOADER_CFLAGS := $(LOADER_FLAGS) -D __C__ -std=c11 +RANOM_NUMBER := $(strip $(shell $(OD) -vAn -N8 -tu8 < /dev/urandom)) +LOADER_CFLAGS := $(LOADER_FLAGS) -D __C__ -std=c11 -D Boot_Compile_Random_Number=$(RANOM_NUMBER)ul LOADER_ASFLAGS := $(LOADER_FLAGS) -D __ASM__ - +KERNEL_FLAGS := -O2 -MP -MMD -mno-sse -Wall -Wextra -ffreestanding -I ./include -fPIC CC := $(TRIPLE)-gcc -CFLAGS := -std=c11 -O2 -MP -MMD -mcmodel=kernel \ - -ffreestanding -fstack-protector-all \ - -Wall -Wextra \ - -I ./include $(MACROS) -D __C__ -mno-sse +CFLAGS := -std=c11 $(KERNEL_FLAGS) $(MACROS) -D __C__ AS := $(TRIPLE)-gcc -ASFLAGS := -O2 -MP -MMD -mcmodel=kernel \ - -ffreestanding \ - -Wall -Wextra \ - -I ./include $(MACROS) -D __ASM__ +ASFLAGS := $(KERNEL_FLAGS) $(MACROS) -D __ASM__ -LD := $(TRIPLE)-gcc -LDFLAGS := -nostdlib -ffreestanding -O2 -mcmodel=kernel +LD := $(TRIPLE)-ld +LDFLAGS := -nostdlib -O2 -soname="Kernel of Truth" -m elf_x86_64 -z max-page-size=0x1000 -fPIE -fPIC MODULE_CC := $(CC) MODULE_LD := $(TRIPLE)-ld @@ -76,15 +75,15 @@ MAKE := make .PHONY: all clean debug iso release start start-log tools -all: $(KERNEL) tools +all: $(LOADER) $(MODULES) -include/loader/kernel.h: $(KERNEL) +include/loader/kernel.h: $(KERNEL64) $(PYTHON) loader/generate_kernel_header.py $@ $< -$(BUILD_DIR)/truth_loader.$(ARCH).elf64: loader/$(ARCH)/link.ld $(KERNEL)64 $(LOADER_OBJS) +$(LOADER64): loader/$(ARCH)/link.ld $(LOADER_OBJS) $(CC) -T loader/$(ARCH)/link.ld $(LOADER_OBJS) $(LOADER_CFLAGS) -o $@ $< -nostdlib -$(BUILD_DIR)/truth_loader.$(ARCH).elf: $(BUILD_DIR)/truth_loader.$(ARCH).elf64 +$(LOADER): $(BUILD_DIR)/truth_loader.$(ARCH).elf64 $(OBJCOPY) $< -O elf32-i386 $@ @@ -97,6 +96,8 @@ debug: CFLAGS += -g -fsanitize=undefined debug: ASFLAGS += -g debug: all +release: LOADER_CFLAGS += -Werror +release: LOADER_ASFLAGS += -Werror release: CFLAGS += -Werror release: AFLAGS += -Werror release: all @@ -105,8 +106,9 @@ release: all $(KERNEL): $(KERNEL)64 $(MODULES) $(OBJCOPY) $< -O elf32-i386 $@ -$(KERNEL)64: kernel/arch/$(ARCH)/link.ld $(BUILD_DIR)/symbols.o - $(LD) -T kernel/arch/$(ARCH)/link.ld $(OBJ) $(BUILD_DIR)/symbols.o -o $@ $(LDFLAGS) +$(KERNEL64): kernel/arch/$(ARCH)/link.ld $(OBJ) + #$(LD) -T kernel/arch/$(ARCH)/link.ld $(BUILD_DIR)/symbols.o -o $@ $(OBJ) + $(LD) -T kernel/arch/$(ARCH)/link.ld -o $@ $(OBJ) -shared -soname="truth" -ffreestanding -nostdlib $(BUILD_DIR)/%.c.o: kernel/%.c include/truth/key.h mkdir -p $(shell dirname $@) @@ -120,7 +122,7 @@ $(BUILD_DIR)/loader/%.S.o: loader/%.S mkdir -p $(shell dirname $@) $(AS) -c $< -o $@ $(LOADER_ASFLAGS) -$(BUILD_DIR)/loader/%.c.o: loader/%.c +$(BUILD_DIR)/loader/%.c.o: loader/%.c include/loader/kernel.h mkdir -p $(shell dirname $@) $(CC) -c $< -o $@ $(LOADER_CFLAGS) @@ -131,10 +133,10 @@ $(BUILD_DIR)/key.pub: $(BUILD_DIR)/tools/truesign include/truth/key.h: $(BUILD_DIR)/key.pub $(BUILD_DIR)/tools/truesign header $(BUILD_DIR)/key.pub $@ -$(BUILD_DIR)/symbols.o: $(OBJ) kernel/arch/$(ARCH)/link.ld - $(LD) -T kernel/arch/$(ARCH)/link.ld $(OBJ) -o $(KERNEL)64 $(LDFLAGS) - nm $(KERNEL)64 | $(PYTHON) build_symbol_table.py $(BUILD_DIR)/symbols.S - $(AS) -c $(BUILD_DIR)/symbols.S -o $@ $(ASFLAGS) +#$(BUILD_DIR)/symbols.o: $(OBJ) kernel/arch/$(ARCH)/link.ld +# $(LD) -T kernel/arch/$(ARCH)/link.ld $(OBJ) -o $(KERNEL)64 $(LDFLAGS) +# nm $(KERNEL)64 | $(PYTHON) build_symbol_table.py $(BUILD_DIR)/symbols.S +# $(AS) -c $(BUILD_DIR)/symbols.S -o $@ $(ASFLAGS) $(BUILD_DIR)/modules/%.ko: modules/% modules/link.ld $(BUILD_DIR)/key.pub mkdir -p $(shell dirname $@) diff --git a/build_symbol_table.py b/build_symbol_table.py index 66d34ac..08ff6fa 100644 --- a/build_symbol_table.py +++ b/build_symbol_table.py @@ -36,4 +36,6 @@ def write_assembly(symbols, file_name): _, symbol_type, name = line.split() if is_global_function(symbol_type): symbols.append(name) + + symbols = [] write_assembly(symbols, sys.argv[1]) diff --git a/include/arch/x64/boot.h b/include/arch/x64/boot.h index 0b7ce07..0474488 100644 --- a/include/arch/x64/boot.h +++ b/include/arch/x64/boot.h @@ -3,6 +3,7 @@ #include #include +#define Multiboot_Register_Magic 0x2badb002 #define MB_Magic 0x1badb002 #define MB_Alignment (1 << 1) #define MB_Info (1 << 1) diff --git a/kernel/arch/x64/boot.S b/kernel/arch/x64/boot.S index c21e481..e377cfa 100644 --- a/kernel/arch/x64/boot.S +++ b/kernel/arch/x64/boot.S @@ -44,172 +44,179 @@ _init_stack_top: .global _start .type _start, @function -.code32 +.code64 _start: # Initialize stack pointer. - movl $virt_to_phys(_init_stack_top), %esp - - - # We got our multiboot information in various registers. - pushl $0 - pushl %ebx - - movl $virt_to_phys(init_pl4), %edi - movl %edi, %cr3 - - movl $(virt_to_phys(init_pl3) + (Page_User | Page_Write | Page_Present)), virt_to_phys(init_pl4) - movl $(virt_to_phys(init_pl3) + (Page_User | Page_Write | Page_Present)), virt_to_phys(init_pl4) + 511 * 8 - - movl $(virt_to_phys(init_pl2) + (Page_User | Page_Write | Page_Present)), virt_to_phys(init_pl3) - movl $(virt_to_phys(init_pl2) + (Page_User | Page_Write | Page_Present)), virt_to_phys(init_pl3) + 510 * 8 - - movl $(virt_to_phys(init_pl1) + (Page_Write | Page_Present)), virt_to_phys(init_pl2) - - # Fractal mapping. - movl $(virt_to_phys(init_pl4) + (Page_Write | Page_Present)), virt_to_phys(init_pl4) + Kernel_Fractal_Page_Table_Index * 8 - movl $Page_Execute_Disable_High, virt_to_phys(init_pl4) + (Kernel_Fractal_Page_Table_Index * 8) + 4 - - - # Page Table (identity map the first 1 MiB, except NULL). - movl $(virt_to_phys(init_pl1) + 8), %edi - movl $(0x1000 | Page_Present | Page_Write), %esi - movl $Page_Execute_Disable_High, %edx - movl $0xff, %ecx -1: - movl %esi, (%edi) - addl $4, %edi - movl %edx, (%edi) - addl $Page_Small, %esi - addl $4, %edi - loop 1b - - - # Map kernel text section - andl $(Memory_Writable_Mask), %esi - movl $0, %edx - movl $virt_to_phys(__text_end), %ecx - subl $virt_to_phys(__text_start), %ecx - shrl $12, %ecx -1: - movl %esi, (%edi) - addl $4, %edi - movl %edx, (%edi) - addl $Page_Small, %esi - addl $4, %edi - loop 1b - - # Map kernel data section - orl $(Memory_Writable), %esi - movl $Page_Execute_Disable_High, %edx - movl $virt_to_phys(__data_end), %ecx - subl $virt_to_phys(__data_start), %ecx - shrl $12, %ecx -1: - movl %esi, (%edi) - addl $4, %edi - movl %edx, (%edi) - addl $Page_Small, %esi - addl $4, %edi - loop 1b - - # Map kernel rodata section - andl $(Memory_Writable_Mask), %esi - movl $Page_Execute_Disable_High, %edx - movl $virt_to_phys(__rodata_end), %ecx - subl $virt_to_phys(__rodata_start), %ecx - shrl $12, %ecx -1: - movl %esi, (%edi) - addl $4, %edi - movl %edx, (%edi) - addl $Page_Small, %esi - addl $4, %edi - loop 1b - - # Map kernel bss section - orl $(Memory_Writable), %esi - movl $Page_Execute_Disable_High, %edx - movl $virt_to_phys(__bss_end), %ecx - subl $virt_to_phys(__bss_start), %ecx - shrl $12, %ecx -1: - movl %esi, (%edi) - addl $4, %edi - movl %edx, (%edi) - addl $Page_Small, %esi - addl $4, %edi - loop 1b - - # Enable PAE. - movl %cr4, %eax - orl $CR4_PAE, %eax - movl %eax, %cr4 - - # Enable long mode and the No-Execute bit. - movl $IA32_EFER_MSR, %ecx - rdmsr - orl $0x900, %eax - wrmsr - - # Enable paging (with write protection) and enter long mode (still 32-bit) - movl %cr0, %eax - orl $(CR0_Paging | CR0_Write_Protect), %eax - movl %eax, %cr0 - - -paging: - - # Load the Global Descriptor Table pointer register. - lgdt virt_to_phys(Physical_GDT_Register) - - # Now use the 64-bit code segment, and we are in full 64-bit mode. - ljmp $Segment_Kernel_Code, $virt_to_phys(long_mode) - -.code64 -long_mode: - # Clear upper 32 bits of stack pointer. - mov %esp, %esp - - # Load kernel data segment. - movw $Segment_Kernel_Data, %cx - movw %cx, %ds - movw %cx, %es - movw %cx, %ss - - # Install the kernel stack into the Task Switch Segment. - mov $_init_stack_top, %rcx - mov %rcx, Tss + 4 - - # Finish installing the TSS into the GDT - mov $Tss, %rcx - movw %cx, GDT + Segment_TSS + 2 - shr $16, %rcx - movb %cl, GDT + Segment_TSS + 4 - shr $8, %rcx - movb %cl, GDT + Segment_TSS + 7 - shr $8, %rcx - movl %ecx, GDT + Segment_TSS + 8 - - # Switch the task switch segment register to the task switch segment. - movw $(Segment_TSS | Segment_RPL), %cx - ltr %cx - - add $Kernel_Space_Start, %rsp - mov $higher_half, %rcx - jmp *%rcx - -higher_half: - # Load the Global Descriptor Table pointer register again. - lgdt GDT_Register - + # lea _init_stack_top(%rip), %rsi + movq %rsi, %rsp call set_stack_guard - - # Multiboot information structure pointer. - pop %rdi - call kernel_main + call *kernel_main@GOTPCREL(%rip) jmp halt + +# +# +# # We got our multiboot information in various registers. +# pushl $0 +# pushl %ebx +# +# movl $virt_to_phys(init_pl4), %edi +# movl %edi, %cr3 +# +# movl $(virt_to_phys(init_pl3) + (Page_User | Page_Write | Page_Present)), virt_to_phys(init_pl4) +# movl $(virt_to_phys(init_pl3) + (Page_User | Page_Write | Page_Present)), virt_to_phys(init_pl4) + 511 * 8 +# +# movl $(virt_to_phys(init_pl2) + (Page_User | Page_Write | Page_Present)), virt_to_phys(init_pl3) +# movl $(virt_to_phys(init_pl2) + (Page_User | Page_Write | Page_Present)), virt_to_phys(init_pl3) + 510 * 8 +# +# movl $(virt_to_phys(init_pl1) + (Page_Write | Page_Present)), virt_to_phys(init_pl2) +# +# # Fractal mapping. +# movl $(virt_to_phys(init_pl4) + (Page_Write | Page_Present)), virt_to_phys(init_pl4) + Kernel_Fractal_Page_Table_Index * 8 +# movl $Page_Execute_Disable_High, virt_to_phys(init_pl4) + (Kernel_Fractal_Page_Table_Index * 8) + 4 +# +# +# # Page Table (identity map the first 1 MiB, except NULL). +# movl $(virt_to_phys(init_pl1) + 8), %edi +# movl $(0x1000 | Page_Present | Page_Write), %esi +# movl $Page_Execute_Disable_High, %edx +# movl $0xff, %ecx +#1: +# movl %esi, (%edi) +# addl $4, %edi +# movl %edx, (%edi) +# addl $Page_Small, %esi +# addl $4, %edi +# loop 1b +# +# +# # Map kernel text section +# andl $(Memory_Writable_Mask), %esi +# movl $0, %edx +# movl $virt_to_phys(__text_end), %ecx +# subl $virt_to_phys(__text_start), %ecx +# shrl $12, %ecx +#1: +# movl %esi, (%edi) +# addl $4, %edi +# movl %edx, (%edi) +# addl $Page_Small, %esi +# addl $4, %edi +# loop 1b +# +# # Map kernel data section +# orl $(Memory_Writable), %esi +# movl $Page_Execute_Disable_High, %edx +# movl $virt_to_phys(__data_end), %ecx +# subl $virt_to_phys(__data_start), %ecx +# shrl $12, %ecx +#1: +# movl %esi, (%edi) +# addl $4, %edi +# movl %edx, (%edi) +# addl $Page_Small, %esi +# addl $4, %edi +# loop 1b +# +# # Map kernel rodata section +# andl $(Memory_Writable_Mask), %esi +# movl $Page_Execute_Disable_High, %edx +# movl $virt_to_phys(__rodata_end), %ecx +# subl $virt_to_phys(__rodata_start), %ecx +# shrl $12, %ecx +#1: +# movl %esi, (%edi) +# addl $4, %edi +# movl %edx, (%edi) +# addl $Page_Small, %esi +# addl $4, %edi +# loop 1b +# +# # Map kernel bss section +# orl $(Memory_Writable), %esi +# movl $Page_Execute_Disable_High, %edx +# movl $virt_to_phys(__bss_end), %ecx +# subl $virt_to_phys(__bss_start), %ecx +# shrl $12, %ecx +#1: +# movl %esi, (%edi) +# addl $4, %edi +# movl %edx, (%edi) +# addl $Page_Small, %esi +# addl $4, %edi +# loop 1b +# +# # Enable PAE. +# movl %cr4, %eax +# orl $CR4_PAE, %eax +# movl %eax, %cr4 +# +# # Enable long mode and the No-Execute bit. +# movl $IA32_EFER_MSR, %ecx +# rdmsr +# orl $0x900, %eax +# wrmsr +# +# # Enable paging (with write protection) and enter long mode (still 32-bit) +# movl %cr0, %eax +# orl $(CR0_Paging | CR0_Write_Protect), %eax +# movl %eax, %cr0 +# +# +#paging: +# +# # Load the Global Descriptor Table pointer register. +# lgdt virt_to_phys(Physical_GDT_Register) +# +# # Now use the 64-bit code segment, and we are in full 64-bit mode. +# ljmp $Segment_Kernel_Code, $virt_to_phys(long_mode) +# +#.code64 +#long_mode: +# # Clear upper 32 bits of stack pointer. +# mov %esp, %esp +# +# # Load kernel data segment. +# movw $Segment_Kernel_Data, %cx +# movw %cx, %ds +# movw %cx, %es +# movw %cx, %ss +# +# # Install the kernel stack into the Task Switch Segment. +# mov $_init_stack_top, %rcx +# mov %rcx, Tss + 4 +# +# # Finish installing the TSS into the GDT +# mov $Tss, %rcx +# movw %cx, GDT + Segment_TSS + 2 +# shr $16, %rcx +# movb %cl, GDT + Segment_TSS + 4 +# shr $8, %rcx +# movb %cl, GDT + Segment_TSS + 7 +# shr $8, %rcx +# movl %ecx, GDT + Segment_TSS + 8 +# +# # Switch the task switch segment register to the task switch segment. +# movw $(Segment_TSS | Segment_RPL), %cx +# ltr %cx +# +# add $Kernel_Space_Start, %rsp +# mov $higher_half, %rcx +# jmp *%rcx +# +#higher_half: +# # Load the Global Descriptor Table pointer register again. +# lgdt GDT_Register +# +# call set_stack_guard +# +# # Multiboot information structure pointer. +# pop %rdi +# call kernel_main +# +# jmp halt + .global halt .type halt, @function halt: @@ -269,6 +276,6 @@ set_stack_guard: loop 0b .load_guard: - mov %rbx, __stack_chk_guard + movl %ebx, __stack_chk_guard@GOTPCREL(%rip) pop %rbx ret diff --git a/kernel/arch/x64/isr.S b/kernel/arch/x64/isr.S index 033bbda..6e169de 100644 --- a/kernel/arch/x64/isr.S +++ b/kernel/arch/x64/isr.S @@ -43,12 +43,12 @@ _service_interrupt: rdtsc mov %di, %ax .extern entropy_pool_seed - call entropy_pool_seed + call *entropy_pool_seed@GOTPCREL(%rip) # Call interrupt dispatcher. .dispatch: .extern interrupts_dispatcher - call interrupts_dispatcher + call *interrupts_dispatcher@GOTPCREL(%rip) # Restore data segment. pop %rax diff --git a/kernel/arch/x64/link.ld b/kernel/arch/x64/link.ld index 90f1cea..2003093 100644 --- a/kernel/arch/x64/link.ld +++ b/kernel/arch/x64/link.ld @@ -2,9 +2,9 @@ ENTRY(_start) SECTIONS { - . = 0xffffffff80000000 + 1M; + /*. = 0xffffffff80000000 + 1M;*/ - .text : AT(1M) { + .text BLOCK(4K) : ALIGN(4K) { __kernel_start = .; __text_start = .; *(.text) diff --git a/kernel/core/main.c b/kernel/core/main.c index 694dbea..d6ebcf9 100644 --- a/kernel/core/main.c +++ b/kernel/core/main.c @@ -16,7 +16,7 @@ #include -void kernel_main(uint32_t multiboot_tables) { +constructor void kernel_main(uint32_t multiboot_tables) { assert_ok(log_init(Log_Debug, "log")); log(Log_None, Logo); logf(Log_None, "\tCPU Time %ld\n", cpu_time()); diff --git a/kernel/core/physical_allocator.c b/kernel/core/physical_allocator.c index add098f..c938e28 100644 --- a/kernel/core/physical_allocator.c +++ b/kernel/core/physical_allocator.c @@ -28,7 +28,7 @@ static bool physical_region_contains(uintptr_t start_a, uintptr_t end_a, // When populating the physical allocator, certain addresses are unavailable or // reserved. The multiboot tables give a sorted list of regions which are -// useable memory, but some of these contain the kernel, modules, or the +// usable memory, but some of these contain the kernel, modules, or the // multiboot tables themselves. static void insert_regions(struct multiboot_info *multiboot_tables) { struct reserved_region { diff --git a/loader/x64/boot.S b/loader/x64/boot.S index 73b250c..8e21f83 100644 --- a/loader/x64/boot.S +++ b/loader/x64/boot.S @@ -34,10 +34,19 @@ init_pl3: init_pl2: .skip Page_Small -.global init_pl1 -init_pl1: +.global init_pl1_a +init_pl1_a: .skip Page_Small +.global init_pl1_b +init_pl1_b: + .skip Page_Small + +.global init_pl1_c +init_pl1_c: + .skip Page_Small + + .global _init_stack_top init_stack: .skip (16 * KB) @@ -52,7 +61,11 @@ Function(_start) movl $_init_stack_top, %esp # Save Multiboot info table physical address. + # Push a 0 in front of it so when we do a 64 bit pop later we don't + # underflow the stack. + pushl $0 pushl %ebx + movl %esp, %ebp # Is this a multiboot compatible bootloader? cmpl $Multiboot_Register_Magic, %eax @@ -141,30 +154,13 @@ long_mode: movw %cx, %es movw %cx, %ss - movl $Boot_Loader_String, %edi - call boot_vga_log64 + pop %rdi + call boot_loader_main jmp boot_halt .bad_boot: call boot_vga_log jmp boot_halt -# void boot_vga_log64(char *edi); -Function(boot_vga_log64) - movl (Boot_VGA_Pointer), %ebx -.write_char64: - movl (%edi), %eax - testb %al, %al - jz .out64 - movb $0x0f, %ah - movw %ax, (%ebx) - addl $2, %ebx - inc %edi - jmp .write_char64 -.out64: - movl %ebx, (Boot_VGA_Pointer) - ret - - .code32 Function(boot_map_page_table) @@ -175,12 +171,14 @@ Function(boot_map_page_table) movl $(init_pl2 + (Page_User | Page_Write | Page_Present)), init_pl3 - movl $(init_pl1 + (Page_Write | Page_Present)), init_pl2 + movl $(init_pl1_a + (Page_Write | Page_Present)), init_pl2 + movl $(init_pl1_b + (Page_Write | Page_Present)), init_pl2 + 8 + movl $(init_pl1_c + (Page_Write | Page_Present)), init_pl2 + 16 # Fractal mapping. movl $(init_pl4 + (Page_Write | Page_Present)), init_pl4 + Kernel_Fractal_Page_Table_Index * 8 # Map first 4 MB except for the NULL page. - movl $(init_pl1 + 8), %edi + movl $(init_pl1_a + 8), %edi movl $(0x1000 | Page_Present | Page_Write), %esi movl $0x1ff, %ecx 1: @@ -188,6 +186,27 @@ Function(boot_map_page_table) addl $8, %edi addl $Page_Small, %esi loop 1b + + addl $Page_Small, %esi + # Map next pl1 + movl $(init_pl1_b + 8), %edi + movl $0x200, %ecx +1: + movl %esi, (%edi) + addl $8, %edi + addl $Page_Small, %esi + loop 1b + + # Map next pl1 + movl $(init_pl1_c + 8), %edi + movl $0x200, %ecx +1: + movl %esi, (%edi) + addl $8, %edi + addl $Page_Small, %esi + loop 1b + + ret @@ -202,8 +221,6 @@ Function(boot_vga_clear) # void boot_vga_log(char *edi); Function(boot_vga_log) - movl (Boot_VGA_Pointer), %ebx -.write_char: movl (%edi), %eax testb %al, %al jz .out @@ -211,9 +228,8 @@ Function(boot_vga_log) movw %ax, (%ebx) addl $2, %ebx inc %edi - jmp .write_char + jmp boot_vga_log .out: - movl %ebx, (Boot_VGA_Pointer) ret Function(boot_halt) @@ -242,12 +258,6 @@ Function(boot_cpuid_available) ret .section .data -Boot_VGA_Pointer: -.long Boot_VGA_Window_Start - - -Boot_Loader_String: -.asciz "Kernel of Truth Loader" Boot_Bad_Multiboot_Magic_String: .asciz "Bad multiboot magic. Incompatible bootloader." diff --git a/loader/x64/boot.c b/loader/x64/boot.c index e08d7cf..cc460a8 100644 --- a/loader/x64/boot.c +++ b/loader/x64/boot.c @@ -1,4 +1,27 @@ #include +#include +#include +#include +#include + +#define ELF_BAD_BASE_ADDRESS (~0ul) + +size_t strlen(const char *str) { + const char *c; + for (c = str; *c != '\0'; ++c) { } + return c - str; +} + +int strncmp(const char *s1, const char *s2, size_t n) { + for (size_t i = 0; i < n && *s1 != '\0' && *s2 != '\0'; ++s1, ++s2, ++i) { + int diff = *s1 - *s2; + if (diff != 0) { + return diff; + } + } + return *s1 - *s2; +} + struct tss_entry { uint32_t reserved0; @@ -94,6 +117,313 @@ struct gdt_register Boot_GDT_Register = { .base = (uint64_t)&Boot_GDT, }; +static void *Boot_Allocator_Next_Page = (void *)0x1000; +static void *Boot_Allocator_Last_Page = NULL; + +void *boot_allocator(size_t pages) { + void *page = Boot_Allocator_Next_Page; + if (Boot_Allocator_Next_Page == Boot_Allocator_Last_Page) { + return NULL; + } + + Boot_Allocator_Next_Page += pages * Page_Small; + return page; +} + +void boot_allocator_init(uint64_t kilobytes) { + Boot_Allocator_Last_Page = (void *)(kilobytes * KB); +} + +static uint16_t *const Boot_VGA_Window = (uint16_t *)0xb8000; +static size_t Boot_VGA_Window_Index = 0; + +void boot_vga_log64(const char *string) { + for (const char *c = string; *c != '\0'; ++c) { + Boot_VGA_Window[Boot_VGA_Window_Index] = 0x0f00 | *c; + Boot_VGA_Window_Index++; + } +} + +void boot_log_number(uint64_t n) { + const size_t nibbles = sizeof(uint64_t) * 2; + char number[nibbles + 1]; + for (size_t i = 0; i < nibbles; ++i) { + int nibble = n % 16; + n /= 16; + if (nibble < 10) { + number[nibbles - i - 1] = nibble + '0'; + } else { + number[nibbles - i - 1] = nibble + 'a' - 10; + } + } + + number[nibbles] = '\0'; + boot_vga_log64(" "); + boot_vga_log64((const char *)&number); + boot_vga_log64(" "); +} + +#define Boot_Jitter_SHA1_Starting_Values 0xefcdab8967452301 + +#define Boot_Jitter_Max_Fold_Bits 4 +#define Boot_Jitter_Buffer_Size (2 * Page_Small) +#define Boot_Jitter_Fold_Mask (0xff) + +static inline uint64_t boot_cpu_get_ticks(void) { + uint32_t eax, edx; + __asm__ volatile ("rdtsc" : "=(eax)"(eax), "=(edx)"(edx)::); + return (((uint64_t)edx) << 32) | eax; +} + +uint64_t boot_memory_jitter_calculate(void) { + uint8_t *memory = boot_allocator(Boot_Jitter_Buffer_Size/Page_Small); + uint64_t entropy = Boot_Jitter_SHA1_Starting_Values; + for (size_t i = 0; i < Boot_Jitter_Buffer_Size; ++i) { + uint64_t before = boot_cpu_get_ticks(); + memory[i] += 1; + uint64_t after = boot_cpu_get_ticks(); + uint64_t delta = after - before; + entropy ^= delta & Boot_Jitter_Fold_Mask; + entropy = (entropy << 8) | (entropy & 0xff00000000000000) >> 56; + } + return entropy; +} + +/* +uint32_t boot_crc32(void *start, size_t size) { + uint32_t checksum = 0; + uint32_t *chunks = start; + for (size_t i = 0; i < size / sizeof(uint32_t); ++i) { + __asm__ ("crc32 %0, %1" : "+r"(checksum), "=r"(chunks[i])); + } + boot_log_number(checksum); + return checksum; +} +*/ +static void *boot_elf_get_base_address(void *kernel_start, size_t kernel_size) { + size_t base = ELF_BAD_BASE_ADDRESS; + const struct elf64_header *header = kernel_start; + + const struct elf_section_header *sections = kernel_start + header->e_shoff; + if ((void *)sections + header->e_shentsize * header->e_shnum > kernel_start + kernel_size) { + return NULL; + } + + for (size_t i = 0; i < header->e_shnum; ++i) { + if (sections[i].sh_type != SHT_NULL && sections[i].sh_offset < base) { + base = sections[i].sh_offset; + } + } + + if (base == ELF_BAD_BASE_ADDRESS) { + return NULL; + } + + return (void *)base; +} + + +const void *boot_elf_get_section(const struct elf64_header *header, + const size_t size, const char *name, + size_t *section_size) { + const void *section; + const uint8_t *start = (const uint8_t *)header; + + const struct elf_section_header *sections = (const void *)start + + header->e_shoff; + if ((uint8_t *)(sections + header->e_shnum) > start + size) { + boot_vga_log64("Section header out of bounds"); + return NULL; + } -void loader_main(uint64_t multiboot_magic, uint64_t multiboot_info_physical) { + const char *strtab = (const char *)header + + sections[header->e_shstrndx].sh_offset; + if (strtab >= (const char *)header + size) { + boot_vga_log64("Strtab out of bounds"); + return NULL; + } + + for (size_t i = 0; i < header->e_shnum; ++i) { + const char *section_name = strtab + sections[i].sh_name; + if ((uint8_t *)section_name >= start + size) { + continue; + } + if (strncmp(name, section_name, strlen(name)) == 0) { + section = start + sections[i].sh_offset; + if ((void *)section > (void *)start + size) { + boot_vga_log64("Section out of bounds"); + boot_vga_log64(name); + return NULL; + } + *section_size = sections[i].sh_size; + return section; + } + } + + boot_vga_log64("Section not found"); + boot_vga_log64(name); + return NULL; +} + + +bool boot_elf_relocate(uint64_t random_address, void *kernel_start, size_t kernel_size) { + int64_t *pointer; + int64_t value; + const struct elf64_header *header = kernel_start; + const struct elf_symbol *symbol; + size_t rela_size; + const struct elf_rela *rela; + size_t dynsym_size; + const struct elf_symbol *dynsym; + size_t dynstr_size; + void *base; + + const struct elf_section_header *sections = (const void *)kernel_start + + header->e_shoff; + /* + if ((uint8_t *)(sections + header->e_shnum) > (uint8_t *)kernel_start + kernel_size) { + boot_vga_log64("Section header out of bounds"); + return false; + //return NULL; + } + */ + + const char *strtab = kernel_start + + sections[header->e_shstrndx].sh_offset; + if (strtab >= (const char *)header + kernel_size) { + boot_vga_log64("Strtab out of bounds"); + return false; + //return NULL; + } + + /* + for (size_t i = 0; i < header->e_shnum; ++i) { + + boot_vga_log64("a 5 a"); + //boot_vga_log64(&strtab[sections[i].sh_name]); + //boot_log_number(sections[i].sh_offset); + boot_log_number(sections[i].sh_type); + } + boot_vga_log64("a 6 a"); + */ + + const char *dynstr = boot_elf_get_section(kernel_start, + kernel_size, + ".dynstr", + &dynstr_size); + if (dynstr == NULL) { + boot_vga_log64("Couldn't find section .dynstr"); + return false; + } + + dynsym = boot_elf_get_section(kernel_start, kernel_size, ".dynsym", + &dynsym_size); + if (dynsym == NULL) { + boot_vga_log64("Couldn't find section .dynsym"); + return false; + } + + rela = boot_elf_get_section(kernel_start, kernel_size, ".rela.dyn", &rela_size); + if (rela == NULL) { + boot_vga_log64("Couldn't find section .rela.dyn"); + return false; + } + + base = boot_elf_get_base_address(kernel_start, kernel_size); + if (base == NULL) { + boot_vga_log64("Bad base"); + return false; + } + + for (size_t i = 0; i < rela_size / sizeof(struct elf_rela); ++i) { + int r_type = ELF64_R_TYPE(rela[i].r_info); + switch (r_type) { + case R_X86_64_RELATIVE: + pointer = kernel_start + rela[i].r_offset; + value = random_address + (uintptr_t)base + rela[i].r_addend; + *pointer = value; + break; + case R_X86_64_JUMP_SLOT: + case R_X86_64_GLOB_DAT: + case R_X86_64_64: + symbol = &dynsym[ELF64_R_SYM(rela[i].r_info)]; + if ((void *)(symbol + 1) > kernel_start + kernel_size) { + boot_vga_log64("Symbol out of bounds"); + return false; + } + pointer = kernel_start + (uintptr_t)base + rela[i].r_offset; + if (symbol->st_index == SHN_UNDEF) { + boot_vga_log64("External symbol not loaded"); + boot_vga_log64(&dynstr[symbol->st_name]); + return false; + } else if (r_type == R_X86_64_64) { + value = random_address + (uintptr_t)base + symbol->st_value + rela[i].r_addend; + } else { + value = random_address + (uintptr_t)base + symbol->st_value; + } + *pointer = value; + break; + default: + boot_vga_log64("Unable to resolve rela symbol"); + boot_log_number(rela[i].r_info); + return false; + } + } + + return true; +} + + + +bool boot_kernel_init(uint64_t random_address, void *kernel_start, size_t kernel_size) { + const char elf_magic[] = ELFMAG; + if (kernel_size < sizeof(struct elf64_header)) { + boot_vga_log64("Kernel is way too small"); + return false; + } + + if ((kernel_size % sizeof(uint32_t)) != 0) { + boot_vga_log64("Kernel size is not a multiple of 32 bits"); + return false; + } + + /* + if (boot_crc32(kernel_start, kernel_size) != Kernel_CRC32) { + boot_vga_log64("Kernel checksum failed"); + return false; + } + */ + + + struct elf64_header *header = kernel_start; + for (size_t i = 0; i < 4; ++i) { + if (header->e_ident[i] != elf_magic[i]) { + boot_vga_log64("Kernel isn't a valid ELF file"); + return false; + } + } + + if (!boot_elf_relocate(random_address, kernel_start, kernel_size)) { + boot_vga_log64("Couldn't relocate elf"); + return false; + } + return true; +} + +void boot_loader_main(struct multiboot_info *multiboot_info_physical) { + uint64_t random; + size_t kernel_size = sizeof(Kernel_ELF); + boot_vga_log64("Kernel of Truth Secondary Loader"); + boot_log_number(multiboot_info_physical); + boot_allocator_init(multiboot_info_physical->mem_lower); + do { + random = boot_memory_jitter_calculate() ^ Boot_Compile_Random_Number; + random |= Memory_Kernel_Set_Mask; + random = align_as(random, Page_Small); + boot_log_number(random); + } while (~0ul - random < kernel_size); + + if (!boot_kernel_init(random, &Kernel_ELF, kernel_size)) { + boot_vga_log64("Failed to load kernel"); + } } From 9e064f887bbe4f10307a1b166b08630e287065f9 Mon Sep 17 00:00:00 2001 From: Ian Kronquist Date: Sun, 9 Jul 2017 12:32:28 -0400 Subject: [PATCH 04/51] Optimize for a smaller header file --- loader/generate_kernel_header.py | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/loader/generate_kernel_header.py b/loader/generate_kernel_header.py index 29ce51e..1d0a6b8 100644 --- a/loader/generate_kernel_header.py +++ b/loader/generate_kernel_header.py @@ -1,16 +1,10 @@ import sys -prefix = ''' -#pragma once - +prefix = '''#pragma once #include +uint8_t Kernel_ELF[]={''' -uint8_t Kernel_ELF[] = { -''' - -suffix = ''' -}; - +suffix = '''}; ''' if __name__ == '__main__': @@ -22,5 +16,5 @@ header.write(prefix) with open(sys.argv[2], 'r') as elf: for byte in elf.read(): - header.write('{}, '.format(hex(ord(byte)))) + header.write('{},'.format(ord(byte))) header.write(suffix) From 185036c20a103dcb20685671ca4195ba537860d9 Mon Sep 17 00:00:00 2001 From: Ian Kronquist Date: Sun, 9 Jul 2017 12:33:05 -0400 Subject: [PATCH 05/51] Make kernel_main a constructor --- kernel/arch/x64/link.ld | 11 +++++++++++ kernel/core/main.c | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/kernel/arch/x64/link.ld b/kernel/arch/x64/link.ld index 2003093..dd2b816 100644 --- a/kernel/arch/x64/link.ld +++ b/kernel/arch/x64/link.ld @@ -10,6 +10,17 @@ SECTIONS { *(.text) } + .init_array : { + *(.init_array*) + *(.ctors*) + } + + .fini_array : { + *(.init_array*) + *(.dtors*) + } + + .data BLOCK(4K) : ALIGN(4K) { __text_end = .; __data_start = .; diff --git a/kernel/core/main.c b/kernel/core/main.c index d6ebcf9..6646dcc 100644 --- a/kernel/core/main.c +++ b/kernel/core/main.c @@ -16,7 +16,7 @@ #include -constructor void kernel_main(uint32_t multiboot_tables) { +constructor void kernel_main(uint64_t multiboot_tables) { assert_ok(log_init(Log_Debug, "log")); log(Log_None, Logo); logf(Log_None, "\tCPU Time %ld\n", cpu_time()); From 81a6116d05b5e0efc7ce3dbb6f5d933310d42b2c Mon Sep 17 00:00:00 2001 From: Ian Kronquist Date: Sun, 9 Jul 2017 12:33:48 -0400 Subject: [PATCH 06/51] Paging and elf loader Doesn't quite work -- the init array isn't being linked right. --- loader/x64/boot.c | 262 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 241 insertions(+), 21 deletions(-) diff --git a/loader/x64/boot.c b/loader/x64/boot.c index cc460a8..654cc32 100644 --- a/loader/x64/boot.c +++ b/loader/x64/boot.c @@ -5,6 +5,27 @@ #include #define ELF_BAD_BASE_ADDRESS (~0ul) +// Memory_Writable implies NX. We need this for higher levels of the page table. +#define Memory_Just_Writable (1 << 1) +#define invalid_phys_addr 0xfff + + +#define pl1_Count 512 +#define pl2_Count 512 +#define pl3_Count 512 +#define pl4_Count 512 + +#define pl1_offset 12 +#define pl1_mask 0777 +#define pl2_offset 21 +#define pl2_mask 0777 +#define pl3_offset 30 +#define pl3_mask 0777 +#define pl4_offset 39 +#define pl4_mask 0777 + +void boot_halt(void); + size_t strlen(const char *str) { const char *c; @@ -189,6 +210,122 @@ uint64_t boot_memory_jitter_calculate(void) { return entropy; } +static inline size_t pl4_index(void *address) { + return (uintptr_t)address >> pl4_offset & pl4_mask; +} + +static inline size_t pl3_index(void *address) { + return ((uintptr_t)address >> pl3_offset) & pl3_mask; +} + +static inline size_t pl2_index(void *address) { + return ((uintptr_t)address >> pl2_offset) & pl2_mask; +} + +static inline size_t pl1_index(void *address) { + return ((uintptr_t)address >> pl1_offset) & pl1_mask; +} + + +static uint64_t *get_pl4(void) { + return (uint64_t *)01777774004004004000000; +} + +static uint64_t *get_pl3_index(size_t pl4_index) { + return (uint64_t *)(01777774004004000000000 | (pl4_index << 12)); +} + +static uint64_t *get_pl2_index(size_t pl4_index, size_t pl3_index) { + return (uint64_t *)(01777774004000000000000 | (pl4_index << 21) | (pl3_index << 12)); +} + +static uint64_t *get_pl1_index(size_t pl4_index, size_t pl3_index, size_t pl2_index) { + return (uint64_t *)(01777774000000000000000 | (pl4_index << 30) | (pl3_index << 21) | (pl2_index << 12)); +} + +static void paging_page_invalidate(void *virt) { + __asm__ volatile ("invlpg %0" ::"m"(*(uint8_t *)virt)); +} + +static phys_addr *get_pl3(void *address) { + return get_pl3_index(pl4_index(address)); +} + +static phys_addr *get_pl2(void *address) { + return get_pl2_index(pl4_index(address), pl3_index(address)); +} + +static phys_addr *get_pl1(void *address) { + return get_pl1_index(pl4_index(address), pl3_index(address), pl2_index(address)); +} + +static inline bool is_pl3_present(phys_addr *pl4, void *address) { + return (pl4[pl4_index(address)] & Memory_Present) == 1; +} + +static inline bool is_pl2_present(phys_addr *level_three, void *address) { + return level_three[pl3_index(address)] & Memory_Present; +} + +static inline bool is_pl1_present(phys_addr *level_two, void *address) { + return level_two[pl2_index(address)] & Memory_Present; +} + +static inline bool is_Memory_Present(phys_addr *level_one, void *address) { + return level_one[pl1_index(address)] & Memory_Present; +} + + + +enum status boot_map_page(void *virtual_address, phys_addr phys_address, enum memory_attributes permissions) { + + phys_address = phys_address & ~Memory_Permissions_Mask; + phys_addr *level_four = get_pl4(); + phys_addr *level_three = get_pl3(virtual_address); + phys_addr *level_two = get_pl2(virtual_address); + phys_addr *level_one = get_pl1(virtual_address); + + if (!is_pl3_present(level_four, virtual_address)) { + phys_addr phys_address = (phys_addr)boot_allocator(Page_Small/KB); + if (phys_address == invalid_phys_addr) { + boot_vga_log64("l3"); + return Error_No_Memory; + } + level_four[pl4_index(virtual_address)] = phys_address | Memory_Just_Writable | Memory_User_Access | Memory_Present; + paging_page_invalidate(level_three); + } + + if (!is_pl2_present(level_three, virtual_address)) { + phys_addr phys_address = (phys_addr)boot_allocator(Page_Small/KB); + if (phys_address == invalid_phys_addr) { + boot_vga_log64("l2"); + return Error_No_Memory; + } + level_three[pl3_index(virtual_address)] = phys_address | Memory_Just_Writable | Memory_User_Access | Memory_Present; + paging_page_invalidate(level_two); + } + + if (!is_pl1_present(level_two, virtual_address)) { + phys_addr phys_address = (phys_addr)boot_allocator(Page_Small/KB); + if (phys_address == invalid_phys_addr) { + boot_vga_log64("l1"); + return Error_No_Memory; + } + level_two[pl2_index(virtual_address)] = phys_address | Memory_Just_Writable | Memory_User_Access | Memory_Present; + paging_page_invalidate(level_one); + } + + if (is_Memory_Present(level_one, virtual_address)) { + boot_vga_log64("The virtual address is already present"); + boot_log_number((uintptr_t)virtual_address); + return Error_Present; + } + + level_one[pl1_index(virtual_address)] = (phys_address | permissions | Memory_Present); + paging_page_invalidate(virtual_address); + + return Ok; +} /* uint32_t boot_crc32(void *start, size_t size) { uint32_t checksum = 0; @@ -278,39 +415,22 @@ bool boot_elf_relocate(uint64_t random_address, void *kernel_start, size_t kerne size_t dynstr_size; void *base; - const struct elf_section_header *sections = (const void *)kernel_start + - header->e_shoff; - /* + const struct elf_section_header *sections = (const void *)kernel_start + header->e_shoff; if ((uint8_t *)(sections + header->e_shnum) > (uint8_t *)kernel_start + kernel_size) { boot_vga_log64("Section header out of bounds"); return false; //return NULL; } - */ - const char *strtab = kernel_start + - sections[header->e_shstrndx].sh_offset; + const char *strtab = kernel_start + sections[header->e_shstrndx].sh_offset; if (strtab >= (const char *)header + kernel_size) { boot_vga_log64("Strtab out of bounds"); return false; //return NULL; } - /* - for (size_t i = 0; i < header->e_shnum; ++i) { - - boot_vga_log64("a 5 a"); - //boot_vga_log64(&strtab[sections[i].sh_name]); - //boot_log_number(sections[i].sh_offset); - boot_log_number(sections[i].sh_type); - } - boot_vga_log64("a 6 a"); - */ - const char *dynstr = boot_elf_get_section(kernel_start, - kernel_size, - ".dynstr", - &dynstr_size); + const char *dynstr = boot_elf_get_section(kernel_start, kernel_size, ".dynstr", &dynstr_size); if (dynstr == NULL) { boot_vga_log64("Couldn't find section .dynstr"); return false; @@ -410,11 +530,88 @@ bool boot_kernel_init(uint64_t random_address, void *kernel_start, size_t kernel return true; } + +static enum status boot_elf_allocate_bss(void *random_address, void *kernel_start, size_t kernel_size) { + + size_t bss_size; + void *bss = boot_elf_get_section(kernel_start, kernel_size, ".bss", &bss_size); + if (bss == NULL) { + boot_vga_log64("Couldn't find section .bss"); + return Error_Invalid; + } + void *base_bss = bss - kernel_start + random_address; + + phys_addr phys; + void *page; + for (page = base_bss, phys = (phys_addr)bss; phys < round_next((uintptr_t)bss + bss_size, Page_Small); page += Page_Small, phys += Page_Small) { + if (boot_map_page(page, phys, Memory_Writable) != Ok) { + return Error_Invalid; + } + } + + return Ok; +} + +static enum status boot_elf_kernel_enter(void *kernel_start, size_t kernel_size, struct multiboot_info *mb_info) { + void *base; + size_t funcs_size = 0; + bool funcs_size_found = false; + void (**funcs)(uint64_t) = NULL; + size_t dynamic_size; + const struct elf_dyn *dynamic = boot_elf_get_section(kernel_start, kernel_size, ".dynamic", &dynamic_size); + if (dynamic == NULL) { + boot_vga_log64("Couldn't find section .dynamic"); + return Error_Invalid; + } + + base = boot_elf_get_base_address(kernel_start, kernel_size); + if (base == NULL) { + boot_vga_log64("Bad base"); + return Error_Invalid; + } + + for (size_t i = 0; i < dynamic_size / sizeof(struct elf_dyn); ++i) { + if (dynamic[i].d_tag == DT_INIT_ARRAY) { + funcs = base + dynamic[i].d_un.d_ptr; + } else if (dynamic[i].d_tag == DT_INIT_ARRAYSZ) { + funcs_size = dynamic[i].d_un.d_val; + funcs_size_found = true; + } + + if (funcs != NULL && funcs_size_found) { + break; + } + } + + + if (funcs == NULL || !funcs_size_found) { + boot_vga_log64("Kernel has no entry point"); + return Ok; + } else if ((void *)funcs + funcs_size > kernel_start + kernel_size) { + boot_vga_log64("Kernel entry point out of bounds"); + return Error_Invalid; + } else if (funcs_size / sizeof(enum status (*)(void)) != 1) { + boot_vga_log64("Kernel should have one entry point"); + return Error_Invalid; + } + boot_vga_log64("call"); + boot_log_number(funcs[0]); + boot_log_number(mb_info); + while(1); + funcs[0]((uintptr_t)mb_info); + + // NOT REACHED + boot_vga_log64("Kernel main should never return!"); + boot_halt(); + return Error_Invalid; +} + + void boot_loader_main(struct multiboot_info *multiboot_info_physical) { uint64_t random; size_t kernel_size = sizeof(Kernel_ELF); boot_vga_log64("Kernel of Truth Secondary Loader"); - boot_log_number(multiboot_info_physical); + boot_log_number((uintptr_t)multiboot_info_physical); boot_allocator_init(multiboot_info_physical->mem_lower); do { random = boot_memory_jitter_calculate() ^ Boot_Compile_Random_Number; @@ -425,5 +622,28 @@ void boot_loader_main(struct multiboot_info *multiboot_info_physical) { if (!boot_kernel_init(random, &Kernel_ELF, kernel_size)) { boot_vga_log64("Failed to load kernel"); + return; + } + + // FIXME W^X/DEP + void *kernel_random_base = (void *)random; + phys_addr kernel_physical_base = (phys_addr)&Kernel_ELF; + for (size_t i = 0; i < kernel_size / Page_Small; ++i, kernel_random_base += Page_Small, kernel_physical_base += Page_Small) { + boot_map_page(kernel_random_base, kernel_physical_base, Memory_Writable); + } + boot_vga_log64("ready to roll"); + + enum status status = boot_elf_allocate_bss(kernel_random_base, &Kernel_ELF, kernel_size); + if (status != Ok) { + boot_vga_log64("Couldn't allocate bss"); + return; + }; + + boot_log_number(&Kernel_ELF); + boot_log_number(kernel_size); + boot_log_number(multiboot_info_physical); + status = boot_elf_kernel_enter(&Kernel_ELF, kernel_size, multiboot_info_physical); + if (status != Ok) { + boot_vga_log64("Couldn't enter kernel"); } } From 31df3947bc68a3e093da338e5abdfa6dac35b61c Mon Sep 17 00:00:00 2001 From: Ian Kronquist Date: Sun, 9 Jul 2017 19:18:26 -0400 Subject: [PATCH 07/51] Align embedded kernel array --- Makefile | 4 ++-- loader/generate_kernel_header.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 43e9bf2..c2eaf5c 100644 --- a/Makefile +++ b/Makefile @@ -160,10 +160,10 @@ clean: rm -rf $(BUILD_DIR) start: debug - $(QEMU) -kernel $(KERNEL) $(QEMU_FLAGS) -monitor stdio + $(QEMU) -kernel $(LOADER) $(QEMU_FLAGS) -monitor stdio start-log: debug - $(QEMU) -kernel $(KERNEL) -d in_asm,cpu_reset,exec,int,guest_errors,pcall \ + $(QEMU) -kernel $(LOADER) -d in_asm,cpu_reset,exec,int,guest_errors,pcall \ -D $(BUILD_DIR)/qemu.log $(QEMU_FLAGS) -monitor stdio -include $(OBJ:.o=.d) diff --git a/loader/generate_kernel_header.py b/loader/generate_kernel_header.py index 1d0a6b8..3ab8188 100644 --- a/loader/generate_kernel_header.py +++ b/loader/generate_kernel_header.py @@ -2,7 +2,7 @@ prefix = '''#pragma once #include -uint8_t Kernel_ELF[]={''' +uint8_t Kernel_ELF[]__attribute__((aligned(0x1000)))={''' suffix = '''}; ''' From 0402ffb55b0dfa84477a34d3d7174af58ee19d86 Mon Sep 17 00:00:00 2001 From: Ian Kronquist Date: Sun, 9 Jul 2017 19:19:09 -0400 Subject: [PATCH 08/51] Link kernel properly --- loader/x64/boot.c | 164 ++++++++++++++++++++++++++++------------------ 1 file changed, 100 insertions(+), 64 deletions(-) diff --git a/loader/x64/boot.c b/loader/x64/boot.c index 654cc32..a97bbf6 100644 --- a/loader/x64/boot.c +++ b/loader/x64/boot.c @@ -403,10 +403,9 @@ const void *boot_elf_get_section(const struct elf64_header *header, } -bool boot_elf_relocate(uint64_t random_address, void *kernel_start, size_t kernel_size) { +enum status boot_elf_relocate(void *kernel_start, size_t kernel_size) { int64_t *pointer; int64_t value; - const struct elf64_header *header = kernel_start; const struct elf_symbol *symbol; size_t rela_size; const struct elf_rela *rela; @@ -414,53 +413,43 @@ bool boot_elf_relocate(uint64_t random_address, void *kernel_start, size_t kerne const struct elf_symbol *dynsym; size_t dynstr_size; void *base; - - const struct elf_section_header *sections = (const void *)kernel_start + header->e_shoff; - if ((uint8_t *)(sections + header->e_shnum) > (uint8_t *)kernel_start + kernel_size) { - boot_vga_log64("Section header out of bounds"); - return false; - //return NULL; - } - - const char *strtab = kernel_start + sections[header->e_shstrndx].sh_offset; - if (strtab >= (const char *)header + kernel_size) { - boot_vga_log64("Strtab out of bounds"); - return false; - //return NULL; - } - - const char *dynstr = boot_elf_get_section(kernel_start, kernel_size, ".dynstr", &dynstr_size); if (dynstr == NULL) { boot_vga_log64("Couldn't find section .dynstr"); - return false; + return Error_Invalid; + } + + rela = boot_elf_get_section(kernel_start, kernel_size, ".rela.dyn", &rela_size); + if (rela == NULL) { + boot_vga_log64("Couldn't find section .rela.dyn"); + return Error_Invalid; } dynsym = boot_elf_get_section(kernel_start, kernel_size, ".dynsym", &dynsym_size); if (dynsym == NULL) { boot_vga_log64("Couldn't find section .dynsym"); - return false; + return Error_Invalid; } rela = boot_elf_get_section(kernel_start, kernel_size, ".rela.dyn", &rela_size); if (rela == NULL) { boot_vga_log64("Couldn't find section .rela.dyn"); - return false; + return Error_Invalid; } base = boot_elf_get_base_address(kernel_start, kernel_size); if (base == NULL) { boot_vga_log64("Bad base"); - return false; + return Error_Invalid; } for (size_t i = 0; i < rela_size / sizeof(struct elf_rela); ++i) { int r_type = ELF64_R_TYPE(rela[i].r_info); switch (r_type) { case R_X86_64_RELATIVE: - pointer = kernel_start + rela[i].r_offset; - value = random_address + (uintptr_t)base + rela[i].r_addend; + pointer = kernel_start + (uintptr_t)base + rela[i].r_offset; + value = (uintptr_t)kernel_start + (uintptr_t)base + rela[i].r_addend; *pointer = value; break; case R_X86_64_JUMP_SLOT: @@ -469,45 +458,44 @@ bool boot_elf_relocate(uint64_t random_address, void *kernel_start, size_t kerne symbol = &dynsym[ELF64_R_SYM(rela[i].r_info)]; if ((void *)(symbol + 1) > kernel_start + kernel_size) { boot_vga_log64("Symbol out of bounds"); - return false; + return Error_Invalid; } pointer = kernel_start + (uintptr_t)base + rela[i].r_offset; if (symbol->st_index == SHN_UNDEF) { - boot_vga_log64("External symbol not loaded"); - boot_vga_log64(&dynstr[symbol->st_name]); - return false; + boot_vga_log64("Undefined symbol"); + return Error_Invalid; } else if (r_type == R_X86_64_64) { - value = random_address + (uintptr_t)base + symbol->st_value + rela[i].r_addend; + value = (uintptr_t)kernel_start + (uintptr_t)base + symbol->st_value + rela[i].r_addend; } else { - value = random_address + (uintptr_t)base + symbol->st_value; + value = (uintptr_t)kernel_start + (uintptr_t)base + symbol->st_value; } *pointer = value; break; default: - boot_vga_log64("Unable to resolve rela symbol"); boot_log_number(rela[i].r_info); - return false; + return Error_Invalid; } } - return true; + return Ok; } -bool boot_kernel_init(uint64_t random_address, void *kernel_start, size_t kernel_size) { + +enum status boot_kernel_init(void *kernel_start, size_t kernel_size) { const char elf_magic[] = ELFMAG; if (kernel_size < sizeof(struct elf64_header)) { boot_vga_log64("Kernel is way too small"); - return false; + return Error_Invalid; } + /* if ((kernel_size % sizeof(uint32_t)) != 0) { boot_vga_log64("Kernel size is not a multiple of 32 bits"); return false; } - /* if (boot_crc32(kernel_start, kernel_size) != Kernel_CRC32) { boot_vga_log64("Kernel checksum failed"); return false; @@ -519,22 +507,22 @@ bool boot_kernel_init(uint64_t random_address, void *kernel_start, size_t kernel for (size_t i = 0; i < 4; ++i) { if (header->e_ident[i] != elf_magic[i]) { boot_vga_log64("Kernel isn't a valid ELF file"); - return false; + return Error_Invalid; } } - - if (!boot_elf_relocate(random_address, kernel_start, kernel_size)) { + enum status status = boot_elf_relocate(kernel_start, kernel_size); + if (status != Ok) { boot_vga_log64("Couldn't relocate elf"); - return false; + return status; } - return true; + return Ok; } static enum status boot_elf_allocate_bss(void *random_address, void *kernel_start, size_t kernel_size) { size_t bss_size; - void *bss = boot_elf_get_section(kernel_start, kernel_size, ".bss", &bss_size); + const void *bss = boot_elf_get_section(kernel_start, kernel_size, ".bss", &bss_size); if (bss == NULL) { boot_vga_log64("Couldn't find section .bss"); return Error_Invalid; @@ -544,7 +532,7 @@ static enum status boot_elf_allocate_bss(void *random_address, void *kernel_star phys_addr phys; void *page; for (page = base_bss, phys = (phys_addr)bss; phys < round_next((uintptr_t)bss + bss_size, Page_Small); page += Page_Small, phys += Page_Small) { - if (boot_map_page(page, phys, Memory_Writable) != Ok) { + if (boot_map_page(page, phys, Memory_Just_Writable) != Ok) { return Error_Invalid; } } @@ -552,7 +540,8 @@ static enum status boot_elf_allocate_bss(void *random_address, void *kernel_star return Ok; } -static enum status boot_elf_kernel_enter(void *kernel_start, size_t kernel_size, struct multiboot_info *mb_info) { +/* +void *boot_debugelf_kernel_enter(void *kernel_start, size_t kernel_size, struct multiboot_info *mb_info) { void *base; size_t funcs_size = 0; bool funcs_size_found = false; @@ -561,13 +550,13 @@ static enum status boot_elf_kernel_enter(void *kernel_start, size_t kernel_size, const struct elf_dyn *dynamic = boot_elf_get_section(kernel_start, kernel_size, ".dynamic", &dynamic_size); if (dynamic == NULL) { boot_vga_log64("Couldn't find section .dynamic"); - return Error_Invalid; + return NULL; } base = boot_elf_get_base_address(kernel_start, kernel_size); if (base == NULL) { boot_vga_log64("Bad base"); - return Error_Invalid; + return NULL; } for (size_t i = 0; i < dynamic_size / sizeof(struct elf_dyn); ++i) { @@ -586,8 +575,54 @@ static enum status boot_elf_kernel_enter(void *kernel_start, size_t kernel_size, if (funcs == NULL || !funcs_size_found) { boot_vga_log64("Kernel has no entry point"); - return Ok; + return NULL; } else if ((void *)funcs + funcs_size > kernel_start + kernel_size) { + boot_vga_log64("Kernel entry point out of bounds"); + return NULL; + } else if (funcs_size / sizeof(enum status (*)(void)) != 1) { + boot_vga_log64("Kernel should have one entry point"); + return NULL; + } + return funcs; +} +*/ + +enum status boot_elf_kernel_enter(void *kernel_start, size_t kernel_size, struct multiboot_info *mb_info) { + void *base; + size_t funcs_size = 0; + bool funcs_size_found = false; + void (**entrypoint)(uint64_t) = NULL; + size_t dynamic_size; + const struct elf_dyn *dynamic = boot_elf_get_section(kernel_start, kernel_size, ".dynamic", &dynamic_size); + if (dynamic == NULL) { + boot_vga_log64("Couldn't find section .dynamic"); + return Error_Invalid; + } + + base = boot_elf_get_base_address(kernel_start, kernel_size); + if (base == NULL) { + boot_vga_log64("Bad base"); + return Error_Invalid; + } + + for (size_t i = 0; i < dynamic_size / sizeof(struct elf_dyn); ++i) { + if (dynamic[i].d_tag == DT_INIT_ARRAY) { + entrypoint = kernel_start + (uintptr_t)base + dynamic[i].d_un.d_ptr; + } else if (dynamic[i].d_tag == DT_INIT_ARRAYSZ) { + funcs_size = dynamic[i].d_un.d_val; + funcs_size_found = true; + } + + if (entrypoint != NULL && funcs_size_found) { + break; + } + } + + + if (entrypoint == NULL || !funcs_size_found) { + boot_vga_log64("Kernel has no entry point"); + return Ok; + } else if ((void *)entrypoint + funcs_size > kernel_start + kernel_size) { boot_vga_log64("Kernel entry point out of bounds"); return Error_Invalid; } else if (funcs_size / sizeof(enum status (*)(void)) != 1) { @@ -595,10 +630,12 @@ static enum status boot_elf_kernel_enter(void *kernel_start, size_t kernel_size, return Error_Invalid; } boot_vga_log64("call"); - boot_log_number(funcs[0]); - boot_log_number(mb_info); - while(1); - funcs[0]((uintptr_t)mb_info); + + //boot_log_number((uintptr_t)&funcs[0]); + //boot_log_number((uintptr_t)funcs[0]); + boot_log_number((uintptr_t)entrypoint); + boot_log_number(*(uint64_t *)(entrypoint)); + entrypoint[0]((uintptr_t)mb_info); // NOT REACHED boot_vga_log64("Kernel main should never return!"); @@ -611,38 +648,37 @@ void boot_loader_main(struct multiboot_info *multiboot_info_physical) { uint64_t random; size_t kernel_size = sizeof(Kernel_ELF); boot_vga_log64("Kernel of Truth Secondary Loader"); - boot_log_number((uintptr_t)multiboot_info_physical); boot_allocator_init(multiboot_info_physical->mem_lower); do { random = boot_memory_jitter_calculate() ^ Boot_Compile_Random_Number; random |= Memory_Kernel_Set_Mask; random = align_as(random, Page_Small); - boot_log_number(random); } while (~0ul - random < kernel_size); - if (!boot_kernel_init(random, &Kernel_ELF, kernel_size)) { - boot_vga_log64("Failed to load kernel"); - return; - } - // FIXME W^X/DEP void *kernel_random_base = (void *)random; phys_addr kernel_physical_base = (phys_addr)&Kernel_ELF; - for (size_t i = 0; i < kernel_size / Page_Small; ++i, kernel_random_base += Page_Small, kernel_physical_base += Page_Small) { - boot_map_page(kernel_random_base, kernel_physical_base, Memory_Writable); + for (size_t i = 0; i < round_next(kernel_size, Page_Small) / Page_Small; ++i, kernel_random_base += Page_Small, kernel_physical_base += Page_Small) { + boot_map_page(kernel_random_base, kernel_physical_base, Memory_Just_Writable); } boot_vga_log64("ready to roll"); + boot_log_number(random); + boot_log_number((uintptr_t)random + kernel_size); + boot_log_number((uintptr_t)kernel_random_base); enum status status = boot_elf_allocate_bss(kernel_random_base, &Kernel_ELF, kernel_size); if (status != Ok) { boot_vga_log64("Couldn't allocate bss"); return; }; - boot_log_number(&Kernel_ELF); - boot_log_number(kernel_size); - boot_log_number(multiboot_info_physical); - status = boot_elf_kernel_enter(&Kernel_ELF, kernel_size, multiboot_info_physical); + status = boot_kernel_init((void *)random, kernel_size); + if (status != Ok) { + boot_vga_log64("Failed to load kernel"); + return; + } + + status = boot_elf_kernel_enter((void *)random, kernel_size, multiboot_info_physical); if (status != Ok) { boot_vga_log64("Couldn't enter kernel"); } From b53a1145838242eb2b37865c023abac98a1bbccf Mon Sep 17 00:00:00 2001 From: Ian Kronquist Date: Mon, 10 Jul 2017 21:36:54 -0400 Subject: [PATCH 09/51] Don't use a silly script to embed the elf kernel --- Makefile | 8 +--- loader/x64/boot.S | 9 +++++ loader/x64/boot.c | 98 ++++++++++++++++++++++++++--------------------- 3 files changed, 66 insertions(+), 49 deletions(-) diff --git a/Makefile b/Makefile index c2eaf5c..2463025 100644 --- a/Makefile +++ b/Makefile @@ -77,16 +77,13 @@ MAKE := make all: $(LOADER) $(MODULES) -include/loader/kernel.h: $(KERNEL64) - $(PYTHON) loader/generate_kernel_header.py $@ $< -$(LOADER64): loader/$(ARCH)/link.ld $(LOADER_OBJS) +$(LOADER64): loader/$(ARCH)/link.ld $(LOADER_OBJS) $(KERNEL64) $(CC) -T loader/$(ARCH)/link.ld $(LOADER_OBJS) $(LOADER_CFLAGS) -o $@ $< -nostdlib -$(LOADER): $(BUILD_DIR)/truth_loader.$(ARCH).elf64 +$(LOADER): $(LOADER64) $(OBJCOPY) $< -O elf32-i386 $@ - tools: $(BUILD_DIR)/tools/truesign $(BUILD_DIR)/tools/truesign: @@ -107,7 +104,6 @@ $(KERNEL): $(KERNEL)64 $(MODULES) $(OBJCOPY) $< -O elf32-i386 $@ $(KERNEL64): kernel/arch/$(ARCH)/link.ld $(OBJ) - #$(LD) -T kernel/arch/$(ARCH)/link.ld $(BUILD_DIR)/symbols.o -o $@ $(OBJ) $(LD) -T kernel/arch/$(ARCH)/link.ld -o $@ $(OBJ) -shared -soname="truth" -ffreestanding -nostdlib $(BUILD_DIR)/%.c.o: kernel/%.c include/truth/key.h diff --git a/loader/x64/boot.S b/loader/x64/boot.S index 8e21f83..dfc18be 100644 --- a/loader/x64/boot.S +++ b/loader/x64/boot.S @@ -276,3 +276,12 @@ Boot_No_NX_Bit_String: Boot_No_Syscall_String: .asciz "Syscall instruction not supported. Incompatible hardware." + +.section .data.kernel +.align Page_Small +.global _binary_build_truth_x64_elf64_start +.global _binary_build_truth_x64_elf64_end +_binary_build_truth_x64_elf64_start: +.incbin "build/truth.x64.elf64" +_binary_build_truth_x64_elf64_end: + diff --git a/loader/x64/boot.c b/loader/x64/boot.c index a97bbf6..e535c4c 100644 --- a/loader/x64/boot.c +++ b/loader/x64/boot.c @@ -9,6 +9,8 @@ #define Memory_Just_Writable (1 << 1) #define invalid_phys_addr 0xfff +extern uint8_t _binary_build_truth_x64_elf64_start[]; +extern uint8_t _binary_build_truth_x64_elf64_end[]; #define pl1_Count 512 #define pl2_Count 512 @@ -483,7 +485,30 @@ enum status boot_elf_relocate(void *kernel_start, size_t kernel_size) { -enum status boot_kernel_init(void *kernel_start, size_t kernel_size) { +static enum status boot_elf_allocate_bss(void *kernel_start, size_t kernel_size) { + + size_t bss_size; + const void *bss = boot_elf_get_section(kernel_start, kernel_size, ".bss", &bss_size); + if (bss == NULL) { + boot_vga_log64("Couldn't find section .bss"); + return Error_Invalid; + } + void *base_bss = bss - kernel_start; + + phys_addr phys; + void *page; + for (page = base_bss, phys = (phys_addr)bss; phys < bss_size / Page_Small + 5; page += Page_Small, phys += Page_Small) { + if (boot_map_page(page, phys, Memory_Just_Writable) != Ok) { + return Error_Invalid; + } + } + + return Ok; +} + + +enum status boot_kernel_init(void *random) { + const size_t kernel_size = _binary_build_truth_x64_elf64_end - _binary_build_truth_x64_elf64_start; const char elf_magic[] = ELFMAG; if (kernel_size < sizeof(struct elf64_header)) { boot_vga_log64("Kernel is way too small"); @@ -503,40 +528,43 @@ enum status boot_kernel_init(void *kernel_start, size_t kernel_size) { */ - struct elf64_header *header = kernel_start; + // FIXME W^X/DEP + void *addr; + phys_addr page; + for (addr = random, page = (phys_addr)_binary_build_truth_x64_elf64_start; + addr < random + kernel_size; + addr += Page_Small, page += Page_Small) { + boot_map_page(addr, page, Memory_Just_Writable); + } + + boot_log_number((uintptr_t)_binary_build_truth_x64_elf64_start); + struct elf64_header *header = (struct elf64_header *)_binary_build_truth_x64_elf64_start; + boot_log_number((uintptr_t)header); + boot_log_number((uintptr_t)header->e_shnum); + boot_log_number((uintptr_t)header->e_shoff); + boot_vga_log64(&header->e_ident); for (size_t i = 0; i < 4; ++i) { if (header->e_ident[i] != elf_magic[i]) { boot_vga_log64("Kernel isn't a valid ELF file"); return Error_Invalid; } } - enum status status = boot_elf_relocate(kernel_start, kernel_size); - if (status != Ok) { - boot_vga_log64("Couldn't relocate elf"); - return status; - } - return Ok; -} + boot_vga_log64("ready to roll"); -static enum status boot_elf_allocate_bss(void *random_address, void *kernel_start, size_t kernel_size) { - - size_t bss_size; - const void *bss = boot_elf_get_section(kernel_start, kernel_size, ".bss", &bss_size); - if (bss == NULL) { - boot_vga_log64("Couldn't find section .bss"); - return Error_Invalid; - } - void *base_bss = bss - kernel_start + random_address; + boot_log_number((uintptr_t)random); + boot_log_number((uintptr_t)random + kernel_size); + enum status status = boot_elf_allocate_bss(header, kernel_size); + if (status != Ok) { + boot_vga_log64("Couldn't allocate bss"); + return status; + }; - phys_addr phys; - void *page; - for (page = base_bss, phys = (phys_addr)bss; phys < round_next((uintptr_t)bss + bss_size, Page_Small); page += Page_Small, phys += Page_Small) { - if (boot_map_page(page, phys, Memory_Just_Writable) != Ok) { - return Error_Invalid; - } + status = boot_elf_relocate((void *)random, kernel_size); + if (status != Ok) { + boot_vga_log64("Couldn't relocate elf"); + return status; } - return Ok; } @@ -646,7 +674,7 @@ enum status boot_elf_kernel_enter(void *kernel_start, size_t kernel_size, struct void boot_loader_main(struct multiboot_info *multiboot_info_physical) { uint64_t random; - size_t kernel_size = sizeof(Kernel_ELF); + size_t kernel_size = _binary_build_truth_x64_elf64_end - _binary_build_truth_x64_elf64_start; boot_vga_log64("Kernel of Truth Secondary Loader"); boot_allocator_init(multiboot_info_physical->mem_lower); do { @@ -655,24 +683,8 @@ void boot_loader_main(struct multiboot_info *multiboot_info_physical) { random = align_as(random, Page_Small); } while (~0ul - random < kernel_size); - // FIXME W^X/DEP - void *kernel_random_base = (void *)random; - phys_addr kernel_physical_base = (phys_addr)&Kernel_ELF; - for (size_t i = 0; i < round_next(kernel_size, Page_Small) / Page_Small; ++i, kernel_random_base += Page_Small, kernel_physical_base += Page_Small) { - boot_map_page(kernel_random_base, kernel_physical_base, Memory_Just_Writable); - } - boot_vga_log64("ready to roll"); - - boot_log_number(random); - boot_log_number((uintptr_t)random + kernel_size); - boot_log_number((uintptr_t)kernel_random_base); - enum status status = boot_elf_allocate_bss(kernel_random_base, &Kernel_ELF, kernel_size); - if (status != Ok) { - boot_vga_log64("Couldn't allocate bss"); - return; - }; - status = boot_kernel_init((void *)random, kernel_size); + enum status status = boot_kernel_init((void *)random); if (status != Ok) { boot_vga_log64("Failed to load kernel"); return; From 5a5d9d3cb8d281d76dac54f909cf2c44258b0921 Mon Sep 17 00:00:00 2001 From: Ian Kronquist Date: Mon, 10 Jul 2017 21:38:20 -0400 Subject: [PATCH 10/51] Tags should include loader --- Makefile | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index 2463025..487b92b 100644 --- a/Makefile +++ b/Makefile @@ -129,20 +129,14 @@ $(BUILD_DIR)/key.pub: $(BUILD_DIR)/tools/truesign include/truth/key.h: $(BUILD_DIR)/key.pub $(BUILD_DIR)/tools/truesign header $(BUILD_DIR)/key.pub $@ -#$(BUILD_DIR)/symbols.o: $(OBJ) kernel/arch/$(ARCH)/link.ld -# $(LD) -T kernel/arch/$(ARCH)/link.ld $(OBJ) -o $(KERNEL)64 $(LDFLAGS) -# nm $(KERNEL)64 | $(PYTHON) build_symbol_table.py $(BUILD_DIR)/symbols.S -# $(AS) -c $(BUILD_DIR)/symbols.S -o $@ $(ASFLAGS) - $(BUILD_DIR)/modules/%.ko: modules/% modules/link.ld $(BUILD_DIR)/key.pub mkdir -p $(shell dirname $@) $(MAKE) -C $< OUTFILE='../../$@' CFLAGS='$(MODULE_CFLAGS)' CC='$(MODULE_CC)' \ BUILD_DIR='../../$(BUILD_DIR)' LD='$(MODULE_LD)' \ AS='$(MODULE_AS)' -tags: kernel/arch/$(ARCH)/*.c kernel/core/*.c kernel/device/*.c \ - include/arch/$(ARCH)/*.h include/truth/*.h - ctags -R kernel include +tags: kernel/arch/$(ARCH)/*.c kernel/core/*.c kernel/device/*.c include/arch/$(ARCH)/*.h include/truth/*.h loader/$(ARCH)/*.c + ctags -R kernel include loader iso: $(BUILD_DIR)/truth.iso From 210bb7ba38aaeeaff5f1a0367ed5ae66a9aea588 Mon Sep 17 00:00:00 2001 From: Ian Kronquist Date: Mon, 10 Jul 2017 21:38:51 -0400 Subject: [PATCH 11/51] Don't need Python in the Makefile --- Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/Makefile b/Makefile index 487b92b..d218014 100644 --- a/Makefile +++ b/Makefile @@ -33,7 +33,6 @@ include kernel/device/Makefile include modules/Makefile -PYTHON := python OD := od LOADER_FLAGS := -O2 -MP -MMD \ From 014353e9e319cb863fdd940964748f71af4fd0d8 Mon Sep 17 00:00:00 2001 From: Ian Kronquist Date: Mon, 10 Jul 2017 21:40:31 -0400 Subject: [PATCH 12/51] Remove debug lines --- loader/x64/boot.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/loader/x64/boot.c b/loader/x64/boot.c index e535c4c..a10e1a4 100644 --- a/loader/x64/boot.c +++ b/loader/x64/boot.c @@ -537,12 +537,7 @@ enum status boot_kernel_init(void *random) { boot_map_page(addr, page, Memory_Just_Writable); } - boot_log_number((uintptr_t)_binary_build_truth_x64_elf64_start); struct elf64_header *header = (struct elf64_header *)_binary_build_truth_x64_elf64_start; - boot_log_number((uintptr_t)header); - boot_log_number((uintptr_t)header->e_shnum); - boot_log_number((uintptr_t)header->e_shoff); - boot_vga_log64(&header->e_ident); for (size_t i = 0; i < 4; ++i) { if (header->e_ident[i] != elf_magic[i]) { boot_vga_log64("Kernel isn't a valid ELF file"); @@ -552,8 +547,6 @@ enum status boot_kernel_init(void *random) { boot_vga_log64("ready to roll"); - boot_log_number((uintptr_t)random); - boot_log_number((uintptr_t)random + kernel_size); enum status status = boot_elf_allocate_bss(header, kernel_size); if (status != Ok) { boot_vga_log64("Couldn't allocate bss"); From e50a476426bb5d4b59b4a2be862f19f92c33a6f4 Mon Sep 17 00:00:00 2001 From: Ian Kronquist Date: Mon, 10 Jul 2017 21:42:39 -0400 Subject: [PATCH 13/51] Define 64 bit symtab macros as macro functions --- include/truth/elf.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/truth/elf.h b/include/truth/elf.h index e4ee9c4..383ae11 100644 --- a/include/truth/elf.h +++ b/include/truth/elf.h @@ -105,9 +105,9 @@ struct elf_symbol { #define ELF32_ST_TYPE(i) ((i) & 0x0f) #define ELF32_ST_INFO(b, t) (((b) << 4) + ((t) & 0x0f)) -#define ELF64_ST_BIND ELF32_ST_BIND -#define ELF64_ST_TYPE ELF32_ST_TYPE -#define ELF64_ST_INFO ELF32_ST_INFO +#define ELF64_ST_BIND(x) ELF32_ST_BIND(x) +#define ELF64_ST_TYPE(x) ELF32_ST_TYPE(x) +#define ELF64_ST_INFO(b, t) ELF32_ST_INFO((b), (t)) #define STB_LOCAL 0 #define STB_GLOBAL 1 From 305d0a97dcc521076874f7c9ba51a2f476a43ce9 Mon Sep 17 00:00:00 2001 From: Ian Kronquist Date: Mon, 10 Jul 2017 21:43:45 -0400 Subject: [PATCH 14/51] Remove debug logs & fix warnings --- loader/x64/boot.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/loader/x64/boot.c b/loader/x64/boot.c index a10e1a4..4e56488 100644 --- a/loader/x64/boot.c +++ b/loader/x64/boot.c @@ -493,7 +493,7 @@ static enum status boot_elf_allocate_bss(void *kernel_start, size_t kernel_size) boot_vga_log64("Couldn't find section .bss"); return Error_Invalid; } - void *base_bss = bss - kernel_start; + void *base_bss = (void *)(bss - kernel_start); phys_addr phys; void *page; @@ -650,12 +650,7 @@ enum status boot_elf_kernel_enter(void *kernel_start, size_t kernel_size, struct boot_vga_log64("Kernel should have one entry point"); return Error_Invalid; } - boot_vga_log64("call"); - //boot_log_number((uintptr_t)&funcs[0]); - //boot_log_number((uintptr_t)funcs[0]); - boot_log_number((uintptr_t)entrypoint); - boot_log_number(*(uint64_t *)(entrypoint)); entrypoint[0]((uintptr_t)mb_info); // NOT REACHED From 41b00c77322d85ddf8f7213e284a4aec24682426 Mon Sep 17 00:00:00 2001 From: Ian Kronquist Date: Mon, 10 Jul 2017 21:46:06 -0400 Subject: [PATCH 15/51] Remove more debug logs --- loader/x64/boot.S | 1 - loader/x64/boot.c | 5 ----- 2 files changed, 6 deletions(-) diff --git a/loader/x64/boot.S b/loader/x64/boot.S index dfc18be..44e5c40 100644 --- a/loader/x64/boot.S +++ b/loader/x64/boot.S @@ -18,7 +18,6 @@ .long MB_Magic .long MB_Flags .long MB_Checksum - .section .bss, "aw", @nobits .align Page_Small diff --git a/loader/x64/boot.c b/loader/x64/boot.c index 4e56488..75662b1 100644 --- a/loader/x64/boot.c +++ b/loader/x64/boot.c @@ -290,7 +290,6 @@ enum status boot_map_page(void *virtual_address, phys_addr phys_address, enum me if (!is_pl3_present(level_four, virtual_address)) { phys_addr phys_address = (phys_addr)boot_allocator(Page_Small/KB); if (phys_address == invalid_phys_addr) { - boot_vga_log64("l3"); return Error_No_Memory; } level_four[pl4_index(virtual_address)] = phys_address | Memory_Just_Writable | Memory_User_Access | Memory_Present; @@ -300,7 +299,6 @@ enum status boot_map_page(void *virtual_address, phys_addr phys_address, enum me if (!is_pl2_present(level_three, virtual_address)) { phys_addr phys_address = (phys_addr)boot_allocator(Page_Small/KB); if (phys_address == invalid_phys_addr) { - boot_vga_log64("l2"); return Error_No_Memory; } level_three[pl3_index(virtual_address)] = phys_address | Memory_Just_Writable | Memory_User_Access | Memory_Present; @@ -310,7 +308,6 @@ enum status boot_map_page(void *virtual_address, phys_addr phys_address, enum me if (!is_pl1_present(level_two, virtual_address)) { phys_addr phys_address = (phys_addr)boot_allocator(Page_Small/KB); if (phys_address == invalid_phys_addr) { - boot_vga_log64("l1"); return Error_No_Memory; } level_two[pl2_index(virtual_address)] = phys_address | Memory_Just_Writable | Memory_User_Access | Memory_Present; @@ -545,8 +542,6 @@ enum status boot_kernel_init(void *random) { } } - boot_vga_log64("ready to roll"); - enum status status = boot_elf_allocate_bss(header, kernel_size); if (status != Ok) { boot_vga_log64("Couldn't allocate bss"); From 8e3a1ac84ffc2cb91a4d6bf1db857ad54dd9df40 Mon Sep 17 00:00:00 2001 From: Ian Kronquist Date: Mon, 10 Jul 2017 21:46:54 -0400 Subject: [PATCH 16/51] Assembly definitions --- include/arch/x64/asm.h | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 include/arch/x64/asm.h diff --git a/include/arch/x64/asm.h b/include/arch/x64/asm.h new file mode 100644 index 0000000..32eae26 --- /dev/null +++ b/include/arch/x64/asm.h @@ -0,0 +1,3 @@ +#pragma once + +#define Function(x) .global x; .type x, @function; x: From 2ca93d4c1fdbcc57b842dc02c1537b2a4ef65f9a Mon Sep 17 00:00:00 2001 From: Ian Kronquist Date: Mon, 10 Jul 2017 21:47:19 -0400 Subject: [PATCH 17/51] Remove silly python script --- loader/generate_kernel_header.py | 20 -------------------- 1 file changed, 20 deletions(-) delete mode 100644 loader/generate_kernel_header.py diff --git a/loader/generate_kernel_header.py b/loader/generate_kernel_header.py deleted file mode 100644 index 3ab8188..0000000 --- a/loader/generate_kernel_header.py +++ /dev/null @@ -1,20 +0,0 @@ -import sys - -prefix = '''#pragma once -#include -uint8_t Kernel_ELF[]__attribute__((aligned(0x1000)))={''' - -suffix = '''}; -''' - -if __name__ == '__main__': - if len(sys.argv) != 3: - sys.stderr.write('Usage: {} elf_file header_file\n'.format(sys.argv[0])) - exit(-1) - - with open(sys.argv[1], 'w') as header: - header.write(prefix) - with open(sys.argv[2], 'r') as elf: - for byte in elf.read(): - header.write('{},'.format(ord(byte))) - header.write(suffix) From 1ce6181317a6c5aca68b14ec497519c92ab0073c Mon Sep 17 00:00:00 2001 From: Ian Kronquist Date: Mon, 10 Jul 2017 21:49:38 -0400 Subject: [PATCH 18/51] Fix Makefile loader dependencies & loader header --- Makefile | 4 ++-- loader/x64/boot.c | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index d218014..1f79e1b 100644 --- a/Makefile +++ b/Makefile @@ -113,11 +113,11 @@ $(BUILD_DIR)/%.S.o: kernel/%.S mkdir -p $(shell dirname $@) $(AS) -c $< -o $@ $(ASFLAGS) -$(BUILD_DIR)/loader/%.S.o: loader/%.S +$(BUILD_DIR)/loader/%.S.o: loader/%.S $(KERNEL64) mkdir -p $(shell dirname $@) $(AS) -c $< -o $@ $(LOADER_ASFLAGS) -$(BUILD_DIR)/loader/%.c.o: loader/%.c include/loader/kernel.h +$(BUILD_DIR)/loader/%.c.o: loader/%.c mkdir -p $(shell dirname $@) $(CC) -c $< -o $@ $(LOADER_CFLAGS) diff --git a/loader/x64/boot.c b/loader/x64/boot.c index 75662b1..c13703a 100644 --- a/loader/x64/boot.c +++ b/loader/x64/boot.c @@ -1,7 +1,6 @@ #include #include #include -#include #include #define ELF_BAD_BASE_ADDRESS (~0ul) From 8519a2ee49afa22330f0c81af8dfb9961e3ee8fe Mon Sep 17 00:00:00 2001 From: Ian Kronquist Date: Tue, 11 Jul 2017 19:41:00 -0400 Subject: [PATCH 19/51] Initialize BSS. --- loader/x64/boot.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/loader/x64/boot.c b/loader/x64/boot.c index c13703a..f5739e7 100644 --- a/loader/x64/boot.c +++ b/loader/x64/boot.c @@ -28,6 +28,15 @@ extern uint8_t _binary_build_truth_x64_elf64_end[]; void boot_halt(void); +// FIXME: This is inefficient. +void *memset(void *b, int c, size_t len) { + uint8_t *buf = b; + for (size_t i = 0; i < len; ++i) { + buf[i] = c; + } + return b; +} + size_t strlen(const char *str) { const char *c; for (c = str; *c != '\0'; ++c) { } @@ -493,12 +502,17 @@ static enum status boot_elf_allocate_bss(void *kernel_start, size_t kernel_size) phys_addr phys; void *page; - for (page = base_bss, phys = (phys_addr)bss; phys < bss_size / Page_Small + 5; page += Page_Small, phys += Page_Small) { + for (page = base_bss, phys = (phys_addr)bss; phys < ((bss_size / Page_Small) + 5); page += Page_Small, phys += Page_Small) { if (boot_map_page(page, phys, Memory_Just_Writable) != Ok) { return Error_Invalid; } } + boot_vga_log64("bss"); + boot_log_number(base_bss); + boot_log_number(base_bss + bss_size + (5 * Page_Small)); + memset(base_bss, 0, bss_size + (5 * Page_Small)); + return Ok; } @@ -541,7 +555,7 @@ enum status boot_kernel_init(void *random) { } } - enum status status = boot_elf_allocate_bss(header, kernel_size); + enum status status = boot_elf_allocate_bss(random, kernel_size); if (status != Ok) { boot_vga_log64("Couldn't allocate bss"); return status; @@ -606,7 +620,7 @@ enum status boot_elf_kernel_enter(void *kernel_start, size_t kernel_size, struct void *base; size_t funcs_size = 0; bool funcs_size_found = false; - void (**entrypoint)(uint64_t) = NULL; + void (**entrypoint)(void *, size_t, struct multiboot_info *) = NULL; size_t dynamic_size; const struct elf_dyn *dynamic = boot_elf_get_section(kernel_start, kernel_size, ".dynamic", &dynamic_size); if (dynamic == NULL) { @@ -645,7 +659,7 @@ enum status boot_elf_kernel_enter(void *kernel_start, size_t kernel_size, struct return Error_Invalid; } - entrypoint[0]((uintptr_t)mb_info); + entrypoint[0](kernel_start, kernel_size, mb_info); // NOT REACHED boot_vga_log64("Kernel main should never return!"); From 6fc95a17d5549d2581f8faab5dd6d87e1314ad6e Mon Sep 17 00:00:00 2001 From: Ian Kronquist Date: Tue, 11 Jul 2017 19:42:45 -0400 Subject: [PATCH 20/51] More parens around macro argument symbols --- include/truth/types.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/truth/types.h b/include/truth/types.h index 8cbf576..1bb9721 100644 --- a/include/truth/types.h +++ b/include/truth/types.h @@ -78,9 +78,9 @@ extern uint8_t __kernel_end; #define container_of(child, parent_type, parent_entry) \ ((parent_type)(child - &((parent_type)NULL)->parent_entry)) -#define align_as(value, alignment) (value & ~(alignment - 1)) +#define align_as(value, alignment) ((value) & ~((alignment) - 1)) #define is_power_of_two(value) ((((value) - 1) & value) == 0) -#define is_aligned(value, alignment) !(value & (alignment - 1)) +#define is_aligned(value, alignment) !((value) & ((alignment) - 1)) #define round_next(x, y) (((x) + (y - 1)) & ~(y - 1)) #define static_array_count(x) (sizeof(x) / sizeof(x)[0]) From d32d4c1d01eaf958cd3ebea49332dd195a79c7fd Mon Sep 17 00:00:00 2001 From: Ian Kronquist Date: Tue, 11 Jul 2017 19:43:35 -0400 Subject: [PATCH 21/51] Remove unnecessary instruction --- kernel/arch/x64/boot.S | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/kernel/arch/x64/boot.S b/kernel/arch/x64/boot.S index e377cfa..94d85ce 100644 --- a/kernel/arch/x64/boot.S +++ b/kernel/arch/x64/boot.S @@ -47,8 +47,7 @@ _init_stack_top: .code64 _start: # Initialize stack pointer. - # lea _init_stack_top(%rip), %rsi - movq %rsi, %rsp + lea _init_stack_top@GOTPCREL(%rip), %rsp call set_stack_guard call *kernel_main@GOTPCREL(%rip) From f0f4960c12c11ca2d994b3acfc456ac23ebd08c3 Mon Sep 17 00:00:00 2001 From: Ian Kronquist Date: Tue, 11 Jul 2017 19:44:07 -0400 Subject: [PATCH 22/51] Nuke unused debug code --- loader/x64/boot.c | 46 ---------------------------------------------- 1 file changed, 46 deletions(-) diff --git a/loader/x64/boot.c b/loader/x64/boot.c index f5739e7..47c8e43 100644 --- a/loader/x64/boot.c +++ b/loader/x64/boot.c @@ -569,52 +569,6 @@ enum status boot_kernel_init(void *random) { return Ok; } -/* -void *boot_debugelf_kernel_enter(void *kernel_start, size_t kernel_size, struct multiboot_info *mb_info) { - void *base; - size_t funcs_size = 0; - bool funcs_size_found = false; - void (**funcs)(uint64_t) = NULL; - size_t dynamic_size; - const struct elf_dyn *dynamic = boot_elf_get_section(kernel_start, kernel_size, ".dynamic", &dynamic_size); - if (dynamic == NULL) { - boot_vga_log64("Couldn't find section .dynamic"); - return NULL; - } - - base = boot_elf_get_base_address(kernel_start, kernel_size); - if (base == NULL) { - boot_vga_log64("Bad base"); - return NULL; - } - - for (size_t i = 0; i < dynamic_size / sizeof(struct elf_dyn); ++i) { - if (dynamic[i].d_tag == DT_INIT_ARRAY) { - funcs = base + dynamic[i].d_un.d_ptr; - } else if (dynamic[i].d_tag == DT_INIT_ARRAYSZ) { - funcs_size = dynamic[i].d_un.d_val; - funcs_size_found = true; - } - - if (funcs != NULL && funcs_size_found) { - break; - } - } - - - if (funcs == NULL || !funcs_size_found) { - boot_vga_log64("Kernel has no entry point"); - return NULL; - } else if ((void *)funcs + funcs_size > kernel_start + kernel_size) { - boot_vga_log64("Kernel entry point out of bounds"); - return NULL; - } else if (funcs_size / sizeof(enum status (*)(void)) != 1) { - boot_vga_log64("Kernel should have one entry point"); - return NULL; - } - return funcs; -} -*/ enum status boot_elf_kernel_enter(void *kernel_start, size_t kernel_size, struct multiboot_info *mb_info) { void *base; From 88eb7aece0e189fa66429047f0edddcfa6c9f32c Mon Sep 17 00:00:00 2001 From: Ian Kronquist Date: Tue, 11 Jul 2017 19:47:18 -0400 Subject: [PATCH 23/51] Use header e_entry as opposed to init_array --- Makefile | 2 +- kernel/core/main.c | 2 +- loader/x64/boot.c | 41 ++++------------------------------------- 3 files changed, 6 insertions(+), 39 deletions(-) diff --git a/Makefile b/Makefile index 1f79e1b..bd2f024 100644 --- a/Makefile +++ b/Makefile @@ -103,7 +103,7 @@ $(KERNEL): $(KERNEL)64 $(MODULES) $(OBJCOPY) $< -O elf32-i386 $@ $(KERNEL64): kernel/arch/$(ARCH)/link.ld $(OBJ) - $(LD) -T kernel/arch/$(ARCH)/link.ld -o $@ $(OBJ) -shared -soname="truth" -ffreestanding -nostdlib + $(LD) -T kernel/arch/$(ARCH)/link.ld -o $@ $(OBJ) -shared -soname="truth" -ffreestanding -nostdlib -z max-page-size=0x1000 -e kernel_main $(BUILD_DIR)/%.c.o: kernel/%.c include/truth/key.h mkdir -p $(shell dirname $@) diff --git a/kernel/core/main.c b/kernel/core/main.c index 6646dcc..c3821da 100644 --- a/kernel/core/main.c +++ b/kernel/core/main.c @@ -16,7 +16,7 @@ #include -constructor void kernel_main(uint64_t multiboot_tables) { +void kernel_main(void *kernel_start, size_t kernel_size, struct multiboot_tables *multiboot_tables) { assert_ok(log_init(Log_Debug, "log")); log(Log_None, Logo); logf(Log_None, "\tCPU Time %ld\n", cpu_time()); diff --git a/loader/x64/boot.c b/loader/x64/boot.c index 47c8e43..3b362d6 100644 --- a/loader/x64/boot.c +++ b/loader/x64/boot.c @@ -574,46 +574,13 @@ enum status boot_elf_kernel_enter(void *kernel_start, size_t kernel_size, struct void *base; size_t funcs_size = 0; bool funcs_size_found = false; - void (**entrypoint)(void *, size_t, struct multiboot_info *) = NULL; - size_t dynamic_size; - const struct elf_dyn *dynamic = boot_elf_get_section(kernel_start, kernel_size, ".dynamic", &dynamic_size); - if (dynamic == NULL) { - boot_vga_log64("Couldn't find section .dynamic"); - return Error_Invalid; - } - + void (*entrypoint)(void *, size_t, struct multiboot_info *) = NULL; + struct elf64_header *header = kernel_start; base = boot_elf_get_base_address(kernel_start, kernel_size); - if (base == NULL) { - boot_vga_log64("Bad base"); - return Error_Invalid; - } - - for (size_t i = 0; i < dynamic_size / sizeof(struct elf_dyn); ++i) { - if (dynamic[i].d_tag == DT_INIT_ARRAY) { - entrypoint = kernel_start + (uintptr_t)base + dynamic[i].d_un.d_ptr; - } else if (dynamic[i].d_tag == DT_INIT_ARRAYSZ) { - funcs_size = dynamic[i].d_un.d_val; - funcs_size_found = true; - } - - if (entrypoint != NULL && funcs_size_found) { - break; - } - } + entrypoint = kernel_start + (uintptr_t)base + header->e_entry; - if (entrypoint == NULL || !funcs_size_found) { - boot_vga_log64("Kernel has no entry point"); - return Ok; - } else if ((void *)entrypoint + funcs_size > kernel_start + kernel_size) { - boot_vga_log64("Kernel entry point out of bounds"); - return Error_Invalid; - } else if (funcs_size / sizeof(enum status (*)(void)) != 1) { - boot_vga_log64("Kernel should have one entry point"); - return Error_Invalid; - } - - entrypoint[0](kernel_start, kernel_size, mb_info); + entrypoint(kernel_start, kernel_size, mb_info); // NOT REACHED boot_vga_log64("Kernel main should never return!"); From 475c2b1a8bd1d336d5ba94e4adf3c05ef2020600 Mon Sep 17 00:00:00 2001 From: Ian Kronquist Date: Tue, 11 Jul 2017 19:59:03 -0400 Subject: [PATCH 24/51] Propagate const --- loader/x64/boot.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/loader/x64/boot.c b/loader/x64/boot.c index 3b362d6..75b0809 100644 --- a/loader/x64/boot.c +++ b/loader/x64/boot.c @@ -220,19 +220,19 @@ uint64_t boot_memory_jitter_calculate(void) { return entropy; } -static inline size_t pl4_index(void *address) { +static inline size_t pl4_index(const void *address) { return (uintptr_t)address >> pl4_offset & pl4_mask; } -static inline size_t pl3_index(void *address) { +static inline size_t pl3_index(const void *address) { return ((uintptr_t)address >> pl3_offset) & pl3_mask; } -static inline size_t pl2_index(void *address) { +static inline size_t pl2_index(const void *address) { return ((uintptr_t)address >> pl2_offset) & pl2_mask; } -static inline size_t pl1_index(void *address) { +static inline size_t pl1_index(const void *address) { return ((uintptr_t)address >> pl1_offset) & pl1_mask; } @@ -253,41 +253,41 @@ static uint64_t *get_pl1_index(size_t pl4_index, size_t pl3_index, size_t pl2_in return (uint64_t *)(01777774000000000000000 | (pl4_index << 30) | (pl3_index << 21) | (pl2_index << 12)); } -static void paging_page_invalidate(void *virt) { +static void paging_page_invalidate(const void *virt) { __asm__ volatile ("invlpg %0" ::"m"(*(uint8_t *)virt)); } -static phys_addr *get_pl3(void *address) { +static phys_addr *get_pl3(const void *address) { return get_pl3_index(pl4_index(address)); } -static phys_addr *get_pl2(void *address) { +static phys_addr *get_pl2(const void *address) { return get_pl2_index(pl4_index(address), pl3_index(address)); } -static phys_addr *get_pl1(void *address) { +static phys_addr *get_pl1(const void *address) { return get_pl1_index(pl4_index(address), pl3_index(address), pl2_index(address)); } -static inline bool is_pl3_present(phys_addr *pl4, void *address) { +static inline bool is_pl3_present(phys_addr *pl4, const void *address) { return (pl4[pl4_index(address)] & Memory_Present) == 1; } -static inline bool is_pl2_present(phys_addr *level_three, void *address) { +static inline bool is_pl2_present(phys_addr *level_three, const void *address) { return level_three[pl3_index(address)] & Memory_Present; } -static inline bool is_pl1_present(phys_addr *level_two, void *address) { +static inline bool is_pl1_present(phys_addr *level_two, const void *address) { return level_two[pl2_index(address)] & Memory_Present; } -static inline bool is_Memory_Present(phys_addr *level_one, void *address) { +static inline bool is_Memory_Present(phys_addr *level_one, const void *address) { return level_one[pl1_index(address)] & Memory_Present; } -enum status boot_map_page(void *virtual_address, phys_addr phys_address, enum memory_attributes permissions) { +enum status boot_map_page(const void *virtual_address, phys_addr phys_address, enum memory_attributes permissions) { phys_address = phys_address & ~Memory_Permissions_Mask; phys_addr *level_four = get_pl4(); From 99c5a70e5d523f573cf3be86bf0e5566a5731170 Mon Sep 17 00:00:00 2001 From: Ian Kronquist Date: Tue, 11 Jul 2017 19:59:39 -0400 Subject: [PATCH 25/51] Define funky symbols as typed macros --- loader/x64/boot.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/loader/x64/boot.c b/loader/x64/boot.c index 75b0809..58b020f 100644 --- a/loader/x64/boot.c +++ b/loader/x64/boot.c @@ -10,6 +10,8 @@ extern uint8_t _binary_build_truth_x64_elf64_start[]; extern uint8_t _binary_build_truth_x64_elf64_end[]; +#define Boot_Kernel_Physical_Start ((phys_addr)_binary_build_truth_x64_elf64_start) +#define Boot_Kernel_Physical_End ((phys_addr)_binary_build_truth_x64_elf64_end) #define pl1_Count 512 #define pl2_Count 512 @@ -518,7 +520,7 @@ static enum status boot_elf_allocate_bss(void *kernel_start, size_t kernel_size) enum status boot_kernel_init(void *random) { - const size_t kernel_size = _binary_build_truth_x64_elf64_end - _binary_build_truth_x64_elf64_start; + const size_t kernel_size = Boot_Kernel_Physical_End - Boot_Kernel_Physical_Start; const char elf_magic[] = ELFMAG; if (kernel_size < sizeof(struct elf64_header)) { boot_vga_log64("Kernel is way too small"); @@ -541,13 +543,13 @@ enum status boot_kernel_init(void *random) { // FIXME W^X/DEP void *addr; phys_addr page; - for (addr = random, page = (phys_addr)_binary_build_truth_x64_elf64_start; + for (addr = random, page = Boot_Kernel_Physical_Start; addr < random + kernel_size; addr += Page_Small, page += Page_Small) { boot_map_page(addr, page, Memory_Just_Writable); } - struct elf64_header *header = (struct elf64_header *)_binary_build_truth_x64_elf64_start; + struct elf64_header *header = (struct elf64_header *)Boot_Kernel_Physical_Start; for (size_t i = 0; i < 4; ++i) { if (header->e_ident[i] != elf_magic[i]) { boot_vga_log64("Kernel isn't a valid ELF file"); @@ -555,7 +557,7 @@ enum status boot_kernel_init(void *random) { } } - enum status status = boot_elf_allocate_bss(random, kernel_size); + enum status status = boot_elf_allocate_bss(random, Boot_Kernel_Physical_Start, kernel_size); if (status != Ok) { boot_vga_log64("Couldn't allocate bss"); return status; @@ -571,12 +573,9 @@ enum status boot_kernel_init(void *random) { enum status boot_elf_kernel_enter(void *kernel_start, size_t kernel_size, struct multiboot_info *mb_info) { - void *base; - size_t funcs_size = 0; - bool funcs_size_found = false; void (*entrypoint)(void *, size_t, struct multiboot_info *) = NULL; struct elf64_header *header = kernel_start; - base = boot_elf_get_base_address(kernel_start, kernel_size); + void *base = boot_elf_get_base_address(kernel_start, kernel_size); entrypoint = kernel_start + (uintptr_t)base + header->e_entry; @@ -591,7 +590,7 @@ enum status boot_elf_kernel_enter(void *kernel_start, size_t kernel_size, struct void boot_loader_main(struct multiboot_info *multiboot_info_physical) { uint64_t random; - size_t kernel_size = _binary_build_truth_x64_elf64_end - _binary_build_truth_x64_elf64_start; + size_t kernel_size = Boot_Kernel_Physical_End - Boot_Kernel_Physical_Start; boot_vga_log64("Kernel of Truth Secondary Loader"); boot_allocator_init(multiboot_info_physical->mem_lower); do { From f0addbaf36e6ac373bde1507fc8599b73d588449 Mon Sep 17 00:00:00 2001 From: Ian Kronquist Date: Tue, 11 Jul 2017 19:59:55 -0400 Subject: [PATCH 26/51] Refactor map bss function --- loader/x64/boot.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/loader/x64/boot.c b/loader/x64/boot.c index 58b020f..754e0a8 100644 --- a/loader/x64/boot.c +++ b/loader/x64/boot.c @@ -490,9 +490,7 @@ enum status boot_elf_relocate(void *kernel_start, size_t kernel_size) { } - - -static enum status boot_elf_allocate_bss(void *kernel_start, size_t kernel_size) { +static enum status boot_elf_allocate_bss(void *kernel_start, phys_addr kernel_phys, size_t kernel_size) { size_t bss_size; const void *bss = boot_elf_get_section(kernel_start, kernel_size, ".bss", &bss_size); @@ -500,20 +498,19 @@ static enum status boot_elf_allocate_bss(void *kernel_start, size_t kernel_size) boot_vga_log64("Couldn't find section .bss"); return Error_Invalid; } - void *base_bss = (void *)(bss - kernel_start); + size_t bss_offset = bss - kernel_start; + const void *bss_end = (void *)round_next((uintptr_t)bss + bss_size, Page_Small); - phys_addr phys; - void *page; - for (page = base_bss, phys = (phys_addr)bss; phys < ((bss_size / Page_Small) + 5); page += Page_Small, phys += Page_Small) { - if (boot_map_page(page, phys, Memory_Just_Writable) != Ok) { + phys_addr page = align_as(kernel_phys + bss_offset, Page_Small); + const void *addr = bss; + for (; addr < bss_end; addr += Page_Small, page += Page_Small) { + if (boot_map_page(addr, page, Memory_Just_Writable) != Ok) { return Error_Invalid; } } boot_vga_log64("bss"); - boot_log_number(base_bss); - boot_log_number(base_bss + bss_size + (5 * Page_Small)); - memset(base_bss, 0, bss_size + (5 * Page_Small)); + memset((void *)bss, 0, bss_size); return Ok; } From 90948f4d8155290d26a27f271844d7f0c74dfbdf Mon Sep 17 00:00:00 2001 From: Ian Kronquist Date: Tue, 11 Jul 2017 20:11:21 -0400 Subject: [PATCH 27/51] Force remap option --- loader/x64/boot.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/loader/x64/boot.c b/loader/x64/boot.c index 754e0a8..2cc1175 100644 --- a/loader/x64/boot.c +++ b/loader/x64/boot.c @@ -289,7 +289,7 @@ static inline bool is_Memory_Present(phys_addr *level_one, const void *address) -enum status boot_map_page(const void *virtual_address, phys_addr phys_address, enum memory_attributes permissions) { +enum status boot_map_page(const void *virtual_address, phys_addr phys_address, enum memory_attributes permissions, bool force) { phys_address = phys_address & ~Memory_Permissions_Mask; phys_addr *level_four = get_pl4(); @@ -324,7 +324,7 @@ enum status boot_map_page(const void *virtual_address, phys_addr phys_address, e paging_page_invalidate(level_one); } - if (is_Memory_Present(level_one, virtual_address)) { + if (!force && is_Memory_Present(level_one, virtual_address)) { boot_vga_log64("The virtual address is already present"); boot_log_number((uintptr_t)virtual_address); return Error_Present; @@ -499,12 +499,12 @@ static enum status boot_elf_allocate_bss(void *kernel_start, phys_addr kernel_ph return Error_Invalid; } size_t bss_offset = bss - kernel_start; - const void *bss_end = (void *)round_next((uintptr_t)bss + bss_size, Page_Small); + const void *bss_end = (const void *)round_next((uintptr_t)bss + bss_size, Page_Small); - phys_addr page = align_as(kernel_phys + bss_offset, Page_Small); - const void *addr = bss; + phys_addr page = round_next(kernel_phys + bss_offset + Page_Small, Page_Small); + const void *addr = (const void *)round_next((uintptr_t)bss + Page_Small, Page_Small); for (; addr < bss_end; addr += Page_Small, page += Page_Small) { - if (boot_map_page(addr, page, Memory_Just_Writable) != Ok) { + if (boot_map_page(addr, page, Memory_Just_Writable, true) != Ok) { return Error_Invalid; } } @@ -543,7 +543,7 @@ enum status boot_kernel_init(void *random) { for (addr = random, page = Boot_Kernel_Physical_Start; addr < random + kernel_size; addr += Page_Small, page += Page_Small) { - boot_map_page(addr, page, Memory_Just_Writable); + boot_map_page(addr, page, Memory_Just_Writable, false); } struct elf64_header *header = (struct elf64_header *)Boot_Kernel_Physical_Start; From 8c237b9768b36d9946837285f330ee17fc1f7983 Mon Sep 17 00:00:00 2001 From: Ian Kronquist Date: Tue, 11 Jul 2017 20:50:27 -0400 Subject: [PATCH 28/51] Checked wrong cpuid leaf --- loader/x64/boot.S | 49 ++++++++++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/loader/x64/boot.S b/loader/x64/boot.S index 44e5c40..6d38581 100644 --- a/loader/x64/boot.S +++ b/loader/x64/boot.S @@ -3,7 +3,7 @@ #define Boot_VGA_Window_Start 0xb8000 #define CPU_Flags_ID 0x00200000 -#define CPUId_Leaf_Manufacturer 0x0 +#define CPUId_Leaf_Feature_Info 0x1 #define CPUId_Leaf_Processor_Info 0x80000001 #define CPUId_EDX_Long_Mode (1 << 29) #define CPUId_EDX_Time_Step_Counter (1 << 4) @@ -66,58 +66,65 @@ Function(_start) pushl %ebx movl %esp, %ebp + + +.compat_check_multiboot: # Is this a multiboot compatible bootloader? cmpl $Multiboot_Register_Magic, %eax - je .compat_multiboot_magic_ok - # If not, clear the screen, print an error message, and hang. + je .compat_check_cpuid call boot_vga_clear + # If not, print an error message, and hang. movl $Boot_Bad_Multiboot_Magic_String, %edi jmp .bad_boot -.compat_multiboot_magic_ok: +.compat_check_cpuid: call boot_vga_clear # Is cpuid supported? It is if the eax register is not 0. call boot_cpuid_available testl %eax, %eax - jnz .compat_cpuid_available + jnz .compat_check_long_mode movl $Boot_No_CPUId, %edi jmp .bad_boot -.compat_cpuid_available: +.compat_check_long_mode: movl $CPUId_Leaf_Processor_Info, %eax cpuid movl %edx, %edi andl $CPUId_EDX_Long_Mode, %edi - jnz .compat_long_mode_supported + jnz .compat_check_nx movl $Boot_No_Long_Mode_String, %edi jmp .bad_boot -.compat_long_mode_supported: - movl %edx, %edi - andl $CPUId_EDX_Time_Step_Counter, %edi - jnz .compat_time_step_counter_available - movl $Boot_No_RDTSC_String, %edi - jmp .bad_boot - -.compat_time_step_counter_available: +.compat_check_nx: movl %edx, %edi andl $CPUId_EDX_Not_Executable_Pages, %edi - jnz .compat_nx_bit_available + jnz .compat_check_syscall movl $Boot_No_NX_Bit_String, %edi jmp .bad_boot -.compat_nx_bit_available: +.compat_check_syscall: movl %edx, %edi andl $CPUId_EDX_Syscall, %edi - jnz .compat_syscall_available + jnz .compat_check_tsc movl $Boot_No_Syscall_String, %edi jmp .bad_boot -.compat_syscall_available: +.compat_check_tsc: + movl $CPUId_Leaf_Feature_Info, %eax + cpuid + + movl %edx, %edi + andl $CPUId_EDX_Time_Step_Counter, %edi + jnz .enable_paging + movl $Boot_No_RDTSC_String, %edi + jmp .bad_boot + + +.enable_paging: call boot_map_page_table # Enable PAE. @@ -220,6 +227,8 @@ Function(boot_vga_clear) # void boot_vga_log(char *edi); Function(boot_vga_log) + movl $Boot_VGA_Window_Start, %ebx +.boot_vga_log_loop: movl (%edi), %eax testb %al, %al jz .out @@ -227,7 +236,7 @@ Function(boot_vga_log) movw %ax, (%ebx) addl $2, %ebx inc %edi - jmp boot_vga_log + jmp .boot_vga_log_loop .out: ret From a10eb1a7b46b8d3e5babcb74ca18ddedc4259f5d Mon Sep 17 00:00:00 2001 From: Ian Kronquist Date: Tue, 11 Jul 2017 21:58:43 -0400 Subject: [PATCH 29/51] Boot remap sections --- loader/x64/boot.c | 51 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 47 insertions(+), 4 deletions(-) diff --git a/loader/x64/boot.c b/loader/x64/boot.c index 2cc1175..189d5e1 100644 --- a/loader/x64/boot.c +++ b/loader/x64/boot.c @@ -490,7 +490,7 @@ enum status boot_elf_relocate(void *kernel_start, size_t kernel_size) { } -static enum status boot_elf_allocate_bss(void *kernel_start, phys_addr kernel_phys, size_t kernel_size) { +static enum status boot_elf_allocate_bss(void *kernel_start, phys_addr kernel_phys, size_t kernel_size, const void **bss_end) { size_t bss_size; const void *bss = boot_elf_get_section(kernel_start, kernel_size, ".bss", &bss_size); @@ -499,11 +499,11 @@ static enum status boot_elf_allocate_bss(void *kernel_start, phys_addr kernel_ph return Error_Invalid; } size_t bss_offset = bss - kernel_start; - const void *bss_end = (const void *)round_next((uintptr_t)bss + bss_size, Page_Small); + *bss_end = (const void *)round_next((uintptr_t)bss + bss_size, Page_Small); phys_addr page = round_next(kernel_phys + bss_offset + Page_Small, Page_Small); const void *addr = (const void *)round_next((uintptr_t)bss + Page_Small, Page_Small); - for (; addr < bss_end; addr += Page_Small, page += Page_Small) { + for (; addr < *bss_end; addr += Page_Small, page += Page_Small) { if (boot_map_page(addr, page, Memory_Just_Writable, true) != Ok) { return Error_Invalid; } @@ -512,6 +512,30 @@ static enum status boot_elf_allocate_bss(void *kernel_start, phys_addr kernel_ph boot_vga_log64("bss"); memset((void *)bss, 0, bss_size); + boot_log_number(bss_size); + return Ok; +} + +static enum status boot_remap_section(void *kernel_start, phys_addr kernel_phys, size_t kernel_size, const void *virtual_base, size_t *section_size, const char *section_name) { + enum status status; + const void *section = boot_elf_get_section(kernel_start, kernel_size, section_name, section_size); + if (section == NULL) { + boot_vga_log64("Section absent."); + return Error_Absent; + } + size_t section_offset = section - kernel_start; + phys_addr section_phys = kernel_phys + section_offset; + phys_addr section_phys_end = round_next(section_phys + *section_size, Page_Small); + phys_addr page = section_phys; + const void *addr = virtual_base; + for (; page < section_phys_end; page += Page_Small, addr += Page_Small) { + status = boot_map_page(addr, page, Memory_Just_Writable, false); + if (status != Ok) { + boot_vga_log64("Mapping already present."); + return status; + } + } + return Ok; } @@ -554,7 +578,9 @@ enum status boot_kernel_init(void *random) { } } - enum status status = boot_elf_allocate_bss(random, Boot_Kernel_Physical_Start, kernel_size); + const void *bss_end; + const void *kernel_end = (void *)round_next((uintptr_t)random + kernel_size, Page_Small); + enum status status = boot_elf_allocate_bss(random, Boot_Kernel_Physical_Start, kernel_size, &bss_end); if (status != Ok) { boot_vga_log64("Couldn't allocate bss"); return status; @@ -565,6 +591,23 @@ enum status boot_kernel_init(void *random) { boot_vga_log64("Couldn't relocate elf"); return status; } + boot_log_number(bss_end); + + size_t symtab_size; + status = boot_remap_section(random, Boot_Kernel_Physical_Start, kernel_size, kernel_end, &symtab_size, ".symtab"); + if (status != Ok) { + boot_vga_log64("Couldn't remap symtab"); + return status; + } + const void *symtab_end = (const void *)round_next((uintptr_t)kernel_end + symtab_size, Page_Small); + + size_t strtab_size; + status = boot_remap_section(random, Boot_Kernel_Physical_Start, kernel_size, symtab_end, &strtab_size, ".strtab"); + if (status != Ok) { + boot_vga_log64("Couldn't remap strtab"); + return status; + } + return Ok; } From 54d37fe26403e1d0d8ed113a278784da4f04b4a7 Mon Sep 17 00:00:00 2001 From: Ian Kronquist Date: Tue, 11 Jul 2017 22:58:55 -0400 Subject: [PATCH 30/51] Pass boot info from loader to kernel --- include/truth/boot.h | 19 ++++++++ kernel/core/main.c | 13 ++++-- loader/x64/boot.c | 103 +++++++++++++++++++++++++++++++++++-------- 3 files changed, 114 insertions(+), 21 deletions(-) create mode 100644 include/truth/boot.h diff --git a/include/truth/boot.h b/include/truth/boot.h new file mode 100644 index 0000000..d207612 --- /dev/null +++ b/include/truth/boot.h @@ -0,0 +1,19 @@ +#pragma once + +#include +#include + +struct boot_info { + const void *kernel; + phys_addr kernel_physical; + size_t kernel_size; + const void *strtab; + phys_addr strtab_physical; + size_t strtab_size; + const void *symtab; + phys_addr symtab_physical; + size_t symtab_size; + struct multiboot_info *multiboot_info; +}; + +#define Boot_Info_Name "Boot_Info" diff --git a/kernel/core/main.c b/kernel/core/main.c index c3821da..71c871b 100644 --- a/kernel/core/main.c +++ b/kernel/core/main.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -14,14 +15,20 @@ #include #include #include +#include -void kernel_main(void *kernel_start, size_t kernel_size, struct multiboot_tables *multiboot_tables) { +struct boot_info Boot_Info; + + +void kernel_main(void) { assert_ok(log_init(Log_Debug, "log")); log(Log_None, Logo); logf(Log_None, "\tCPU Time %ld\n", cpu_time()); + logf(Log_Debug, "Kernel start address: %p\nKernel size: %zu\nMultiboot tables: %p\n", Boot_Info.kernel, Boot_Info.kernel_size, Boot_Info.multiboot_info); interrupts_init(); - physical_allocator_init(phys_to_virt(multiboot_tables)); + halt(); + physical_allocator_init(Boot_Info.multiboot_info); slab_init(); logf(Log_Debug, "slab usage %lx\n", slab_get_usage()); assert_ok(heap_init()); @@ -30,7 +37,7 @@ void kernel_main(void *kernel_start, size_t kernel_size, struct multiboot_tables assert_ok(processes_init()); assert_ok(random_init()); logf(Log_Debug, "slab usage %lx\n", slab_get_usage()); - assert_ok(modules_init(phys_to_virt(multiboot_tables))); + assert_ok(modules_init(Boot_Info.multiboot_info)); timer_init(); keyboard_init(); vga_init(); diff --git a/loader/x64/boot.c b/loader/x64/boot.c index 189d5e1..62895c5 100644 --- a/loader/x64/boot.c +++ b/loader/x64/boot.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -28,6 +29,7 @@ extern uint8_t _binary_build_truth_x64_elf64_end[]; #define pl4_mask 0777 void boot_halt(void); +struct boot_info *Boot_Info_Pointer = NULL; // FIXME: This is inefficient. @@ -454,6 +456,12 @@ enum status boot_elf_relocate(void *kernel_start, size_t kernel_size) { } for (size_t i = 0; i < rela_size / sizeof(struct elf_rela); ++i) { + symbol = &dynsym[ELF64_R_SYM(rela[i].r_info)]; + if ((void *)(symbol + 1) > kernel_start + kernel_size) { + boot_vga_log64("Symbol out of bounds"); + return Error_Invalid; + } + int r_type = ELF64_R_TYPE(rela[i].r_info); switch (r_type) { case R_X86_64_RELATIVE: @@ -464,11 +472,6 @@ enum status boot_elf_relocate(void *kernel_start, size_t kernel_size) { case R_X86_64_JUMP_SLOT: case R_X86_64_GLOB_DAT: case R_X86_64_64: - symbol = &dynsym[ELF64_R_SYM(rela[i].r_info)]; - if ((void *)(symbol + 1) > kernel_start + kernel_size) { - boot_vga_log64("Symbol out of bounds"); - return Error_Invalid; - } pointer = kernel_start + (uintptr_t)base + rela[i].r_offset; if (symbol->st_index == SHN_UNDEF) { boot_vga_log64("Undefined symbol"); @@ -484,8 +487,20 @@ enum status boot_elf_relocate(void *kernel_start, size_t kernel_size) { boot_log_number(rela[i].r_info); return Error_Invalid; } + const char *symbol_name = &dynstr[symbol->st_name]; + if ((void *)symbol_name > kernel_start + kernel_size) { + boot_vga_log64("String out of bounds"); + return Error_Invalid; + } + if (strncmp(symbol_name, Boot_Info_Name, sizeof(Boot_Info_Name)) == 0) { + Boot_Info_Pointer = (struct boot_info *)value; + } } + if (Boot_Info_Pointer == NULL) { + boot_vga_log64("Couldn't find Boot Info structure"); + return Error_Absent; + } return Ok; } @@ -516,7 +531,7 @@ static enum status boot_elf_allocate_bss(void *kernel_start, phys_addr kernel_ph return Ok; } -static enum status boot_remap_section(void *kernel_start, phys_addr kernel_phys, size_t kernel_size, const void *virtual_base, size_t *section_size, const char *section_name) { +static enum status boot_remap_section(void *kernel_start, phys_addr kernel_phys, size_t kernel_size, const void *virtual_base, phys_addr *section_phys, size_t *section_size, const char *section_name) { enum status status; const void *section = boot_elf_get_section(kernel_start, kernel_size, section_name, section_size); if (section == NULL) { @@ -524,9 +539,9 @@ static enum status boot_remap_section(void *kernel_start, phys_addr kernel_phys, return Error_Absent; } size_t section_offset = section - kernel_start; - phys_addr section_phys = kernel_phys + section_offset; - phys_addr section_phys_end = round_next(section_phys + *section_size, Page_Small); - phys_addr page = section_phys; + *section_phys = kernel_phys + section_offset; + phys_addr section_phys_end = round_next(*section_phys + *section_size, Page_Small); + phys_addr page = *section_phys; const void *addr = virtual_base; for (; page < section_phys_end; page += Page_Small, addr += Page_Small) { status = boot_map_page(addr, page, Memory_Just_Writable, false); @@ -540,7 +555,7 @@ static enum status boot_remap_section(void *kernel_start, phys_addr kernel_phys, } -enum status boot_kernel_init(void *random) { +enum status boot_kernel_init(void *random, struct multiboot_info *multiboot_info) { const size_t kernel_size = Boot_Kernel_Physical_End - Boot_Kernel_Physical_Start; const char elf_magic[] = ELFMAG; if (kernel_size < sizeof(struct elf64_header)) { @@ -591,10 +606,10 @@ enum status boot_kernel_init(void *random) { boot_vga_log64("Couldn't relocate elf"); return status; } - boot_log_number(bss_end); size_t symtab_size; - status = boot_remap_section(random, Boot_Kernel_Physical_Start, kernel_size, kernel_end, &symtab_size, ".symtab"); + phys_addr symtab_phys; + status = boot_remap_section(random, Boot_Kernel_Physical_Start, kernel_size, kernel_end, &symtab_phys, &symtab_size, ".symtab"); if (status != Ok) { boot_vga_log64("Couldn't remap symtab"); return status; @@ -602,24 +617,76 @@ enum status boot_kernel_init(void *random) { const void *symtab_end = (const void *)round_next((uintptr_t)kernel_end + symtab_size, Page_Small); size_t strtab_size; - status = boot_remap_section(random, Boot_Kernel_Physical_Start, kernel_size, symtab_end, &strtab_size, ".strtab"); + phys_addr strtab_phys; + status = boot_remap_section(random, Boot_Kernel_Physical_Start, kernel_size, symtab_end, &strtab_phys, &strtab_size, ".strtab"); if (status != Ok) { boot_vga_log64("Couldn't remap strtab"); return status; } + const void *strtab_end = (const void *)round_next((uintptr_t)symtab_end + strtab_size, Page_Small); + + if (Boot_Info_Pointer == NULL) { + boot_vga_log64("Boot Info pointer is NULL"); + return Error_Absent; + } + + Boot_Info_Pointer->kernel = random; + Boot_Info_Pointer->kernel_size = kernel_size; + Boot_Info_Pointer->kernel_physical = Boot_Kernel_Physical_Start; + Boot_Info_Pointer->strtab_size = strtab_size; + Boot_Info_Pointer->strtab = kernel_end; + Boot_Info_Pointer->strtab_physical = strtab_phys; + Boot_Info_Pointer->symtab_size = symtab_size; + Boot_Info_Pointer->symtab = strtab_end; + Boot_Info_Pointer->symtab_physical = symtab_phys; + Boot_Info_Pointer->multiboot_info = multiboot_info; return Ok; } +/* +struct boot_info *boot_get_kernel_boot_info(void *kernel_start, size_t kernel_size) { + struct elf64_header *header = kernel_start; + size_t strtab_size; + const char *strtab = boot_elf_get_section(kernel_start, kernel_size, &strtab_size, ".strtab"); + if (strtab == NULL) { + boot_vga_log64("Couldn't find strtab"); + return NULL; + } + + size_t symtab_size; + struct elf_symbol *symtab = boot_elf_get_section(kernel_start, kernel_size, &symtab_size, ".symtab"); + if (symtab == NULL) { + boot_vga_log64("Couldn't find symtab"); + return NULL; + } + + for (size_t i = 0; i < symtab_size/ sizeof(struct elf_symbol); ++i) { + const char *symbol_name = &strtab[symtab[i].st_name]; + if ((void *)symbol_name > kernel_start + kernel_size) { + boot_vga_log64("Symbol name out of bounds"); + return NULL; + } + if (strncmp(symbol_name, Boot_Info_Name, sizeof(Boot_Info_Name)) == 0) { + struct boot_info + + return boot_info; + } + } + + return NULL; +} +*/ + -enum status boot_elf_kernel_enter(void *kernel_start, size_t kernel_size, struct multiboot_info *mb_info) { - void (*entrypoint)(void *, size_t, struct multiboot_info *) = NULL; +enum status boot_elf_kernel_enter(void *kernel_start, size_t kernel_size) { + void (*entrypoint)(void); struct elf64_header *header = kernel_start; void *base = boot_elf_get_base_address(kernel_start, kernel_size); entrypoint = kernel_start + (uintptr_t)base + header->e_entry; - entrypoint(kernel_start, kernel_size, mb_info); + entrypoint(); // NOT REACHED boot_vga_log64("Kernel main should never return!"); @@ -640,13 +707,13 @@ void boot_loader_main(struct multiboot_info *multiboot_info_physical) { } while (~0ul - random < kernel_size); - enum status status = boot_kernel_init((void *)random); + enum status status = boot_kernel_init((void *)random, multiboot_info_physical); if (status != Ok) { boot_vga_log64("Failed to load kernel"); return; } - status = boot_elf_kernel_enter((void *)random, kernel_size, multiboot_info_physical); + status = boot_elf_kernel_enter((void *)random, kernel_size); if (status != Ok) { boot_vga_log64("Couldn't enter kernel"); } From a5d9b4124040734cbee715855d7f42607c39c9e6 Mon Sep 17 00:00:00 2001 From: Ian Kronquist Date: Tue, 11 Jul 2017 23:03:42 -0400 Subject: [PATCH 31/51] Bounds check against right table during so loading --- kernel/core/elf.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/kernel/core/elf.c b/kernel/core/elf.c index 8bff8d5..c55d502 100644 --- a/kernel/core/elf.c +++ b/kernel/core/elf.c @@ -238,10 +238,7 @@ enum status elf_relocate(void *module_start, size_t module_size) { const struct elf_symbol *dynsym; size_t dynstr_size; void *base; - const char *dynstr = elf_get_section(module_start, - module_size, - ".dynstr", - &dynstr_size); + const char *dynstr = elf_get_section(module_start, module_size, ".dynstr", &dynstr_size); if (dynstr == NULL) { log(Log_Error, "Couldn't find section .dynstr"); return Error_Invalid; @@ -290,7 +287,7 @@ enum status elf_relocate(void *module_start, size_t module_size) { } pointer = base + rela[i].r_offset; if (symbol->st_index == SHN_UNDEF) { - if ((void *)&dynsym[symbol->st_name] > module_start + module_size) { + if ((void *)&dynstr[symbol->st_name] > module_start + module_size) { log(Log_Error, "String out of bounds"); return Error_Invalid; } From 6f55997d9edb21788419a48e0d48ccba5b9c62a4 Mon Sep 17 00:00:00 2001 From: Ian Kronquist Date: Tue, 11 Jul 2017 23:04:15 -0400 Subject: [PATCH 32/51] Add KASLR to readme feature list --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 982801a..a0adb69 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,7 @@ Kernel Features - [x] Elf loader. - [x] Loadable kernel modules. - [x] 🔐 Kernel module Address Space Layout Randomization (ASLR) & signature verification. +- [x] 🔐 Kernel Address Space Layout Randomization (KASLR). - [ ] Basic syscalls. - [ ] POSIX syscall layer. - [ ] EXT2 filesystem. From 58d01f356927e2cd95b06ca408d684ee314bb1d8 Mon Sep 17 00:00:00 2001 From: Ian Kronquist Date: Wed, 12 Jul 2017 00:10:14 -0400 Subject: [PATCH 33/51] Change strip target --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index bd2f024..ffd63d7 100644 --- a/Makefile +++ b/Makefile @@ -97,7 +97,7 @@ release: LOADER_ASFLAGS += -Werror release: CFLAGS += -Werror release: AFLAGS += -Werror release: all - $(STRIP) -s $(KERNEL) + $(STRIP) $(KERNEL64) $(KERNEL): $(KERNEL)64 $(MODULES) $(OBJCOPY) $< -O elf32-i386 $@ From 3dfec7730ba0a2322f36ffc0666d4dc1e8c4f375 Mon Sep 17 00:00:00 2001 From: Ian Kronquist Date: Wed, 12 Jul 2017 01:06:17 -0400 Subject: [PATCH 34/51] Don't fractal map in loader It's all identity mapped anyway, so. --- include/truth/types.h | 1 + loader/x64/boot.S | 2 -- loader/x64/boot.c | 50 +++++++++++++++++++------------------------ loader/x64/link.ld | 2 ++ 4 files changed, 25 insertions(+), 30 deletions(-) diff --git a/include/truth/types.h b/include/truth/types.h index 1bb9721..4e057fd 100644 --- a/include/truth/types.h +++ b/include/truth/types.h @@ -83,6 +83,7 @@ extern uint8_t __kernel_end; #define is_aligned(value, alignment) !((value) & ((alignment) - 1)) #define round_next(x, y) (((x) + (y - 1)) & ~(y - 1)) #define static_array_count(x) (sizeof(x) / sizeof(x)[0]) +#define min(x, y) ((x) < (y) ? (x) : (y)) #define check_format(x, y) __attribute__((format(printf, x, y))) #define checked __attribute__((warn_unused_result)) diff --git a/loader/x64/boot.S b/loader/x64/boot.S index 6d38581..193775d 100644 --- a/loader/x64/boot.S +++ b/loader/x64/boot.S @@ -181,8 +181,6 @@ Function(boot_map_page_table) movl $(init_pl1_b + (Page_Write | Page_Present)), init_pl2 + 8 movl $(init_pl1_c + (Page_Write | Page_Present)), init_pl2 + 16 - # Fractal mapping. - movl $(init_pl4 + (Page_Write | Page_Present)), init_pl4 + Kernel_Fractal_Page_Table_Index * 8 # Map first 4 MB except for the NULL page. movl $(init_pl1_a + 8), %edi movl $(0x1000 | Page_Present | Page_Write), %esi diff --git a/loader/x64/boot.c b/loader/x64/boot.c index 62895c5..545238b 100644 --- a/loader/x64/boot.c +++ b/loader/x64/boot.c @@ -9,8 +9,12 @@ #define Memory_Just_Writable (1 << 1) #define invalid_phys_addr 0xfff +extern uint8_t __loader_start[]; +extern uint8_t __loader_end[]; extern uint8_t _binary_build_truth_x64_elf64_start[]; extern uint8_t _binary_build_truth_x64_elf64_end[]; +#define Boot_Loader_Physical_Start ((phys_addr)__loader_start) +#define Boot_Loader_Physical_End ((phys_addr)__loader_end) #define Boot_Kernel_Physical_Start ((phys_addr)_binary_build_truth_x64_elf64_start) #define Boot_Kernel_Physical_End ((phys_addr)_binary_build_truth_x64_elf64_end) @@ -28,6 +32,12 @@ extern uint8_t _binary_build_truth_x64_elf64_end[]; #define pl4_offset 39 #define pl4_mask 0777 +static inline uint64_t boot_get_cr3(void) { + uint64_t cr3; + __asm__("mov %%cr3, %0" : "=r"(cr3)); + return cr3; +} + void boot_halt(void); struct boot_info *Boot_Info_Pointer = NULL; @@ -240,23 +250,6 @@ static inline size_t pl1_index(const void *address) { return ((uintptr_t)address >> pl1_offset) & pl1_mask; } - -static uint64_t *get_pl4(void) { - return (uint64_t *)01777774004004004000000; -} - -static uint64_t *get_pl3_index(size_t pl4_index) { - return (uint64_t *)(01777774004004000000000 | (pl4_index << 12)); -} - -static uint64_t *get_pl2_index(size_t pl4_index, size_t pl3_index) { - return (uint64_t *)(01777774004000000000000 | (pl4_index << 21) | (pl3_index << 12)); -} - -static uint64_t *get_pl1_index(size_t pl4_index, size_t pl3_index, size_t pl2_index) { - return (uint64_t *)(01777774000000000000000 | (pl4_index << 30) | (pl3_index << 21) | (pl2_index << 12)); -} - static void paging_page_invalidate(const void *virt) { __asm__ volatile ("invlpg %0" ::"m"(*(uint8_t *)virt)); } @@ -289,15 +282,17 @@ static inline bool is_Memory_Present(phys_addr *level_one, const void *address) return level_one[pl1_index(address)] & Memory_Present; } - +phys_addr *boot_page_table_entry(phys_addr p) { + return (phys_addr *)(p & ~Memory_Permissions_Mask); +} enum status boot_map_page(const void *virtual_address, phys_addr phys_address, enum memory_attributes permissions, bool force) { - phys_address = phys_address & ~Memory_Permissions_Mask; - phys_addr *level_four = get_pl4(); - phys_addr *level_three = get_pl3(virtual_address); - phys_addr *level_two = get_pl2(virtual_address); - phys_addr *level_one = get_pl1(virtual_address); + phys_address = (phys_addr)boot_page_table_entry(phys_address); + phys_addr *level_four = (phys_addr *)boot_get_cr3(); + phys_addr *level_three; + phys_addr *level_two; + phys_addr *level_one; if (!is_pl3_present(level_four, virtual_address)) { phys_addr phys_address = (phys_addr)boot_allocator(Page_Small/KB); @@ -305,8 +300,8 @@ enum status boot_map_page(const void *virtual_address, phys_addr phys_address, e return Error_No_Memory; } level_four[pl4_index(virtual_address)] = phys_address | Memory_Just_Writable | Memory_User_Access | Memory_Present; - paging_page_invalidate(level_three); } + level_three = boot_page_table_entry(level_four[pl4_index(virtual_address)]); if (!is_pl2_present(level_three, virtual_address)) { phys_addr phys_address = (phys_addr)boot_allocator(Page_Small/KB); @@ -314,8 +309,8 @@ enum status boot_map_page(const void *virtual_address, phys_addr phys_address, e return Error_No_Memory; } level_three[pl3_index(virtual_address)] = phys_address | Memory_Just_Writable | Memory_User_Access | Memory_Present; - paging_page_invalidate(level_two); } + level_two = boot_page_table_entry(level_three[pl3_index(virtual_address)]); if (!is_pl1_present(level_two, virtual_address)) { phys_addr phys_address = (phys_addr)boot_allocator(Page_Small/KB); @@ -323,8 +318,9 @@ enum status boot_map_page(const void *virtual_address, phys_addr phys_address, e return Error_No_Memory; } level_two[pl2_index(virtual_address)] = phys_address | Memory_Just_Writable | Memory_User_Access | Memory_Present; - paging_page_invalidate(level_one); } + level_one = boot_page_table_entry(level_two[pl2_index(virtual_address)]); + if (!force && is_Memory_Present(level_one, virtual_address)) { boot_vga_log64("The virtual address is already present"); @@ -524,10 +520,8 @@ static enum status boot_elf_allocate_bss(void *kernel_start, phys_addr kernel_ph } } - boot_vga_log64("bss"); memset((void *)bss, 0, bss_size); - boot_log_number(bss_size); return Ok; } diff --git a/loader/x64/link.ld b/loader/x64/link.ld index a684cc6..5e9ac37 100644 --- a/loader/x64/link.ld +++ b/loader/x64/link.ld @@ -3,6 +3,7 @@ ENTRY(_start) SECTIONS { . = 1M; + __loader_start = .; .text : AT(1M) { *(.text) } @@ -20,4 +21,5 @@ SECTIONS { } . = ALIGN(4K); + __loader_end = .; } From 407c071e000c3129daae22b947433cd768255f9a Mon Sep 17 00:00:00 2001 From: Ian Kronquist Date: Wed, 12 Jul 2017 01:08:10 -0400 Subject: [PATCH 35/51] Remove unused function --- loader/x64/boot.c | 34 ---------------------------------- 1 file changed, 34 deletions(-) diff --git a/loader/x64/boot.c b/loader/x64/boot.c index 545238b..ce21573 100644 --- a/loader/x64/boot.c +++ b/loader/x64/boot.c @@ -638,40 +638,6 @@ enum status boot_kernel_init(void *random, struct multiboot_info *multiboot_info return Ok; } -/* -struct boot_info *boot_get_kernel_boot_info(void *kernel_start, size_t kernel_size) { - struct elf64_header *header = kernel_start; - size_t strtab_size; - const char *strtab = boot_elf_get_section(kernel_start, kernel_size, &strtab_size, ".strtab"); - if (strtab == NULL) { - boot_vga_log64("Couldn't find strtab"); - return NULL; - } - - size_t symtab_size; - struct elf_symbol *symtab = boot_elf_get_section(kernel_start, kernel_size, &symtab_size, ".symtab"); - if (symtab == NULL) { - boot_vga_log64("Couldn't find symtab"); - return NULL; - } - - for (size_t i = 0; i < symtab_size/ sizeof(struct elf_symbol); ++i) { - const char *symbol_name = &strtab[symtab[i].st_name]; - if ((void *)symbol_name > kernel_start + kernel_size) { - boot_vga_log64("Symbol name out of bounds"); - return NULL; - } - if (strncmp(symbol_name, Boot_Info_Name, sizeof(Boot_Info_Name)) == 0) { - struct boot_info - - return boot_info; - } - } - - return NULL; -} -*/ - enum status boot_elf_kernel_enter(void *kernel_start, size_t kernel_size) { void (*entrypoint)(void); From 522b9852204f9a3886b4b69c6c1444449cc7b101 Mon Sep 17 00:00:00 2001 From: Ian Kronquist Date: Wed, 12 Jul 2017 01:08:55 -0400 Subject: [PATCH 36/51] Unused symbols --- loader/x64/boot.c | 4 ---- loader/x64/link.ld | 2 -- 2 files changed, 6 deletions(-) diff --git a/loader/x64/boot.c b/loader/x64/boot.c index ce21573..00f8b23 100644 --- a/loader/x64/boot.c +++ b/loader/x64/boot.c @@ -9,12 +9,8 @@ #define Memory_Just_Writable (1 << 1) #define invalid_phys_addr 0xfff -extern uint8_t __loader_start[]; -extern uint8_t __loader_end[]; extern uint8_t _binary_build_truth_x64_elf64_start[]; extern uint8_t _binary_build_truth_x64_elf64_end[]; -#define Boot_Loader_Physical_Start ((phys_addr)__loader_start) -#define Boot_Loader_Physical_End ((phys_addr)__loader_end) #define Boot_Kernel_Physical_Start ((phys_addr)_binary_build_truth_x64_elf64_start) #define Boot_Kernel_Physical_End ((phys_addr)_binary_build_truth_x64_elf64_end) diff --git a/loader/x64/link.ld b/loader/x64/link.ld index 5e9ac37..a684cc6 100644 --- a/loader/x64/link.ld +++ b/loader/x64/link.ld @@ -3,7 +3,6 @@ ENTRY(_start) SECTIONS { . = 1M; - __loader_start = .; .text : AT(1M) { *(.text) } @@ -21,5 +20,4 @@ SECTIONS { } . = ALIGN(4K); - __loader_end = .; } From 6ef784c2c66733e829cfe3566233e72646d989f1 Mon Sep 17 00:00:00 2001 From: Ian Kronquist Date: Wed, 12 Jul 2017 01:14:14 -0400 Subject: [PATCH 37/51] Remove unused functions --- loader/x64/boot.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/loader/x64/boot.c b/loader/x64/boot.c index 00f8b23..5221024 100644 --- a/loader/x64/boot.c +++ b/loader/x64/boot.c @@ -250,18 +250,6 @@ static void paging_page_invalidate(const void *virt) { __asm__ volatile ("invlpg %0" ::"m"(*(uint8_t *)virt)); } -static phys_addr *get_pl3(const void *address) { - return get_pl3_index(pl4_index(address)); -} - -static phys_addr *get_pl2(const void *address) { - return get_pl2_index(pl4_index(address), pl3_index(address)); -} - -static phys_addr *get_pl1(const void *address) { - return get_pl1_index(pl4_index(address), pl3_index(address), pl2_index(address)); -} - static inline bool is_pl3_present(phys_addr *pl4, const void *address) { return (pl4[pl4_index(address)] & Memory_Present) == 1; } From a2a4e53e8607521447c707719367855cf409f8af Mon Sep 17 00:00:00 2001 From: Ian Kronquist Date: Wed, 12 Jul 2017 01:14:39 -0400 Subject: [PATCH 38/51] Move string functions into own file --- include/loader/string.h | 7 +++++++ loader/x64/Makefile | 1 + loader/x64/boot.c | 24 +----------------------- loader/x64/string.c | 26 ++++++++++++++++++++++++++ 4 files changed, 35 insertions(+), 23 deletions(-) create mode 100644 include/loader/string.h create mode 100644 loader/x64/string.c diff --git a/include/loader/string.h b/include/loader/string.h new file mode 100644 index 0000000..cd80cf2 --- /dev/null +++ b/include/loader/string.h @@ -0,0 +1,7 @@ +#pragma once + +#include + +void *memset(void *b, int c, size_t len); +size_t strlen(const char *str); +int strncmp(const char *s1, const char *s2, size_t n); diff --git a/loader/x64/Makefile b/loader/x64/Makefile index 53d435d..09781a3 100644 --- a/loader/x64/Makefile +++ b/loader/x64/Makefile @@ -1,2 +1,3 @@ LOADER_OBJS += $(BUILD_DIR)/loader/$(ARCH)/boot.S.o LOADER_OBJS += $(BUILD_DIR)/loader/$(ARCH)/boot.c.o +LOADER_OBJS += $(BUILD_DIR)/loader/$(ARCH)/string.c.o diff --git a/loader/x64/boot.c b/loader/x64/boot.c index 5221024..8be0531 100644 --- a/loader/x64/boot.c +++ b/loader/x64/boot.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -38,30 +39,7 @@ void boot_halt(void); struct boot_info *Boot_Info_Pointer = NULL; -// FIXME: This is inefficient. -void *memset(void *b, int c, size_t len) { - uint8_t *buf = b; - for (size_t i = 0; i < len; ++i) { - buf[i] = c; - } - return b; -} - -size_t strlen(const char *str) { - const char *c; - for (c = str; *c != '\0'; ++c) { } - return c - str; -} -int strncmp(const char *s1, const char *s2, size_t n) { - for (size_t i = 0; i < n && *s1 != '\0' && *s2 != '\0'; ++s1, ++s2, ++i) { - int diff = *s1 - *s2; - if (diff != 0) { - return diff; - } - } - return *s1 - *s2; -} struct tss_entry { diff --git a/loader/x64/string.c b/loader/x64/string.c new file mode 100644 index 0000000..de8e98a --- /dev/null +++ b/loader/x64/string.c @@ -0,0 +1,26 @@ +#include + +// FIXME: This is inefficient. +void *memset(void *b, int c, size_t len) { + uint8_t *buf = b; + for (size_t i = 0; i < len; ++i) { + buf[i] = c; + } + return b; +} + +size_t strlen(const char *str) { + const char *c; + for (c = str; *c != '\0'; ++c) { } + return c - str; +} + +int strncmp(const char *s1, const char *s2, size_t n) { + for (size_t i = 0; i < n && *s1 != '\0' && *s2 != '\0'; ++s1, ++s2, ++i) { + int diff = *s1 - *s2; + if (diff != 0) { + return diff; + } + } + return *s1 - *s2; +} From d5d94f92095ae937ea39291733314e93c283a1dc Mon Sep 17 00:00:00 2001 From: Ian Kronquist Date: Wed, 12 Jul 2017 01:27:13 -0400 Subject: [PATCH 39/51] Split monolith into logical little pieces --- include/loader/allocator.h | 7 ++ include/loader/jitter.h | 5 + include/loader/log.h | 6 ++ include/loader/paging.h | 9 ++ loader/x64/Makefile | 4 + loader/x64/allocator.c | 20 ++++ loader/x64/boot.c | 185 +------------------------------------ loader/x64/jitter.c | 28 ++++++ loader/x64/log.c | 30 ++++++ loader/x64/paging.c | 111 ++++++++++++++++++++++ 10 files changed, 224 insertions(+), 181 deletions(-) create mode 100644 include/loader/allocator.h create mode 100644 include/loader/jitter.h create mode 100644 include/loader/log.h create mode 100644 include/loader/paging.h create mode 100644 loader/x64/allocator.c create mode 100644 loader/x64/jitter.c create mode 100644 loader/x64/log.c create mode 100644 loader/x64/paging.c diff --git a/include/loader/allocator.h b/include/loader/allocator.h new file mode 100644 index 0000000..52bc72c --- /dev/null +++ b/include/loader/allocator.h @@ -0,0 +1,7 @@ +#pragma once + +#include + + +void *boot_allocator(size_t pages); +void boot_allocator_init(uint64_t kilobytes); diff --git a/include/loader/jitter.h b/include/loader/jitter.h new file mode 100644 index 0000000..efe246b --- /dev/null +++ b/include/loader/jitter.h @@ -0,0 +1,5 @@ +#pragma once + +#include + +uint64_t boot_memory_jitter_calculate(void); diff --git a/include/loader/log.h b/include/loader/log.h new file mode 100644 index 0000000..90e8713 --- /dev/null +++ b/include/loader/log.h @@ -0,0 +1,6 @@ +#pragma once + +#include + +void boot_vga_log64(const char *string); +void boot_log_number(uint64_t n); diff --git a/include/loader/paging.h b/include/loader/paging.h new file mode 100644 index 0000000..abac3c4 --- /dev/null +++ b/include/loader/paging.h @@ -0,0 +1,9 @@ +#pragma once + +#include +#include + +// Memory_Writable implies NX. We need this for higher levels of the page table. +#define Memory_Just_Writable (1 << 1) +#define invalid_phys_addr 0xfff +enum status boot_map_page(const void *virtual_address, phys_addr phys_address, enum memory_attributes permissions, bool force); diff --git a/loader/x64/Makefile b/loader/x64/Makefile index 09781a3..e7b1297 100644 --- a/loader/x64/Makefile +++ b/loader/x64/Makefile @@ -1,3 +1,7 @@ LOADER_OBJS += $(BUILD_DIR)/loader/$(ARCH)/boot.S.o +LOADER_OBJS += $(BUILD_DIR)/loader/$(ARCH)/allocator.c.o LOADER_OBJS += $(BUILD_DIR)/loader/$(ARCH)/boot.c.o +LOADER_OBJS += $(BUILD_DIR)/loader/$(ARCH)/jitter.c.o +LOADER_OBJS += $(BUILD_DIR)/loader/$(ARCH)/paging.c.o +LOADER_OBJS += $(BUILD_DIR)/loader/$(ARCH)/log.c.o LOADER_OBJS += $(BUILD_DIR)/loader/$(ARCH)/string.c.o diff --git a/loader/x64/allocator.c b/loader/x64/allocator.c new file mode 100644 index 0000000..acaf299 --- /dev/null +++ b/loader/x64/allocator.c @@ -0,0 +1,20 @@ +#include +#include +#include + +static void *Boot_Allocator_Next_Page = (void *)0x1000; +static void *Boot_Allocator_Last_Page = NULL; + +void *boot_allocator(size_t pages) { + void *page = Boot_Allocator_Next_Page; + if (Boot_Allocator_Next_Page == Boot_Allocator_Last_Page) { + return NULL; + } + + Boot_Allocator_Next_Page += pages * Page_Small; + return page; +} + +void boot_allocator_init(uint64_t kilobytes) { + Boot_Allocator_Last_Page = (void *)(kilobytes * KB); +} diff --git a/loader/x64/boot.c b/loader/x64/boot.c index 8be0531..96f1720 100644 --- a/loader/x64/boot.c +++ b/loader/x64/boot.c @@ -1,3 +1,7 @@ +#include +#include +#include +#include #include #include #include @@ -6,35 +10,12 @@ #include #define ELF_BAD_BASE_ADDRESS (~0ul) -// Memory_Writable implies NX. We need this for higher levels of the page table. -#define Memory_Just_Writable (1 << 1) -#define invalid_phys_addr 0xfff extern uint8_t _binary_build_truth_x64_elf64_start[]; extern uint8_t _binary_build_truth_x64_elf64_end[]; #define Boot_Kernel_Physical_Start ((phys_addr)_binary_build_truth_x64_elf64_start) #define Boot_Kernel_Physical_End ((phys_addr)_binary_build_truth_x64_elf64_end) -#define pl1_Count 512 -#define pl2_Count 512 -#define pl3_Count 512 -#define pl4_Count 512 - -#define pl1_offset 12 -#define pl1_mask 0777 -#define pl2_offset 21 -#define pl2_mask 0777 -#define pl3_offset 30 -#define pl3_mask 0777 -#define pl4_offset 39 -#define pl4_mask 0777 - -static inline uint64_t boot_get_cr3(void) { - uint64_t cr3; - __asm__("mov %%cr3, %0" : "=r"(cr3)); - return cr3; -} - void boot_halt(void); struct boot_info *Boot_Info_Pointer = NULL; @@ -136,165 +117,7 @@ struct gdt_register Boot_GDT_Register = { .base = (uint64_t)&Boot_GDT, }; -static void *Boot_Allocator_Next_Page = (void *)0x1000; -static void *Boot_Allocator_Last_Page = NULL; - -void *boot_allocator(size_t pages) { - void *page = Boot_Allocator_Next_Page; - if (Boot_Allocator_Next_Page == Boot_Allocator_Last_Page) { - return NULL; - } - - Boot_Allocator_Next_Page += pages * Page_Small; - return page; -} - -void boot_allocator_init(uint64_t kilobytes) { - Boot_Allocator_Last_Page = (void *)(kilobytes * KB); -} - -static uint16_t *const Boot_VGA_Window = (uint16_t *)0xb8000; -static size_t Boot_VGA_Window_Index = 0; - -void boot_vga_log64(const char *string) { - for (const char *c = string; *c != '\0'; ++c) { - Boot_VGA_Window[Boot_VGA_Window_Index] = 0x0f00 | *c; - Boot_VGA_Window_Index++; - } -} - -void boot_log_number(uint64_t n) { - const size_t nibbles = sizeof(uint64_t) * 2; - char number[nibbles + 1]; - for (size_t i = 0; i < nibbles; ++i) { - int nibble = n % 16; - n /= 16; - if (nibble < 10) { - number[nibbles - i - 1] = nibble + '0'; - } else { - number[nibbles - i - 1] = nibble + 'a' - 10; - } - } - - number[nibbles] = '\0'; - boot_vga_log64(" "); - boot_vga_log64((const char *)&number); - boot_vga_log64(" "); -} - -#define Boot_Jitter_SHA1_Starting_Values 0xefcdab8967452301 - -#define Boot_Jitter_Max_Fold_Bits 4 -#define Boot_Jitter_Buffer_Size (2 * Page_Small) -#define Boot_Jitter_Fold_Mask (0xff) - -static inline uint64_t boot_cpu_get_ticks(void) { - uint32_t eax, edx; - __asm__ volatile ("rdtsc" : "=(eax)"(eax), "=(edx)"(edx)::); - return (((uint64_t)edx) << 32) | eax; -} - -uint64_t boot_memory_jitter_calculate(void) { - uint8_t *memory = boot_allocator(Boot_Jitter_Buffer_Size/Page_Small); - uint64_t entropy = Boot_Jitter_SHA1_Starting_Values; - for (size_t i = 0; i < Boot_Jitter_Buffer_Size; ++i) { - uint64_t before = boot_cpu_get_ticks(); - memory[i] += 1; - uint64_t after = boot_cpu_get_ticks(); - uint64_t delta = after - before; - entropy ^= delta & Boot_Jitter_Fold_Mask; - entropy = (entropy << 8) | (entropy & 0xff00000000000000) >> 56; - } - return entropy; -} - -static inline size_t pl4_index(const void *address) { - return (uintptr_t)address >> pl4_offset & pl4_mask; -} - -static inline size_t pl3_index(const void *address) { - return ((uintptr_t)address >> pl3_offset) & pl3_mask; -} - -static inline size_t pl2_index(const void *address) { - return ((uintptr_t)address >> pl2_offset) & pl2_mask; -} - -static inline size_t pl1_index(const void *address) { - return ((uintptr_t)address >> pl1_offset) & pl1_mask; -} - -static void paging_page_invalidate(const void *virt) { - __asm__ volatile ("invlpg %0" ::"m"(*(uint8_t *)virt)); -} - -static inline bool is_pl3_present(phys_addr *pl4, const void *address) { - return (pl4[pl4_index(address)] & Memory_Present) == 1; -} - -static inline bool is_pl2_present(phys_addr *level_three, const void *address) { - return level_three[pl3_index(address)] & Memory_Present; -} - -static inline bool is_pl1_present(phys_addr *level_two, const void *address) { - return level_two[pl2_index(address)] & Memory_Present; -} - -static inline bool is_Memory_Present(phys_addr *level_one, const void *address) { - return level_one[pl1_index(address)] & Memory_Present; -} - -phys_addr *boot_page_table_entry(phys_addr p) { - return (phys_addr *)(p & ~Memory_Permissions_Mask); -} - -enum status boot_map_page(const void *virtual_address, phys_addr phys_address, enum memory_attributes permissions, bool force) { - - phys_address = (phys_addr)boot_page_table_entry(phys_address); - phys_addr *level_four = (phys_addr *)boot_get_cr3(); - phys_addr *level_three; - phys_addr *level_two; - phys_addr *level_one; - if (!is_pl3_present(level_four, virtual_address)) { - phys_addr phys_address = (phys_addr)boot_allocator(Page_Small/KB); - if (phys_address == invalid_phys_addr) { - return Error_No_Memory; - } - level_four[pl4_index(virtual_address)] = phys_address | Memory_Just_Writable | Memory_User_Access | Memory_Present; - } - level_three = boot_page_table_entry(level_four[pl4_index(virtual_address)]); - - if (!is_pl2_present(level_three, virtual_address)) { - phys_addr phys_address = (phys_addr)boot_allocator(Page_Small/KB); - if (phys_address == invalid_phys_addr) { - return Error_No_Memory; - } - level_three[pl3_index(virtual_address)] = phys_address | Memory_Just_Writable | Memory_User_Access | Memory_Present; - } - level_two = boot_page_table_entry(level_three[pl3_index(virtual_address)]); - - if (!is_pl1_present(level_two, virtual_address)) { - phys_addr phys_address = (phys_addr)boot_allocator(Page_Small/KB); - if (phys_address == invalid_phys_addr) { - return Error_No_Memory; - } - level_two[pl2_index(virtual_address)] = phys_address | Memory_Just_Writable | Memory_User_Access | Memory_Present; - } - level_one = boot_page_table_entry(level_two[pl2_index(virtual_address)]); - - - if (!force && is_Memory_Present(level_one, virtual_address)) { - boot_vga_log64("The virtual address is already present"); - boot_log_number((uintptr_t)virtual_address); - return Error_Present; - } - - level_one[pl1_index(virtual_address)] = (phys_address | permissions | Memory_Present); - paging_page_invalidate(virtual_address); - - return Ok; -} /* uint32_t boot_crc32(void *start, size_t size) { uint32_t checksum = 0; diff --git a/loader/x64/jitter.c b/loader/x64/jitter.c new file mode 100644 index 0000000..2e37a14 --- /dev/null +++ b/loader/x64/jitter.c @@ -0,0 +1,28 @@ +#include +#include + +#define Boot_Jitter_SHA1_Starting_Values 0xefcdab8967452301 + +#define Boot_Jitter_Max_Fold_Bits 4 +#define Boot_Jitter_Buffer_Size (2 * Page_Small) +#define Boot_Jitter_Fold_Mask (0xff) + +static inline uint64_t boot_cpu_get_ticks(void) { + uint32_t eax, edx; + __asm__ volatile ("rdtsc" : "=(eax)"(eax), "=(edx)"(edx)::); + return (((uint64_t)edx) << 32) | eax; +} + +uint64_t boot_memory_jitter_calculate(void) { + uint8_t *memory = boot_allocator(Boot_Jitter_Buffer_Size/Page_Small); + uint64_t entropy = Boot_Jitter_SHA1_Starting_Values; + for (size_t i = 0; i < Boot_Jitter_Buffer_Size; ++i) { + uint64_t before = boot_cpu_get_ticks(); + memory[i] += 1; + uint64_t after = boot_cpu_get_ticks(); + uint64_t delta = after - before; + entropy ^= delta & Boot_Jitter_Fold_Mask; + entropy = (entropy << 8) | (entropy & 0xff00000000000000) >> 56; + } + return entropy; +} diff --git a/loader/x64/log.c b/loader/x64/log.c new file mode 100644 index 0000000..8e26008 --- /dev/null +++ b/loader/x64/log.c @@ -0,0 +1,30 @@ +#include + +static uint16_t *const Boot_VGA_Window = (uint16_t *)0xb8000; +static size_t Boot_VGA_Window_Index = 0; + +void boot_vga_log64(const char *string) { + for (const char *c = string; *c != '\0'; ++c) { + Boot_VGA_Window[Boot_VGA_Window_Index] = 0x0f00 | *c; + Boot_VGA_Window_Index++; + } +} + +void boot_log_number(uint64_t n) { + const size_t nibbles = sizeof(uint64_t) * 2; + char number[nibbles + 1]; + for (size_t i = 0; i < nibbles; ++i) { + int nibble = n % 16; + n /= 16; + if (nibble < 10) { + number[nibbles - i - 1] = nibble + '0'; + } else { + number[nibbles - i - 1] = nibble + 'a' - 10; + } + } + + number[nibbles] = '\0'; + boot_vga_log64(" "); + boot_vga_log64((const char *)&number); + boot_vga_log64(" "); +} diff --git a/loader/x64/paging.c b/loader/x64/paging.c new file mode 100644 index 0000000..ebf6523 --- /dev/null +++ b/loader/x64/paging.c @@ -0,0 +1,111 @@ +#include +#include + +#define pl1_Count 512 +#define pl2_Count 512 +#define pl3_Count 512 +#define pl4_Count 512 + +#define pl1_offset 12 +#define pl1_mask 0777 +#define pl2_offset 21 +#define pl2_mask 0777 +#define pl3_offset 30 +#define pl3_mask 0777 +#define pl4_offset 39 +#define pl4_mask 0777 + +static inline uint64_t boot_get_cr3(void) { + uint64_t cr3; + __asm__("mov %%cr3, %0" : "=r"(cr3)); + return cr3; +} + +static inline size_t pl4_index(const void *address) { + return (uintptr_t)address >> pl4_offset & pl4_mask; +} + +static inline size_t pl3_index(const void *address) { + return ((uintptr_t)address >> pl3_offset) & pl3_mask; +} + +static inline size_t pl2_index(const void *address) { + return ((uintptr_t)address >> pl2_offset) & pl2_mask; +} + +static inline size_t pl1_index(const void *address) { + return ((uintptr_t)address >> pl1_offset) & pl1_mask; +} + +static void paging_page_invalidate(const void *virt) { + __asm__ volatile ("invlpg %0" ::"m"(*(uint8_t *)virt)); +} + +static inline bool is_pl3_present(phys_addr *pl4, const void *address) { + return (pl4[pl4_index(address)] & Memory_Present) == 1; +} + +static inline bool is_pl2_present(phys_addr *level_three, const void *address) { + return level_three[pl3_index(address)] & Memory_Present; +} + +static inline bool is_pl1_present(phys_addr *level_two, const void *address) { + return level_two[pl2_index(address)] & Memory_Present; +} + +static inline bool is_Memory_Present(phys_addr *level_one, const void *address) { + return level_one[pl1_index(address)] & Memory_Present; +} + +static phys_addr *boot_page_table_entry(phys_addr p) { + return (phys_addr *)(p & ~Memory_Permissions_Mask); +} + +enum status boot_map_page(const void *virtual_address, phys_addr phys_address, enum memory_attributes permissions, bool force) { + + phys_address = (phys_addr)boot_page_table_entry(phys_address); + phys_addr *level_four = (phys_addr *)boot_get_cr3(); + phys_addr *level_three; + phys_addr *level_two; + phys_addr *level_one; + + if (!is_pl3_present(level_four, virtual_address)) { + phys_addr phys_address = (phys_addr)boot_allocator(Page_Small/KB); + if (phys_address == invalid_phys_addr) { + return Error_No_Memory; + } + level_four[pl4_index(virtual_address)] = phys_address | Memory_Just_Writable | Memory_User_Access | Memory_Present; + } + level_three = boot_page_table_entry(level_four[pl4_index(virtual_address)]); + + if (!is_pl2_present(level_three, virtual_address)) { + phys_addr phys_address = (phys_addr)boot_allocator(Page_Small/KB); + if (phys_address == invalid_phys_addr) { + return Error_No_Memory; + } + level_three[pl3_index(virtual_address)] = phys_address | Memory_Just_Writable | Memory_User_Access | Memory_Present; + } + level_two = boot_page_table_entry(level_three[pl3_index(virtual_address)]); + + if (!is_pl1_present(level_two, virtual_address)) { + phys_addr phys_address = (phys_addr)boot_allocator(Page_Small/KB); + if (phys_address == invalid_phys_addr) { + return Error_No_Memory; + } + level_two[pl2_index(virtual_address)] = phys_address | Memory_Just_Writable | Memory_User_Access | Memory_Present; + } + level_one = boot_page_table_entry(level_two[pl2_index(virtual_address)]); + + + if (!force && is_Memory_Present(level_one, virtual_address)) { + boot_vga_log64("The virtual address is already present"); + boot_log_number((uintptr_t)virtual_address); + return Error_Present; + } + + level_one[pl1_index(virtual_address)] = (phys_address | permissions | Memory_Present); + paging_page_invalidate(virtual_address); + + return Ok; +} + From a87e1e6dc45c0b9e8427cbea170d90e3fdae3865 Mon Sep 17 00:00:00 2001 From: Ian Kronquist Date: Wed, 12 Jul 2017 17:24:14 -0400 Subject: [PATCH 40/51] Move structure definitions to header file Share the definitions with the secondary loader --- include/arch/x64/segments.h | 56 +++++++++++++++++++++++++++ kernel/arch/x64/gdt.c | 75 +++---------------------------------- 2 files changed, 61 insertions(+), 70 deletions(-) diff --git a/include/arch/x64/segments.h b/include/arch/x64/segments.h index 235159a..89b1332 100644 --- a/include/arch/x64/segments.h +++ b/include/arch/x64/segments.h @@ -12,4 +12,60 @@ void tss_set_stack(void *stack); +struct tss_entry { + uint32_t reserved0; + uint64_t stack0; + uint64_t stack1; + uint64_t stack2; + uint64_t reserved1; + uint64_t ist[7]; + uint64_t reserved2; + uint16_t reserved3; + uint16_t iomap_base; +} pack; + +struct gdt_entry { + uint16_t limit_low; + uint16_t base_low; + uint8_t base_middle; + uint8_t access; + uint8_t granularity; + uint8_t base_high; +}; + +struct gdt_register { + uint16_t limit; + uint64_t base; +} pack; + + +#define Gran_64_Bit_Mode (1 << 5) +#define Gran_32_Bit_Mode (1 << 6) +#define Gran_4_KB_Blocks (1 << 7) + +#define gdt_entry(base, limit, access, granularity) \ + { (limit) & 0xffff, \ + (uint16_t) ((base) >> 0 & 0xffff), \ + (uint8_t) ((base) >> 16 & 0xff), \ + (access) & 0xff, \ + ((limit) >> 16 & 0x0f) | ((granularity) & 0xf0), \ + (uint8_t) ((base) >> 24 & 0xff), \ + } + +#define gdt_entry64(base, limit, access, granularity) \ + { (limit) & 0xffff, \ + (uint16_t) ((base) >> 0 & 0xffff), \ + (uint8_t) ((base) >> 16 & 0xff), \ + (access) & 0xff, \ + ((limit) >> 16 & 0x0f) | ((granularity) & 0xf0), \ + (uint8_t) ((base) >> 24 & 0xff), \ + }, \ + { (uint16_t) ((base) >> 32 & 0xffff), \ + (uint16_t) ((base) >> 48 & 0xffff), \ + 0, \ + 0, \ + 0, \ + 0, \ + } \ + #endif diff --git a/kernel/arch/x64/gdt.c b/kernel/arch/x64/gdt.c index 101a128..3c29aad 100644 --- a/kernel/arch/x64/gdt.c +++ b/kernel/arch/x64/gdt.c @@ -1,37 +1,6 @@ #include #include - -struct gdt_entry { - uint16_t limit_low; - uint16_t base_low; - uint8_t base_middle; - uint8_t access; - uint8_t granularity; - uint8_t base_high; -}; - -struct gdt_entry64 { - uint16_t limit_low; - uint16_t base_low; - uint8_t base_middle; - uint8_t access; - uint8_t granularity; - uint8_t base_high; - uint32_t base_highest; - uint32_t reserved0; -}; - -struct tss_entry { - uint32_t reserved0; - uint64_t stack0; - uint64_t stack1; - uint64_t stack2; - uint64_t reserved1; - uint64_t ist[7]; - uint64_t reserved2; - uint16_t reserved3; - uint16_t iomap_base; -} pack; +#include struct tss_entry Tss = { .reserved0 = 0, @@ -45,60 +14,26 @@ struct tss_entry Tss = { .iomap_base = 0, }; - -#define GRAN_64_BIT_MODE (1 << 5) -#define GRAN_32_BIT_MODE (1 << 6) -#define GRAN_4KIB_BLOCKS (1 << 7) - -#define gdt_entry(base, limit, access, granularity) \ - { (limit) & 0xffff, \ - (uint16_t) ((base) >> 0 & 0xffff), \ - (uint8_t) ((base) >> 16 & 0xff), \ - (access) & 0xff, \ - ((limit) >> 16 & 0x0f) | ((granularity) & 0xf0), \ - (uint8_t) ((base) >> 24 & 0xff), \ - } - -#define gdt_entry64(base, limit, access, granularity) \ - { (limit) & 0xffff, \ - (uint16_t) ((base) >> 0 & 0xffff), \ - (uint8_t) ((base) >> 16 & 0xff), \ - (access) & 0xff, \ - ((limit) >> 16 & 0x0f) | ((granularity) & 0xf0), \ - (uint8_t) ((base) >> 24 & 0xff), \ - }, \ - { (uint16_t) ((base) >> 32 & 0xffff), \ - (uint16_t) ((base) >> 48 & 0xffff), \ - 0, \ - 0, \ - 0, \ - 0, \ - } \ - struct gdt_entry GDT[] = { // NULL segment gdt_entry(0, 0, 0, 0), // Kernel Code Segment. - gdt_entry(0, 0xffffffff, 0x9a, GRAN_64_BIT_MODE | GRAN_4KIB_BLOCKS), + gdt_entry(0, 0xffffffff, 0x9a, Gran_64_Bit_Mode | Gran_4_KB_Blocks), // Kernel Data Segment. - gdt_entry(0, 0xffffffff, 0x92, GRAN_64_BIT_MODE | GRAN_4KIB_BLOCKS), + gdt_entry(0, 0xffffffff, 0x92, Gran_64_Bit_Mode | Gran_4_KB_Blocks), // User Code Segment. - gdt_entry(0, 0xffffffff, 0xfa, GRAN_64_BIT_MODE | GRAN_4KIB_BLOCKS), + gdt_entry(0, 0xffffffff, 0xfa, Gran_64_Bit_Mode | Gran_4_KB_Blocks), // User Data Segment. - gdt_entry(0, 0xffffffff, 0xf2, GRAN_64_BIT_MODE | GRAN_4KIB_BLOCKS), + gdt_entry(0, 0xffffffff, 0xf2, Gran_64_Bit_Mode | Gran_4_KB_Blocks), // Task Switch Segment. gdt_entry64(0ull, sizeof(Tss) - 1, 0xe9, 0x00), }; -struct gdt_register { - uint16_t limit; - uint64_t base; -} pack; struct gdt_register Physical_GDT_Register = { .limit = sizeof(GDT) - 1, From 1e7acfc4ce29586c3c0706d9d98f904c1f5e4c58 Mon Sep 17 00:00:00 2001 From: Ian Kronquist Date: Wed, 12 Jul 2017 17:24:43 -0400 Subject: [PATCH 41/51] Add #pragma once to elf header --- include/truth/elf.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/truth/elf.h b/include/truth/elf.h index 383ae11..5734cf6 100644 --- a/include/truth/elf.h +++ b/include/truth/elf.h @@ -1,3 +1,5 @@ +#pragma once + #include #define EI_CLASS 4 From 3cde7c32b39e123c30e7a6d2823f61308632688e Mon Sep 17 00:00:00 2001 From: Ian Kronquist Date: Wed, 12 Jul 2017 17:25:12 -0400 Subject: [PATCH 42/51] Change inline assembly to make clang-tidy happy --- include/arch/x64/cpu.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/arch/x64/cpu.h b/include/arch/x64/cpu.h index 8f63892..55627a2 100644 --- a/include/arch/x64/cpu.h +++ b/include/arch/x64/cpu.h @@ -30,7 +30,7 @@ static inline void cpu_flags_clear_ac(void) { static inline uint64_t cpu_get_ticks(void) { uint32_t eax, edx; - __asm__ volatile ("rdtsc" : "=(eax)"(eax), "=(edx)"(edx)::); + __asm__ volatile ("rdtsc" : "=a"(eax), "=d"(edx)::); return (((uint64_t)edx) << 32) | eax; } From a41b454a93f5d0e1139f08b844393687c401f6e5 Mon Sep 17 00:00:00 2001 From: Ian Kronquist Date: Wed, 12 Jul 2017 17:25:42 -0400 Subject: [PATCH 43/51] Define atomic macro which old clang doesn't have --- include/truth/types.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/truth/types.h b/include/truth/types.h index 4e057fd..5a7bbd4 100644 --- a/include/truth/types.h +++ b/include/truth/types.h @@ -6,6 +6,11 @@ #include #include +#ifndef ATOMIC_INT_LOCK_FREE +#define ATOMIC_INT_LOCK_FREE (0) +#endif + + typedef uint64_t phys_addr; enum partial { From eebcd94c817b50e5720f68dc9dd87d55ce24aded Mon Sep 17 00:00:00 2001 From: Ian Kronquist Date: Wed, 12 Jul 2017 17:26:56 -0400 Subject: [PATCH 44/51] Split elf and segments into separate files --- loader/x64/Makefile | 1 + loader/x64/boot.c | 317 +++----------------------------------------- loader/x64/elf.c | 279 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 296 insertions(+), 301 deletions(-) create mode 100644 loader/x64/elf.c diff --git a/loader/x64/Makefile b/loader/x64/Makefile index e7b1297..ffa171f 100644 --- a/loader/x64/Makefile +++ b/loader/x64/Makefile @@ -1,6 +1,7 @@ LOADER_OBJS += $(BUILD_DIR)/loader/$(ARCH)/boot.S.o LOADER_OBJS += $(BUILD_DIR)/loader/$(ARCH)/allocator.c.o LOADER_OBJS += $(BUILD_DIR)/loader/$(ARCH)/boot.c.o +LOADER_OBJS += $(BUILD_DIR)/loader/$(ARCH)/elf.c.o LOADER_OBJS += $(BUILD_DIR)/loader/$(ARCH)/jitter.c.o LOADER_OBJS += $(BUILD_DIR)/loader/$(ARCH)/paging.c.o LOADER_OBJS += $(BUILD_DIR)/loader/$(ARCH)/log.c.o diff --git a/loader/x64/boot.c b/loader/x64/boot.c index 96f1720..c2d6d06 100644 --- a/loader/x64/boot.c +++ b/loader/x64/boot.c @@ -1,4 +1,6 @@ #include +#include +#include #include #include #include @@ -7,93 +9,27 @@ #include #include #include +#include #include -#define ELF_BAD_BASE_ADDRESS (~0ul) extern uint8_t _binary_build_truth_x64_elf64_start[]; extern uint8_t _binary_build_truth_x64_elf64_end[]; #define Boot_Kernel_Physical_Start ((phys_addr)_binary_build_truth_x64_elf64_start) #define Boot_Kernel_Physical_End ((phys_addr)_binary_build_truth_x64_elf64_end) -void boot_halt(void); struct boot_info *Boot_Info_Pointer = NULL; - - - -struct tss_entry { - uint32_t reserved0; - uint64_t stack0; - uint64_t stack1; - uint64_t stack2; - uint64_t reserved1; - uint64_t ist[7]; - uint64_t reserved2; - uint16_t reserved3; - uint16_t iomap_base; -} pack; - -struct tss_entry Boot_TSS = { - .reserved0 = 0, - .stack0 = 0, - .stack1 = 0, - .stack2 = 0, - .reserved1 = 0, - .ist = { 0, 0, 0, 0, 0, 0, 0}, - .reserved2 = 0, - .reserved3 = 0, - .iomap_base = 0, -}; - -struct gdt_entry { - uint16_t limit_low; - uint16_t base_low; - uint8_t base_middle; - uint8_t access; - uint8_t granularity; - uint8_t base_high; -}; - -#define Gran_64_Bit_Mode (1 << 5) -#define Gran_32_Bit_Mode (1 << 6) -#define Gran_4_KB_BLocks (1 << 7) - -#define gdt_entry(base, limit, access, granularity) \ - { (limit) & 0xffff, \ - (uint16_t) ((base) >> 0 & 0xffff), \ - (uint8_t) ((base) >> 16 & 0xff), \ - (access) & 0xff, \ - ((limit) >> 16 & 0x0f) | ((granularity) & 0xf0), \ - (uint8_t) ((base) >> 24 & 0xff), \ - } - -#define gdt_entry64(base, limit, access, granularity) \ - { (limit) & 0xffff, \ - (uint16_t) ((base) >> 0 & 0xffff), \ - (uint8_t) ((base) >> 16 & 0xff), \ - (access) & 0xff, \ - ((limit) >> 16 & 0x0f) | ((granularity) & 0xf0), \ - (uint8_t) ((base) >> 24 & 0xff), \ - }, \ - { (uint16_t) ((base) >> 32 & 0xffff), \ - (uint16_t) ((base) >> 48 & 0xffff), \ - 0, \ - 0, \ - 0, \ - 0, \ - } \ - struct gdt_entry Boot_GDT[] = { // NULL segment gdt_entry(0, 0, 0, 0), // Kernel Code Segment. - gdt_entry(0, 0xffffffff, 0x9a, Gran_64_Bit_Mode | Gran_4_KB_BLocks), + gdt_entry(0, 0xffffffff, 0x9a, Gran_64_Bit_Mode | Gran_4_KB_Blocks), // Kernel Data Segment. - gdt_entry(0, 0xffffffff, 0x92, Gran_64_Bit_Mode | Gran_4_KB_BLocks), + gdt_entry(0, 0xffffffff, 0x92, Gran_64_Bit_Mode | Gran_4_KB_Blocks), // User code and data segments would go here, but we don't need them in // early boot. @@ -102,16 +38,9 @@ struct gdt_entry Boot_GDT[] = { {0}, {0}, - - // Task Switch Segment. - gdt_entry64(0ull, sizeof(Boot_TSS) - 1, 0xe9, 0x00), + // We don't need the TSS though. }; -struct gdt_register { - uint16_t limit; - uint64_t base; -} pack; - struct gdt_register Boot_GDT_Register = { .limit = sizeof(Boot_GDT) - 1, .base = (uint64_t)&Boot_GDT, @@ -129,209 +58,9 @@ uint32_t boot_crc32(void *start, size_t size) { return checksum; } */ -static void *boot_elf_get_base_address(void *kernel_start, size_t kernel_size) { - size_t base = ELF_BAD_BASE_ADDRESS; - const struct elf64_header *header = kernel_start; - const struct elf_section_header *sections = kernel_start + header->e_shoff; - if ((void *)sections + header->e_shentsize * header->e_shnum > kernel_start + kernel_size) { - return NULL; - } - for (size_t i = 0; i < header->e_shnum; ++i) { - if (sections[i].sh_type != SHT_NULL && sections[i].sh_offset < base) { - base = sections[i].sh_offset; - } - } - if (base == ELF_BAD_BASE_ADDRESS) { - return NULL; - } - - return (void *)base; -} - - -const void *boot_elf_get_section(const struct elf64_header *header, - const size_t size, const char *name, - size_t *section_size) { - const void *section; - const uint8_t *start = (const uint8_t *)header; - - const struct elf_section_header *sections = (const void *)start + - header->e_shoff; - if ((uint8_t *)(sections + header->e_shnum) > start + size) { - boot_vga_log64("Section header out of bounds"); - return NULL; - } - - const char *strtab = (const char *)header + - sections[header->e_shstrndx].sh_offset; - if (strtab >= (const char *)header + size) { - boot_vga_log64("Strtab out of bounds"); - return NULL; - } - - for (size_t i = 0; i < header->e_shnum; ++i) { - const char *section_name = strtab + sections[i].sh_name; - if ((uint8_t *)section_name >= start + size) { - continue; - } - if (strncmp(name, section_name, strlen(name)) == 0) { - section = start + sections[i].sh_offset; - if ((void *)section > (void *)start + size) { - boot_vga_log64("Section out of bounds"); - boot_vga_log64(name); - return NULL; - } - *section_size = sections[i].sh_size; - return section; - } - } - - boot_vga_log64("Section not found"); - boot_vga_log64(name); - return NULL; -} - - -enum status boot_elf_relocate(void *kernel_start, size_t kernel_size) { - int64_t *pointer; - int64_t value; - const struct elf_symbol *symbol; - size_t rela_size; - const struct elf_rela *rela; - size_t dynsym_size; - const struct elf_symbol *dynsym; - size_t dynstr_size; - void *base; - const char *dynstr = boot_elf_get_section(kernel_start, kernel_size, ".dynstr", &dynstr_size); - if (dynstr == NULL) { - boot_vga_log64("Couldn't find section .dynstr"); - return Error_Invalid; - } - - rela = boot_elf_get_section(kernel_start, kernel_size, ".rela.dyn", &rela_size); - if (rela == NULL) { - boot_vga_log64("Couldn't find section .rela.dyn"); - return Error_Invalid; - } - - dynsym = boot_elf_get_section(kernel_start, kernel_size, ".dynsym", - &dynsym_size); - if (dynsym == NULL) { - boot_vga_log64("Couldn't find section .dynsym"); - return Error_Invalid; - } - - rela = boot_elf_get_section(kernel_start, kernel_size, ".rela.dyn", &rela_size); - if (rela == NULL) { - boot_vga_log64("Couldn't find section .rela.dyn"); - return Error_Invalid; - } - - base = boot_elf_get_base_address(kernel_start, kernel_size); - if (base == NULL) { - boot_vga_log64("Bad base"); - return Error_Invalid; - } - - for (size_t i = 0; i < rela_size / sizeof(struct elf_rela); ++i) { - symbol = &dynsym[ELF64_R_SYM(rela[i].r_info)]; - if ((void *)(symbol + 1) > kernel_start + kernel_size) { - boot_vga_log64("Symbol out of bounds"); - return Error_Invalid; - } - - int r_type = ELF64_R_TYPE(rela[i].r_info); - switch (r_type) { - case R_X86_64_RELATIVE: - pointer = kernel_start + (uintptr_t)base + rela[i].r_offset; - value = (uintptr_t)kernel_start + (uintptr_t)base + rela[i].r_addend; - *pointer = value; - break; - case R_X86_64_JUMP_SLOT: - case R_X86_64_GLOB_DAT: - case R_X86_64_64: - pointer = kernel_start + (uintptr_t)base + rela[i].r_offset; - if (symbol->st_index == SHN_UNDEF) { - boot_vga_log64("Undefined symbol"); - return Error_Invalid; - } else if (r_type == R_X86_64_64) { - value = (uintptr_t)kernel_start + (uintptr_t)base + symbol->st_value + rela[i].r_addend; - } else { - value = (uintptr_t)kernel_start + (uintptr_t)base + symbol->st_value; - } - *pointer = value; - break; - default: - boot_log_number(rela[i].r_info); - return Error_Invalid; - } - const char *symbol_name = &dynstr[symbol->st_name]; - if ((void *)symbol_name > kernel_start + kernel_size) { - boot_vga_log64("String out of bounds"); - return Error_Invalid; - } - if (strncmp(symbol_name, Boot_Info_Name, sizeof(Boot_Info_Name)) == 0) { - Boot_Info_Pointer = (struct boot_info *)value; - } - } - - if (Boot_Info_Pointer == NULL) { - boot_vga_log64("Couldn't find Boot Info structure"); - return Error_Absent; - } - return Ok; -} - - -static enum status boot_elf_allocate_bss(void *kernel_start, phys_addr kernel_phys, size_t kernel_size, const void **bss_end) { - - size_t bss_size; - const void *bss = boot_elf_get_section(kernel_start, kernel_size, ".bss", &bss_size); - if (bss == NULL) { - boot_vga_log64("Couldn't find section .bss"); - return Error_Invalid; - } - size_t bss_offset = bss - kernel_start; - *bss_end = (const void *)round_next((uintptr_t)bss + bss_size, Page_Small); - - phys_addr page = round_next(kernel_phys + bss_offset + Page_Small, Page_Small); - const void *addr = (const void *)round_next((uintptr_t)bss + Page_Small, Page_Small); - for (; addr < *bss_end; addr += Page_Small, page += Page_Small) { - if (boot_map_page(addr, page, Memory_Just_Writable, true) != Ok) { - return Error_Invalid; - } - } - - memset((void *)bss, 0, bss_size); - - return Ok; -} - -static enum status boot_remap_section(void *kernel_start, phys_addr kernel_phys, size_t kernel_size, const void *virtual_base, phys_addr *section_phys, size_t *section_size, const char *section_name) { - enum status status; - const void *section = boot_elf_get_section(kernel_start, kernel_size, section_name, section_size); - if (section == NULL) { - boot_vga_log64("Section absent."); - return Error_Absent; - } - size_t section_offset = section - kernel_start; - *section_phys = kernel_phys + section_offset; - phys_addr section_phys_end = round_next(*section_phys + *section_size, Page_Small); - phys_addr page = *section_phys; - const void *addr = virtual_base; - for (; page < section_phys_end; page += Page_Small, addr += Page_Small) { - status = boot_map_page(addr, page, Memory_Just_Writable, false); - if (status != Ok) { - boot_vga_log64("Mapping already present."); - return status; - } - } - - return Ok; -} enum status boot_kernel_init(void *random, struct multiboot_info *multiboot_info) { @@ -386,9 +115,15 @@ enum status boot_kernel_init(void *random, struct multiboot_info *multiboot_info return status; } + Boot_Info_Pointer = boot_elf_get_dynamic_symbol(random, kernel_size, Boot_Info_Name, sizeof(Boot_Info_Name)); + if (Boot_Info_Pointer == NULL) { + boot_vga_log64("Boot Info pointer is NULL"); + return Error_Absent; + } + size_t symtab_size; phys_addr symtab_phys; - status = boot_remap_section(random, Boot_Kernel_Physical_Start, kernel_size, kernel_end, &symtab_phys, &symtab_size, ".symtab"); + status = boot_elf_remap_section(random, Boot_Kernel_Physical_Start, kernel_size, kernel_end, &symtab_phys, &symtab_size, ".symtab"); if (status != Ok) { boot_vga_log64("Couldn't remap symtab"); return status; @@ -397,18 +132,13 @@ enum status boot_kernel_init(void *random, struct multiboot_info *multiboot_info size_t strtab_size; phys_addr strtab_phys; - status = boot_remap_section(random, Boot_Kernel_Physical_Start, kernel_size, symtab_end, &strtab_phys, &strtab_size, ".strtab"); + status = boot_elf_remap_section(random, Boot_Kernel_Physical_Start, kernel_size, symtab_end, &strtab_phys, &strtab_size, ".strtab"); if (status != Ok) { boot_vga_log64("Couldn't remap strtab"); return status; } const void *strtab_end = (const void *)round_next((uintptr_t)symtab_end + strtab_size, Page_Small); - if (Boot_Info_Pointer == NULL) { - boot_vga_log64("Boot Info pointer is NULL"); - return Error_Absent; - } - Boot_Info_Pointer->kernel = random; Boot_Info_Pointer->kernel_size = kernel_size; Boot_Info_Pointer->kernel_physical = Boot_Kernel_Physical_Start; @@ -424,22 +154,6 @@ enum status boot_kernel_init(void *random, struct multiboot_info *multiboot_info } -enum status boot_elf_kernel_enter(void *kernel_start, size_t kernel_size) { - void (*entrypoint)(void); - struct elf64_header *header = kernel_start; - void *base = boot_elf_get_base_address(kernel_start, kernel_size); - - entrypoint = kernel_start + (uintptr_t)base + header->e_entry; - - entrypoint(); - - // NOT REACHED - boot_vga_log64("Kernel main should never return!"); - boot_halt(); - return Error_Invalid; -} - - void boot_loader_main(struct multiboot_info *multiboot_info_physical) { uint64_t random; size_t kernel_size = Boot_Kernel_Physical_End - Boot_Kernel_Physical_Start; @@ -460,6 +174,7 @@ void boot_loader_main(struct multiboot_info *multiboot_info_physical) { status = boot_elf_kernel_enter((void *)random, kernel_size); if (status != Ok) { - boot_vga_log64("Couldn't enter kernel"); + boot_vga_log64("Failed to enter kernel"); + return; } } diff --git a/loader/x64/elf.c b/loader/x64/elf.c new file mode 100644 index 0000000..5372739 --- /dev/null +++ b/loader/x64/elf.c @@ -0,0 +1,279 @@ +#include +#include +#include +#include +#include +#include +#include + +#define ELF_BAD_BASE_ADDRESS (~0ul) + +static void *boot_elf_get_base_address(void *kernel_start, size_t kernel_size) { + size_t base = ELF_BAD_BASE_ADDRESS; + const struct elf64_header *header = kernel_start; + + const struct elf_section_header *sections = kernel_start + header->e_shoff; + if ((void *)sections + header->e_shentsize * header->e_shnum > kernel_start + kernel_size) { + return NULL; + } + + for (size_t i = 0; i < header->e_shnum; ++i) { + if (sections[i].sh_type != SHT_NULL && sections[i].sh_offset < base) { + base = sections[i].sh_offset; + } + } + + if (base == ELF_BAD_BASE_ADDRESS) { + return NULL; + } + + return (void *)base; +} + + +const void *boot_elf_get_section(const struct elf64_header *header, const size_t size, const char *name, size_t *section_size) { + const void *section; + const uint8_t *start = (const uint8_t *)header; + + const struct elf_section_header *sections = (const void *)start + + header->e_shoff; + if ((uint8_t *)(sections + header->e_shnum) > start + size) { + boot_vga_log64("Section header out of bounds"); + return NULL; + } + + const char *strtab = (const char *)header + + sections[header->e_shstrndx].sh_offset; + if (strtab >= (const char *)header + size) { + boot_vga_log64("Strtab out of bounds"); + return NULL; + } + + for (size_t i = 0; i < header->e_shnum; ++i) { + const char *section_name = strtab + sections[i].sh_name; + if ((uint8_t *)section_name >= start + size) { + continue; + } + if (strncmp(name, section_name, strlen(name)) == 0) { + section = start + sections[i].sh_offset; + if ((void *)section > (void *)start + size) { + boot_vga_log64("Section out of bounds"); + boot_vga_log64(name); + return NULL; + } + *section_size = sections[i].sh_size; + return section; + } + } + + boot_vga_log64("Section not found"); + boot_vga_log64(name); + return NULL; +} + + +enum status boot_elf_get_relocation_data(void *kernel_start, uintptr_t base, const struct elf_symbol *symbol, const struct elf_rela *rela, int64_t **pointer, int64_t *value) { + int r_type = ELF64_R_TYPE(rela->r_info); + switch (r_type) { + case R_X86_64_RELATIVE: + *pointer = kernel_start + (uintptr_t)base + rela->r_offset; + *value = (uintptr_t)kernel_start + (uintptr_t)base + rela->r_addend; + break; + case R_X86_64_JUMP_SLOT: + case R_X86_64_GLOB_DAT: + case R_X86_64_64: + *pointer = kernel_start + (uintptr_t)base + rela->r_offset; + if (symbol->st_index == SHN_UNDEF) { + boot_vga_log64("Undefined symbol"); + return Error_Invalid; + } else if (r_type == R_X86_64_64) { + *value = (uintptr_t)kernel_start + (uintptr_t)base + symbol->st_value + rela->r_addend; + } else { + *value = (uintptr_t)kernel_start + (uintptr_t)base + symbol->st_value; + } + break; + default: + boot_log_number(rela->r_info); + return Error_Invalid; + } + return Ok; +} + + +void *boot_elf_get_dynamic_symbol(void *kernel_start, size_t kernel_size, const char *name, size_t name_size) { + int64_t *pointer; + int64_t value; + const struct elf_symbol *symbol; + size_t rela_size; + const struct elf_rela *rela; + size_t dynsym_size; + const struct elf_symbol *dynsym; + size_t dynstr_size; + void *base; + const char *dynstr = boot_elf_get_section(kernel_start, kernel_size, ".dynstr", &dynstr_size); + if (dynstr == NULL) { + boot_vga_log64("Couldn't find section .dynstr"); + return NULL; + } + + rela = boot_elf_get_section(kernel_start, kernel_size, ".rela.dyn", &rela_size); + if (rela == NULL) { + boot_vga_log64("Couldn't find section .rela.dyn"); + return NULL; + } + + dynsym = boot_elf_get_section(kernel_start, kernel_size, ".dynsym", + &dynsym_size); + if (dynsym == NULL) { + boot_vga_log64("Couldn't find section .dynsym"); + return NULL; + } + + base = boot_elf_get_base_address(kernel_start, kernel_size); + if (base == NULL) { + boot_vga_log64("Bad base"); + return NULL; + } + + for (size_t i = 0; i < rela_size / sizeof(struct elf_rela); ++i) { + symbol = &dynsym[ELF64_R_SYM(rela[i].r_info)]; + if ((void *)(symbol + 1) > kernel_start + kernel_size) { + boot_vga_log64("Symbol out of bounds"); + return NULL; + } + + enum status status = boot_elf_get_relocation_data(kernel_start, (uintptr_t)base, symbol, &rela[i], &pointer, &value); + if (status != Ok) { + boot_vga_log64("Couldn't read symbol type"); + return NULL; + } + const char *symbol_name = &dynstr[symbol->st_name]; + if ((void *)symbol_name > kernel_start + kernel_size) { + boot_vga_log64("String out of bounds"); + return NULL; + } + if (strncmp(symbol_name, name, name_size) == 0) { + return pointer; + } + } + + return NULL; +} + +enum status boot_elf_relocate(void *kernel_start, size_t kernel_size) { + int64_t *pointer; + int64_t value; + const struct elf_symbol *symbol; + size_t rela_size; + const struct elf_rela *rela; + size_t dynsym_size; + const struct elf_symbol *dynsym; + size_t dynstr_size; + void *base; + const char *dynstr = boot_elf_get_section(kernel_start, kernel_size, ".dynstr", &dynstr_size); + if (dynstr == NULL) { + boot_vga_log64("Couldn't find section .dynstr"); + return Error_Invalid; + } + + dynsym = boot_elf_get_section(kernel_start, kernel_size, ".dynsym", &dynsym_size); + if (dynsym == NULL) { + boot_vga_log64("Couldn't find section .dynsym"); + return Error_Invalid; + } + + rela = boot_elf_get_section(kernel_start, kernel_size, ".rela.dyn", &rela_size); + if (rela == NULL) { + boot_vga_log64("Couldn't find section .rela.dyn"); + return Error_Invalid; + } + + base = boot_elf_get_base_address(kernel_start, kernel_size); + if (base == NULL) { + boot_vga_log64("Bad base"); + return Error_Invalid; + } + + for (size_t i = 0; i < rela_size / sizeof(struct elf_rela); ++i) { + symbol = &dynsym[ELF64_R_SYM(rela[i].r_info)]; + if ((void *)(symbol + 1) > kernel_start + kernel_size) { + boot_vga_log64("Symbol out of bounds"); + return Error_Invalid; + } + + enum status status = boot_elf_get_relocation_data(kernel_start, (uintptr_t)base, symbol, &rela[i], &pointer, &value); + if (status != Ok) { + boot_vga_log64("Couldn't read symbol type"); + return status; + } + + *pointer = value; + } + + return Ok; +} + + +enum status boot_elf_allocate_bss(void *kernel_start, phys_addr kernel_phys, size_t kernel_size, const void **bss_end) { + + size_t bss_size; + const void *bss = boot_elf_get_section(kernel_start, kernel_size, ".bss", &bss_size); + if (bss == NULL) { + boot_vga_log64("Couldn't find section .bss"); + return Error_Invalid; + } + size_t bss_offset = bss - kernel_start; + *bss_end = (const void *)round_next((uintptr_t)bss + bss_size, Page_Small); + + phys_addr page = round_next(kernel_phys + bss_offset + Page_Small, Page_Small); + const void *addr = (const void *)round_next((uintptr_t)bss + Page_Small, Page_Small); + for (; addr < *bss_end; addr += Page_Small, page += Page_Small) { + if (boot_map_page(addr, page, Memory_Just_Writable, true) != Ok) { + return Error_Invalid; + } + } + + memset((void *)bss, 0, bss_size); + + return Ok; +} + + +enum status boot_elf_kernel_enter(void *kernel_start, size_t kernel_size) { + void (*entrypoint)(void); + struct elf64_header *header = kernel_start; + void *base = boot_elf_get_base_address(kernel_start, kernel_size); + + entrypoint = kernel_start + (uintptr_t)base + header->e_entry; + + entrypoint(); + + // NOT REACHED + boot_vga_log64("Kernel main should never return!"); + boot_halt(); + return Error_Invalid; +} + + +enum status boot_elf_remap_section(void *kernel_start, phys_addr kernel_phys, size_t kernel_size, const void *virtual_base, phys_addr *section_phys, size_t *section_size, const char *section_name) { + enum status status; + const void *section = boot_elf_get_section(kernel_start, kernel_size, section_name, section_size); + if (section == NULL) { + boot_vga_log64("Section absent."); + return Error_Absent; + } + size_t section_offset = section - kernel_start; + *section_phys = kernel_phys + section_offset; + phys_addr section_phys_end = round_next(*section_phys + *section_size, Page_Small); + phys_addr page = *section_phys; + const void *addr = virtual_base; + for (; page < section_phys_end; page += Page_Small, addr += Page_Small) { + status = boot_map_page(addr, page, Memory_Just_Writable, false); + if (status != Ok) { + boot_vga_log64("Mapping already present."); + return status; + } + } + + return Ok; +} From 64005aede04dcc7c0a7da78a64fb28a4e6502730 Mon Sep 17 00:00:00 2001 From: Ian Kronquist Date: Wed, 12 Jul 2017 17:34:06 -0400 Subject: [PATCH 45/51] Fix forgotten includes --- loader/x64/jitter.c | 1 + loader/x64/paging.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/loader/x64/jitter.c b/loader/x64/jitter.c index 2e37a14..ef14685 100644 --- a/loader/x64/jitter.c +++ b/loader/x64/jitter.c @@ -1,3 +1,4 @@ +#include #include #include diff --git a/loader/x64/paging.c b/loader/x64/paging.c index ebf6523..e5f0bb0 100644 --- a/loader/x64/paging.c +++ b/loader/x64/paging.c @@ -1,3 +1,5 @@ +#include +#include #include #include From 3423c5cf2ea3c3a54607171a84e61c1ef01a464c Mon Sep 17 00:00:00 2001 From: Ian Kronquist Date: Wed, 12 Jul 2017 17:34:18 -0400 Subject: [PATCH 46/51] Clang complains about inline asm --- loader/x64/jitter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/loader/x64/jitter.c b/loader/x64/jitter.c index ef14685..e0893de 100644 --- a/loader/x64/jitter.c +++ b/loader/x64/jitter.c @@ -10,7 +10,7 @@ static inline uint64_t boot_cpu_get_ticks(void) { uint32_t eax, edx; - __asm__ volatile ("rdtsc" : "=(eax)"(eax), "=(edx)"(edx)::); + __asm__ volatile ("rdtsc" : "=eax"(eax), "=edx"(edx)::); return (((uint64_t)edx) << 32) | eax; } From cdf881dd026d5cce3391af5c342b9aba40f08fb0 Mon Sep 17 00:00:00 2001 From: Ian Kronquist Date: Wed, 12 Jul 2017 17:43:59 -0400 Subject: [PATCH 47/51] Create clang tidy target --- Makefile | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index ffd63d7..d0852f2 100644 --- a/Makefile +++ b/Makefile @@ -33,6 +33,7 @@ include kernel/device/Makefile include modules/Makefile +CLANG_TIDY := clang-tidy OD := od LOADER_FLAGS := -O2 -MP -MMD \ @@ -72,7 +73,7 @@ QEMU_FLAGS := -no-reboot -m 256M -serial file:$(BUILD_DIR)/serial.txt \ MAKE := make -.PHONY: all clean debug iso release start start-log tools +.PHONY: all clean debug iso release start start-log tools tidy all: $(LOADER) $(MODULES) @@ -139,6 +140,9 @@ tags: kernel/arch/$(ARCH)/*.c kernel/core/*.c kernel/device/*.c include/arch/$(A iso: $(BUILD_DIR)/truth.iso +tidy: kernel/arch/$(ARCH)/*.c kernel/core/*.c kernel/device/*.c include/arch/$(ARCH)/*.h include/truth/*.h loader/$(ARCH)/*.c + $(CLANG_TIDY) $^ --checks="*,-clang-diagnostic-incompatible-library-redeclaration" -- -I ./include $(MACROS) -D __C__ -D Boot_Compile_Random_Number=0 + $(BUILD_DIR)/truth.iso: $(KERNEL) grub.cfg mkdir -p $(BUILD_DIR)/isodir/boot/grub cp $(KERNEL) $(BUILD_DIR)/isodir/boot/truth.elf From 45c75dfa1d307ebc6827768e5e78c71e189cc798 Mon Sep 17 00:00:00 2001 From: Ian Kronquist Date: Wed, 12 Jul 2017 17:44:26 -0400 Subject: [PATCH 48/51] Make clang-tidy not error --- include/arch/x64/segments.h | 2 ++ include/truth/mt19937_64.h | 2 ++ kernel/core/jitter.c | 6 ++++++ 3 files changed, 10 insertions(+) diff --git a/include/arch/x64/segments.h b/include/arch/x64/segments.h index 89b1332..9abd0fd 100644 --- a/include/arch/x64/segments.h +++ b/include/arch/x64/segments.h @@ -10,6 +10,8 @@ #ifdef __C__ +#include + void tss_set_stack(void *stack); struct tss_entry { diff --git a/include/truth/mt19937_64.h b/include/truth/mt19937_64.h index 38fd542..4873056 100644 --- a/include/truth/mt19937_64.h +++ b/include/truth/mt19937_64.h @@ -1,5 +1,7 @@ #pragma once +#include + void mt19937_64_seed(uint64_t seed); uint64_t mt19937_64_get_random_number(void); diff --git a/kernel/core/jitter.c b/kernel/core/jitter.c index 848371a..5aa5029 100644 --- a/kernel/core/jitter.c +++ b/kernel/core/jitter.c @@ -20,7 +20,13 @@ uint64_t memory_jitter_calculate(void) { uint64_t entropy = Jitter_SHA1_Starting_Values; for (size_t i = 0; i < Jitter_Buffer_Size; ++i) { uint64_t before = cpu_get_ticks(); + // Analyzer complains about a garbage value -- and it's right, but we + // really don't care about it here, we just want to read and write + // memory. +#ifndef __clang_analyzer__ + // NOLINT memory[i] += 1; +#endif uint64_t after = cpu_get_ticks(); uint64_t delta = after - before; entropy ^= delta & Jitter_Fold_Mask; From 03ac795cf60a3567847d934b69a6c3e94defecf5 Mon Sep 17 00:00:00 2001 From: Ian Kronquist Date: Wed, 12 Jul 2017 17:49:56 -0400 Subject: [PATCH 49/51] Use toolchain strip --- Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index d0852f2..f532ee7 100644 --- a/Makefile +++ b/Makefile @@ -61,9 +61,9 @@ MODULE_LD := $(TRIPLE)-ld MODULE_AS := $(AS) -OBJCOPY := objcopy +OBJCOPY := $(TRIPLE)-objcopy GRUB_MKRESCUE := grub-mkrescue -STRIP := strip +STRIP := $(TRIPLE)-strip TOOLS_CC := gcc @@ -98,7 +98,7 @@ release: LOADER_ASFLAGS += -Werror release: CFLAGS += -Werror release: AFLAGS += -Werror release: all - $(STRIP) $(KERNEL64) + $(STRIP) -s $(KERNEL64) $(KERNEL): $(KERNEL)64 $(MODULES) $(OBJCOPY) $< -O elf32-i386 $@ From a119ca2675c8435fb1e5728a54260036a39e1c87 Mon Sep 17 00:00:00 2001 From: Ian Kronquist Date: Wed, 12 Jul 2017 18:06:37 -0400 Subject: [PATCH 50/51] Fix NULL pointer dereference --- kernel/core/region_vector.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/kernel/core/region_vector.c b/kernel/core/region_vector.c index f332fa5..a47baa7 100644 --- a/kernel/core/region_vector.c +++ b/kernel/core/region_vector.c @@ -66,6 +66,7 @@ enum status checked region_alloc_random(struct region_vector *vect, size_t size, // Randomness has some element of luck. We could pick an address we can't fit in multiple times in a row, so try this multiple times. for (size_t addresses_tried = 0; addresses_tried < Region_Vector_Max_Random_Addresses; ++addresses_tried) { void *addr = random_address(true, Page_Small); + bool finish_vector_iteration = false; struct region_vector *v = vect; // For section in region vector. do { @@ -77,9 +78,7 @@ enum status checked region_alloc_random(struct region_vector *vect, size_t size, if (v->regions[i].address <= addr && v->regions[i].address + v->regions[i].size >= addr && v->regions[i].address) { // If there isn't enough room to fit this region, pick a new address. if (after_random_addr_size < size) { - // Break out of while loop. - v = NULL; - // Break out of for loop. + finish_vector_iteration = true; break; } size_t suffix_size = after_random_addr_size - size; @@ -102,7 +101,7 @@ enum status checked region_alloc_random(struct region_vector *vect, size_t size, } } v = v->next; - } while (v != NULL); + } while (!finish_vector_iteration && v != NULL); } // Either there isn't enough memory, it's too fragmented, or we're just plain unlucky. return Error_No_Memory; From 0c55688f0f1ef7311244ea0431bf80b4090040b8 Mon Sep 17 00:00:00 2001 From: Ian Kronquist Date: Wed, 12 Jul 2017 18:08:04 -0400 Subject: [PATCH 51/51] Forgot some loader includes --- include/loader/elf.h | 9 +++++++++ include/loader/halt.h | 3 +++ 2 files changed, 12 insertions(+) create mode 100644 include/loader/elf.h create mode 100644 include/loader/halt.h diff --git a/include/loader/elf.h b/include/loader/elf.h new file mode 100644 index 0000000..7e016a6 --- /dev/null +++ b/include/loader/elf.h @@ -0,0 +1,9 @@ +#include +#include + +const void *boot_elf_get_section(const struct elf64_header *header, const size_t size, const char *name, size_t *section_size); +enum status boot_elf_relocate(void *kernel_start, size_t kernel_size); +enum status boot_elf_allocate_bss(void *kernel_start, phys_addr kernel_phys, size_t kernel_size, const void **bss_end); +enum status boot_elf_remap_section(void *kernel_start, phys_addr kernel_phys, size_t kernel_size, const void *virtual_base, phys_addr *section_phys, size_t *section_size, const char *section_name); +enum status boot_elf_kernel_enter(void *kernel_start, size_t kernel_size); +void *boot_elf_get_dynamic_symbol(void *kernel_start, size_t kernel_size, const char *name, size_t name_size); diff --git a/include/loader/halt.h b/include/loader/halt.h new file mode 100644 index 0000000..2c911ec --- /dev/null +++ b/include/loader/halt.h @@ -0,0 +1,3 @@ +#pragma once + +void boot_halt(void);