├── .gitignore ├── CMakeLists.txt ├── LICENSE ├── README.md ├── arch └── x86_64 │ ├── boot.S │ ├── boot.h │ └── multiboot.h ├── iso ├── menu.lst └── stage2_eltorito ├── kernel.cpp ├── kernel.h └── link └── kernel.ld /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Compiled Dynamic libraries 12 | *.so 13 | *.dylib 14 | *.dll 15 | 16 | # Fortran module files 17 | *.mod 18 | *.smod 19 | 20 | # Compiled Static libraries 21 | *.lai 22 | *.la 23 | *.a 24 | *.lib 25 | 26 | # Executables 27 | *.exe 28 | *.out 29 | *.app 30 | build 31 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0) 2 | project(os64) 3 | 4 | enable_language(ASM) 5 | 6 | set(FLAGS_COMMON "-march=native -fno-PIC -pedantic -W -Wall -ffreestanding -mno-red-zone -nostdinc -mcmodel=kernel -mno-sse3 -mno-ssse3 -mno-sse4.1 -mno-sse4.2 -mno-sse4 -mno-sse4a -mno-3dnow -mno-avx -mno-avx2") 7 | 8 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${FLAGS_COMMON}") 9 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FLAGS_COMMON} -fno-exceptions -fno-rtti -fuse-cxa-atexit -fno-threadsafe-statics") 10 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -nostdlib -mcmodel=kernel -fno-PIC -no-pie -Wl,--build-id=none -Wl,-z,max-page-size=0x1000,-n,-T,${CMAKE_CURRENT_SOURCE_DIR}/link/kernel.ld") 11 | 12 | # in case we ever want to supprot building on 32-bit, we'll make it easy to select at compile time 13 | if(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "x86_64") 14 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m64") 15 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m64") 16 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -m64") 17 | set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -m64") 18 | elseif(${CMAKE_SYSTEM_PROCESSOR} MATCHES "i[3456]86") 19 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32") 20 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32") 21 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -m32") 22 | set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -m32") 23 | endif() 24 | 25 | set(SOURCE_FILES 26 | kernel.cpp 27 | ) 28 | 29 | if(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "x86_64") 30 | set(SOURCE_FILES ${SOURCE_FILES} 31 | arch/x86_64/boot.S 32 | ) 33 | 34 | include_directories( 35 | ${CMAKE_CURRENT_SOURCE_DIR}/arch/x86_64 36 | ) 37 | elseif(${CMAKE_SYSTEM_PROCESSOR} MATCHES "i[3456]86") 38 | set(SOURCE_FILES ${SOURCE_FILES} 39 | arch/i686/boot.S 40 | ) 41 | 42 | include_directories( 43 | ${CMAKE_CURRENT_SOURCE_DIR}/arch/i686 44 | ) 45 | endif() 46 | 47 | 48 | add_definitions(-D__KERNEL__) 49 | 50 | add_executable (kernel.elf ${SOURCE_FILES}) 51 | 52 | set_property(TARGET kernel.elf PROPERTY CXX_STANDARD 11) 53 | 54 | # custom linker command for the kernel 55 | add_custom_command(TARGET kernel.elf POST_BUILD 56 | COMMAND nm -C kernel.elf | sort | uniq > kernel.sym 57 | COMMAND objdump -C -d -S --no-show-raw-insn -mi386:x86-64:intel kernel.elf > kernel.lst 58 | COMMAND objdump -C -d -mi386:x86-64:intel kernel.elf > kernel.asm 59 | COMMAND strip kernel.elf 60 | ) 61 | 62 | add_custom_target(os64.iso 63 | COMMAND mkdir -p ${PROJECT_BINARY_DIR}/iso/boot/grub 64 | COMMAND mkdir -p ${PROJECT_BINARY_DIR}/iso/bin 65 | COMMAND cp ${PROJECT_SOURCE_DIR}/iso/stage2_eltorito ${PROJECT_BINARY_DIR}/iso/boot/grub/ 66 | COMMAND cp ${PROJECT_SOURCE_DIR}/iso/menu.lst ${PROJECT_BINARY_DIR}/iso/boot/grub/ 67 | COMMAND cp $ ${PROJECT_BINARY_DIR}/iso/boot/ 68 | 69 | # useful if we ever support mounting the ISO filesystem in the OS itself 70 | # COMMAND cp $ ${PROJECT_BINARY_DIR}/iso/bin/ 71 | COMMAND mkisofs -input-charset=utf-8 -R -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 -boot-info-table -V "os64" -iso-level 3 -o ${PROJECT_BINARY_DIR}/os64.iso ${PROJECT_BINARY_DIR}/iso/ 72 | DEPENDS kernel.elf 73 | BYPRODUCTS ${PROJECT_BINARY_DIR}/iso/ 74 | COMMENT "Generating bootable ISO" 75 | ) 76 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Evan Teran 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # os64 2 | A minimal example of an x86_64 higher half kernel loaded at the -2GB mark 3 | -------------------------------------------------------------------------------- /arch/x86_64/boot.S: -------------------------------------------------------------------------------- 1 | 2 | #define ASM 3 | #include "multiboot.h" 4 | #include "boot.h" 5 | 6 | .globl kmain 7 | 8 | .code32 9 | .section .multiboot 10 | .align 4 11 | multiboot_header: 12 | .long MULTIBOOT_HEADER_MAGIC /* magic */ 13 | .long MULTIBOOT_HEADER_FLAGS /* flags */ 14 | .long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) /* checksum */ 15 | .long (multiboot_header - KERNEL_VMA) /* header_addr */ 16 | .long (_start - KERNEL_VMA) /* load_addr */ 17 | .long (_edata - KERNEL_VMA) /* load_end_addr */ 18 | .long (_end - KERNEL_VMA) /* bss_end_addr */ 19 | .long (bootstrap - KERNEL_VMA) /* entry_addr */ 20 | 21 | 22 | .globl bootstrap, init_pml4, init_pdp, init_pd 23 | bootstrap: 24 | /* make sure interrupts are off */ 25 | cli 26 | 27 | /* load the GDT */ 28 | lgdt (init_gdt64_ptr - KERNEL_VMA) 29 | 30 | /* give ourselves a functional stack */ 31 | movl $(init_stack_end - KERNEL_VMA), %esp 32 | 33 | /* reset EFLAGS. */ 34 | pushl $0 35 | popf 36 | 37 | /* store the multiboot info */ 38 | pushl %eax 39 | pushl %ebx 40 | 41 | /* zero out bss section */ 42 | xorl %eax, %eax 43 | movl $(_bss - KERNEL_VMA), %edi 44 | movl $(_end - KERNEL_VMA), %ecx 45 | subl %edi, %ecx 46 | cld 47 | rep stosb 48 | 49 | /* get the multiboot info back */ 50 | popl %esi 51 | popl %edi 52 | 53 | /* ensure that paging is off */ 54 | movl %cr0, %eax 55 | andl $0x7fffffff, %eax 56 | movl %eax, %cr0 57 | 58 | /* enable CR4.PAE */ 59 | movl %cr4, %eax 60 | orl $0x20, %eax 61 | movl %eax, %cr4 62 | 63 | /* load a level4 PD */ 64 | movl $(init_pml4 - KERNEL_VMA), %eax 65 | mov %eax, %cr3 66 | 67 | /* set IA32_EFER.LME */ 68 | movl $0xc0000080, %ecx 69 | rdmsr 70 | /* set the PAE and SYSENTER bits */ 71 | orl $0x00000101, %eax 72 | wrmsr 73 | 74 | /* enable paging */ 75 | movl %cr0, %eax 76 | orl $0x80000000, %eax 77 | movl %eax, %cr0 78 | 79 | /* at this point we should be in IA-32e mode */ 80 | ljmp $0x08, $(boot64 - KERNEL_VMA) 81 | 82 | .data 83 | .align 16 84 | gdt64: 85 | .quad 0x0000000000000000 // 0x00 NULL 86 | .quad 0x0020980000000000 // 0x08 KCODE64 87 | gdt64_end: 88 | 89 | .align 16 90 | init_gdt64_ptr: 91 | .word gdt64_end - gdt64 - 1 92 | .long gdt64 - KERNEL_VMA 93 | 94 | /* ident map of first 4MB GB, and mirror it at the -2GB mark */ 95 | .align 0x1000 96 | init_pml4: 97 | .quad init_pdp - KERNEL_VMA + 3 // [0x0000000000000000 - 0x00000007ffffffff) 98 | .fill 510,8,0 99 | .quad init_pdp - KERNEL_VMA + 3 // [0xfffffff800000000 - 0xffffffffffffffff) 100 | 101 | init_pdp: 102 | .quad init_pd - KERNEL_VMA + 3 103 | .fill 509,8,0 104 | .quad init_pd - KERNEL_VMA + 3 105 | .fill 1,8,0 106 | 107 | init_pd: 108 | .quad 0x0000000000000083 // 0MB - 2MB 109 | .quad 0x0000000000200083 // 2MB - 4MB 110 | .fill 510,8,0 111 | 112 | 113 | init_stack_start: 114 | .fill 0x1000,1,0 115 | init_stack_end: 116 | 117 | 118 | .code64 119 | boot64_high: 120 | /* adjust the stack pointer to be in upper memory */ 121 | movq $KERNEL_VMA, %rax 122 | addq %rax, %rsp 123 | 124 | /* unmap the kernel from low memory */ 125 | movq $0x0,init_pml4 126 | invlpg 0 127 | 128 | /* go to our C entry point */ 129 | call EXT_C(kmain) 130 | 131 | boot64_hang: 132 | hlt 133 | jmp boot64_hang 134 | 135 | boot64: 136 | /* do an indirect to force non-relative jmp */ 137 | movabsq $boot64_high, %rax 138 | jmp *%rax 139 | 140 | 141 | -------------------------------------------------------------------------------- /arch/x86_64/boot.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef BOOT_H_ 3 | #define BOOT_H_ 4 | 5 | #define KERNEL_VMA 0xffffffff80000000 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /arch/x86_64/multiboot.h: -------------------------------------------------------------------------------- 1 | /* multiboot.h - the header for Multiboot */ 2 | /* Copyright (C) 1999, 2001 Free Software Foundation, Inc. 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ 17 | 18 | #ifndef MULTIBOOT_20100223_H_ 19 | #define MULTIBOOT_20100223_H_ 20 | 21 | /* The magic number for the Multiboot header. */ 22 | #define MULTIBOOT_HEADER_MAGIC 0x1BADB002 23 | 24 | /* The flags for the Multiboot header. */ 25 | #define MULTIBOOT_HEADER_FLAGS 0x00010003 26 | 27 | /* The magic number passed by a Multiboot-compliant boot loader. */ 28 | #define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002 29 | 30 | /* C symbol format. HAVE_ASM_USCORE is defined by configure. */ 31 | #ifdef HAVE_ASM_USCORE 32 | #define EXT_C(sym) _ ## sym 33 | #else 34 | #define EXT_C(sym) sym 35 | #endif 36 | 37 | #ifndef ASM 38 | typedef unsigned char __u8; 39 | typedef unsigned short __u16; 40 | typedef unsigned int __u32; 41 | typedef unsigned long long __u64; 42 | 43 | #pragma pack (push, 1) 44 | 45 | /* The Multiboot header. */ 46 | struct multiboot_header { 47 | __u32 magic; 48 | __u32 flags; 49 | __u32 checksum; 50 | __u32 header_addr; 51 | __u32 load_addr; 52 | __u32 load_end_addr; 53 | __u32 bss_end_addr; 54 | __u32 entry_addr; 55 | __u32 mode_type; 56 | __u32 width; 57 | __u32 height; 58 | __u32 depth; 59 | }; 60 | 61 | /* The symbol table for a.out. */ 62 | struct aout_symbol_table { 63 | __u32 tabsize; 64 | __u32 strsize; 65 | __u32 addr; 66 | __u32 reserved; 67 | }; 68 | 69 | /* The section header table for ELF. */ 70 | struct elf_section_header_table { 71 | __u32 num; 72 | __u32 size; 73 | __u32 addr; 74 | __u32 shndx; 75 | }; 76 | 77 | /* The Multiboot information. */ 78 | struct multiboot_info { 79 | __u32 flags; 80 | __u32 mem_lower; 81 | __u32 mem_upper; 82 | __u32 boot_device; 83 | __u32 cmdline; 84 | __u32 mods_count; 85 | __u32 mods_addr; 86 | union { 87 | aout_symbol_table aout_sym; 88 | elf_section_header_table elf_sec; 89 | } u; 90 | __u32 mmap_length; 91 | __u32 mmap_addr; 92 | 93 | __u32 drives_length; 94 | __u32 drives_addr; 95 | 96 | __u32 config_table; 97 | 98 | __u32 boot_loader_name; 99 | 100 | __u32 apm_table; 101 | 102 | __u32 vbe_control_info; 103 | __u32 vbe_mode_info; 104 | __u16 vbe_mode; 105 | __u16 vbe_interface_seg; 106 | __u16 vbe_interface_off; 107 | __u16 vbe_interface_len; 108 | }; 109 | 110 | /* The module structure. */ 111 | struct module { 112 | __u32 mod_start; 113 | __u32 mod_end; 114 | __u32 cmdline; 115 | __u32 reserved; 116 | }; 117 | 118 | /* The memory map. Be careful that the offset 0 is base_addr 119 | but no size. */ 120 | 121 | struct memory_map { 122 | __u32 size; 123 | __u64 base_addr; 124 | __u64 length; 125 | __u32 type; 126 | }; 127 | #pragma pack(pop) 128 | #endif /* ! ASM */ 129 | 130 | #endif 131 | -------------------------------------------------------------------------------- /iso/menu.lst: -------------------------------------------------------------------------------- 1 | default=0 2 | timeout=5 3 | 4 | title os64 5 | kernel /boot/kernel.elf 6 | -------------------------------------------------------------------------------- /iso/stage2_eltorito: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eteran/os64/32f1828f35aeb732e43307649d9fa949c88e9aa3/iso/stage2_eltorito -------------------------------------------------------------------------------- /kernel.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "kernel.h" 3 | #include "boot.h" 4 | #include "multiboot.h" 5 | 6 | namespace { 7 | 8 | const __u64 VideoBuffer = KERNEL_VMA + 0x000b8000; 9 | const __u16 VideoWidth = 80; 10 | const __u16 VideoHeight = 25; 11 | const __u16 VideoSize = VideoWidth * VideoHeight; 12 | 13 | const auto video = reinterpret_cast<__u16 *>(VideoBuffer); 14 | 15 | //+-----------+--------------+--------------+---------------+ 16 | //| Blink (1) | BG Color (3) | FG Color (4) | Character (8) | 17 | //+-----------+--------------+--------------+---------------+ 18 | enum TerminalAttributes : __u16 { 19 | BlinkCursor = 0x8000, 20 | 21 | BackgroundBlack = 0x0000, 22 | BackgroundBlue = 0x1000, 23 | BackgroundGreen = 0x2000, 24 | BackgroundCyan = 0x3000, 25 | BackgroundRed = 0x4000, 26 | BackgroundMagenta = 0x5000, 27 | BackgroundBrown = 0x6000, 28 | BackgroundGray = 0x7000, 29 | 30 | ForegroundBlack = 0x0000, 31 | ForegroundBlue = 0x0100, 32 | ForegroundGreen = 0x0200, 33 | ForegroundCyan = 0x0300, 34 | ForegroundRed = 0x0400, 35 | ForegroundMagenta = 0x0500, 36 | ForegroundBrown = 0x0600, 37 | ForegroundGray = 0x0700, 38 | 39 | ForegroundDarkGray = 0x0800, 40 | ForegroundBrightBlue = 0x0900, 41 | ForegroundBrightGreen = 0x0a00, 42 | ForegroundBrightCyan = 0x0b00, 43 | ForegroundBrightRed = 0x0c00, 44 | ForegroundBrightMagenta = 0x0d00, 45 | ForegroundYellow = 0x0e00, 46 | ForegroundWhite = 0x0f00, 47 | }; 48 | 49 | void clear_screen(__u16 attribute) { 50 | for (int i = 0; i < VideoSize; ++i) { 51 | video[i] = attribute; 52 | } 53 | } 54 | 55 | } 56 | 57 | //------------------------------------------------------------------------------ 58 | // Name: kmain 59 | //------------------------------------------------------------------------------ 60 | int kmain(unsigned long magic, unsigned long mbi) { 61 | 62 | (void)mbi; 63 | 64 | __u16 attribute = (BackgroundBlue | ForegroundWhite); 65 | 66 | if (magic != MULTIBOOT_BOOTLOADER_MAGIC) { 67 | attribute = (BackgroundRed | ForegroundWhite); 68 | } 69 | 70 | clear_screen(attribute); 71 | 72 | // manually put a basic message into the video buffer 73 | video[0] = 'H' | attribute; 74 | video[1] = 'e' | attribute; 75 | video[2] = 'l' | attribute; 76 | video[3] = 'l' | attribute; 77 | video[4] = 'o' | attribute; 78 | video[5] = ',' | attribute; 79 | video[6] = ' ' | attribute; 80 | video[7] = 'W' | attribute; 81 | video[8] = 'o' | attribute; 82 | video[9] = 'r' | attribute; 83 | video[10] = 'l' | attribute; 84 | video[11] = 'd' | attribute; 85 | 86 | while (1) { 87 | // loop forever... 88 | __asm__ __volatile__("hlt"); 89 | } 90 | 91 | return 0; 92 | } 93 | -------------------------------------------------------------------------------- /kernel.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef KERNEL_H_ 3 | #define KERNEL_H_ 4 | 5 | extern "C" int kmain(unsigned long magic, unsigned long mbi); 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /link/kernel.ld: -------------------------------------------------------------------------------- 1 | OUTPUT_FORMAT(elf64-x86-64) 2 | 3 | KERNEL_LMA = 0x0000000000200000; /* 2 MEG */ 4 | KERNEL_VMA = 0xffffffff80000000 + KERNEL_LMA; 5 | 6 | ENTRY(bootstrap) 7 | 8 | SECTIONS { 9 | . = KERNEL_VMA; 10 | 11 | _start = .; 12 | .text : AT(ADDR(.text) - KERNEL_VMA) { 13 | _code = .; 14 | *(.multiboot) 15 | *(.text*) 16 | *(.gnu.linkonce.t*) 17 | . = ALIGN(0x1000); 18 | } 19 | 20 | .rodata : AT(ADDR(.rodata) - KERNEL_VMA) { 21 | _rodata = .; 22 | *(.rodata*) 23 | *(.gnu.linkonce.r*) 24 | 25 | . = ALIGN(8); 26 | __CTOR_LIST__ = .; 27 | *(.ctors) 28 | __CTOR_END__ = .; 29 | 30 | . = ALIGN(8); 31 | __DTOR_LIST__ = .; 32 | *(.dtors) 33 | __DTOR_END__ = .; 34 | 35 | . = ALIGN(8); 36 | __INIT_LIST__ = .; 37 | KEEP (*(.init_array)) 38 | __INIT_END__ = .; 39 | 40 | . = ALIGN(8); 41 | __FINI_LIST__ = .; 42 | KEEP (*(.fini_array)) 43 | __FINI_END__ = .; 44 | 45 | . = ALIGN(0x1000); 46 | } 47 | 48 | .data : AT(ADDR(.data) - KERNEL_VMA) { 49 | _data = .; 50 | *(.data*) 51 | *(.gnu.linkonce.d*) 52 | . = ALIGN(0x1000); 53 | } 54 | 55 | .eh_frame : AT(ADDR(.eh_frame) - KERNEL_VMA) { 56 | _eh_frame = .; 57 | *(.eh_frame) 58 | *(.eh_frame_hdr) 59 | . = ALIGN(0x1000); 60 | } 61 | 62 | _edata = .; 63 | 64 | .bss : AT(ADDR(.bss) - KERNEL_VMA) { 65 | _bss = .; 66 | *(.bss*) 67 | *(.gnu.linkonce.b*) 68 | *(COMMON) 69 | . = ALIGN(0x1000); 70 | } 71 | 72 | _end = .; 73 | 74 | /DISCARD/ : { 75 | *(.comment) 76 | *(note.*) 77 | } 78 | } 79 | --------------------------------------------------------------------------------