├── .cargo ├── config.toml ├── kernel.ld └── x86_64-hyper_os.json ├── .editorconfig ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── build.sh ├── hyper_kernel ├── Cargo.toml ├── build.rs ├── limine.cfg └── src │ ├── arch │ ├── cpu.rs │ ├── gdt.rs │ ├── idt.rs │ ├── interrupts.asm │ ├── io.rs │ ├── mod.rs │ ├── pic.rs │ └── registers.rs │ ├── common │ ├── logger.rs │ ├── mod.rs │ └── writer.rs │ └── main.rs ├── run.sh └── rust-toolchain.toml /.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [unstable] 2 | build-std = ["core", "compiler_builtins", "alloc"] 3 | build-std-features = ["compiler-builtins-mem"] 4 | 5 | [build] 6 | target = "./.cargo/x86_64-hyper_os.json" 7 | rustflags = ["-Cforce-frame-pointers=yes"] 8 | -------------------------------------------------------------------------------- /.cargo/kernel.ld: -------------------------------------------------------------------------------- 1 | OUTPUT_FORMAT(elf64-x86-64) 2 | OUTPUT_ARCH(i386:x86-64) 3 | 4 | ENTRY(kernel_main) 5 | 6 | PHDRS 7 | { 8 | null PT_NULL FLAGS(0) ; 9 | text PT_LOAD FLAGS((1 << 0) | (1 << 2)) ; 10 | rodata PT_LOAD FLAGS((1 << 2)) ; 11 | data PT_LOAD FLAGS((1 << 1) | (1 << 2)) ; 12 | } 13 | 14 | SECTIONS 15 | { 16 | . = 0xffffffff80000000; 17 | 18 | .text : { 19 | *(.text .text.*) 20 | } :text 21 | 22 | . += CONSTANT(MAXPAGESIZE); 23 | 24 | .rodata : { 25 | *(.rodata .rodata.*) 26 | } :rodata 27 | 28 | . += CONSTANT(MAXPAGESIZE); 29 | 30 | .data : { 31 | *(.data .data.*) 32 | } :data 33 | 34 | .bss : { 35 | *(COMMON) 36 | *(.bss .bss.*) 37 | } :data 38 | } 39 | -------------------------------------------------------------------------------- /.cargo/x86_64-hyper_os.json: -------------------------------------------------------------------------------- 1 | { 2 | "llvm-target": "x86_64-unknown-none", 3 | "data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128", 4 | "arch": "x86_64", 5 | "target-endian": "little", 6 | "target-pointer-width": "64", 7 | "target-c-int-width": "32", 8 | "os": "none", 9 | "executables": true, 10 | "linker-flavor": "ld.lld", 11 | "linker": "rust-lld", 12 | "disable-redzone": true, 13 | "panic-strategy": "abort", 14 | "features": "-mmx,-sse,+soft-float", 15 | "code-model": "kernel", 16 | "pre-link-args": { 17 | "ld.lld": [ 18 | "--gc-sections", 19 | "--script=.cargo/kernel.ld" 20 | ] 21 | } 22 | } -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------------------- 2 | # Copyright (c) 2022, SkillerRaptor 3 | # 4 | # SPDX-License-Identifier: MIT 5 | #------------------------------------------------------------------------------------------- 6 | 7 | #------------------------------------------------------------------------------------------- 8 | # Editor Config 9 | #------------------------------------------------------------------------------------------- 10 | root = true 11 | 12 | [*] 13 | end_of_line = lf 14 | charset = utf-8 15 | insert_final_newline = true 16 | trim_trailing_whitespace = true 17 | 18 | # Rust files 19 | [*.rs] 20 | indent_style = space 21 | indent_size = 4 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------------------- 2 | # Copyright (c) 2022, SkillerRaptor 3 | # 4 | # SPDX-License-Identifier: MIT 5 | #------------------------------------------------------------------------------------------- 6 | 7 | #------------------------------------------------------------------------------------------- 8 | # Editor Files 9 | #------------------------------------------------------------------------------------------- 10 | /.cache/ 11 | /.idea/ 12 | /.vs/ 13 | /.vscode/ 14 | 15 | #------------------------------------------------------------------------------------------- 16 | # Rust 17 | #------------------------------------------------------------------------------------------- 18 | debug/ 19 | target/ 20 | **/*.pdb 21 | **/*.rs.bk 22 | 23 | #------------------------------------------------------------------------------------------- 24 | # OS 25 | #------------------------------------------------------------------------------------------- 26 | /boot/ 27 | *.log 28 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "autocfg" 7 | version = "1.1.0" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 10 | 11 | [[package]] 12 | name = "bitflags" 13 | version = "1.3.2" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 16 | 17 | [[package]] 18 | name = "cfg-if" 19 | version = "1.0.0" 20 | source = "registry+https://github.com/rust-lang/crates.io-index" 21 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 22 | 23 | [[package]] 24 | name = "crossbeam-channel" 25 | version = "0.5.6" 26 | source = "registry+https://github.com/rust-lang/crates.io-index" 27 | checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" 28 | dependencies = [ 29 | "cfg-if", 30 | "crossbeam-utils", 31 | ] 32 | 33 | [[package]] 34 | name = "crossbeam-deque" 35 | version = "0.8.2" 36 | source = "registry+https://github.com/rust-lang/crates.io-index" 37 | checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" 38 | dependencies = [ 39 | "cfg-if", 40 | "crossbeam-epoch", 41 | "crossbeam-utils", 42 | ] 43 | 44 | [[package]] 45 | name = "crossbeam-epoch" 46 | version = "0.9.11" 47 | source = "registry+https://github.com/rust-lang/crates.io-index" 48 | checksum = "f916dfc5d356b0ed9dae65f1db9fc9770aa2851d2662b988ccf4fe3516e86348" 49 | dependencies = [ 50 | "autocfg", 51 | "cfg-if", 52 | "crossbeam-utils", 53 | "memoffset", 54 | "scopeguard", 55 | ] 56 | 57 | [[package]] 58 | name = "crossbeam-utils" 59 | version = "0.8.12" 60 | source = "registry+https://github.com/rust-lang/crates.io-index" 61 | checksum = "edbafec5fa1f196ca66527c1b12c2ec4745ca14b50f1ad8f9f6f720b55d11fac" 62 | dependencies = [ 63 | "cfg-if", 64 | ] 65 | 66 | [[package]] 67 | name = "either" 68 | version = "1.8.0" 69 | source = "registry+https://github.com/rust-lang/crates.io-index" 70 | checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" 71 | 72 | [[package]] 73 | name = "hermit-abi" 74 | version = "0.1.19" 75 | source = "registry+https://github.com/rust-lang/crates.io-index" 76 | checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" 77 | dependencies = [ 78 | "libc", 79 | ] 80 | 81 | [[package]] 82 | name = "hyper_kernel" 83 | version = "0.1.0" 84 | dependencies = [ 85 | "bitflags", 86 | "limine", 87 | "log", 88 | "nasm-rs", 89 | ] 90 | 91 | [[package]] 92 | name = "libc" 93 | version = "0.2.137" 94 | source = "registry+https://github.com/rust-lang/crates.io-index" 95 | checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89" 96 | 97 | [[package]] 98 | name = "limine" 99 | version = "0.1.9" 100 | source = "registry+https://github.com/rust-lang/crates.io-index" 101 | checksum = "c847ac148a0c53ba3755dfa9830722b1043179584009869e6afc2b413e13f105" 102 | 103 | [[package]] 104 | name = "log" 105 | version = "0.4.17" 106 | source = "registry+https://github.com/rust-lang/crates.io-index" 107 | checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" 108 | dependencies = [ 109 | "cfg-if", 110 | ] 111 | 112 | [[package]] 113 | name = "memoffset" 114 | version = "0.6.5" 115 | source = "registry+https://github.com/rust-lang/crates.io-index" 116 | checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" 117 | dependencies = [ 118 | "autocfg", 119 | ] 120 | 121 | [[package]] 122 | name = "nasm-rs" 123 | version = "0.2.4" 124 | source = "registry+https://github.com/rust-lang/crates.io-index" 125 | checksum = "ce095842aee9aa3ecbda7a5d2a4df680375fd128a8596b6b56f8e497e231f483" 126 | dependencies = [ 127 | "rayon", 128 | ] 129 | 130 | [[package]] 131 | name = "num_cpus" 132 | version = "1.13.1" 133 | source = "registry+https://github.com/rust-lang/crates.io-index" 134 | checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" 135 | dependencies = [ 136 | "hermit-abi", 137 | "libc", 138 | ] 139 | 140 | [[package]] 141 | name = "rayon" 142 | version = "1.5.3" 143 | source = "registry+https://github.com/rust-lang/crates.io-index" 144 | checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d" 145 | dependencies = [ 146 | "autocfg", 147 | "crossbeam-deque", 148 | "either", 149 | "rayon-core", 150 | ] 151 | 152 | [[package]] 153 | name = "rayon-core" 154 | version = "1.9.3" 155 | source = "registry+https://github.com/rust-lang/crates.io-index" 156 | checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f" 157 | dependencies = [ 158 | "crossbeam-channel", 159 | "crossbeam-deque", 160 | "crossbeam-utils", 161 | "num_cpus", 162 | ] 163 | 164 | [[package]] 165 | name = "scopeguard" 166 | version = "1.1.0" 167 | source = "registry+https://github.com/rust-lang/crates.io-index" 168 | checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" 169 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ 3 | "hyper_kernel", 4 | ] 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022, SkillerRaptor 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 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | set -e 2 | 3 | cargo build 4 | 5 | if [ ! -d "boot/limine/" ] ; then 6 | git clone https://github.com/limine-bootloader/limine.git --branch=v4.x-branch-binary --depth=1 boot/limine/ 7 | make -C boot/limine/ 8 | fi 9 | 10 | mkdir -p boot/ 11 | rm -rf boot/iso_root/ 12 | mkdir -p boot/iso_root/ 13 | 14 | cp target/x86_64-hyper_os/debug/hyper_kernel hyper_kernel/limine.cfg boot/limine/limine.sys boot/limine/limine-cd.bin boot/limine/limine-cd-efi.bin boot/iso_root/ 15 | xorriso -as mkisofs -b limine-cd.bin \ 16 | -no-emul-boot -boot-load-size 4 -boot-info-table \ 17 | --efi-boot limine-cd-efi.bin \ 18 | -efi-boot-part --efi-boot-image --protective-msdos-label \ 19 | boot/iso_root/ -o boot/hyper_os.iso 20 | boot/limine/limine-deploy boot/hyper_os.iso 21 | 22 | rm -rf boot/iso_root/ 23 | 24 | -------------------------------------------------------------------------------- /hyper_kernel/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "hyper_kernel" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | bitflags = "1.3.2" 8 | limine = "0.1.9" 9 | log = "0.4.17" 10 | 11 | [build-dependencies] 12 | nasm-rs = { version = "0.2.4", features = ["parallel"] } 13 | -------------------------------------------------------------------------------- /hyper_kernel/build.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, SkillerRaptor 3 | * 4 | * SPDX-License-Identifier: MIT 5 | */ 6 | 7 | use std::{ 8 | error::Error, 9 | ffi::OsString, 10 | fs::{self, DirEntry}, 11 | path::Path, 12 | }; 13 | 14 | fn visit_directory(directory: &Path, callback: &mut dyn FnMut(&DirEntry)) -> std::io::Result<()> { 15 | if !directory.is_dir() { 16 | return Ok(()); 17 | } 18 | 19 | for entry in fs::read_dir(directory)? { 20 | let entry = entry?; 21 | let path = entry.path(); 22 | 23 | if path.is_dir() { 24 | visit_directory(&path, callback)?; 25 | continue; 26 | } 27 | 28 | callback(&entry); 29 | } 30 | 31 | Ok(()) 32 | } 33 | 34 | fn main() -> Result<(), Box> { 35 | let mut inc_files = vec![]; 36 | 37 | visit_directory(Path::new("src"), &mut |entry| { 38 | let path = entry.path(); 39 | 40 | match path.extension() { 41 | Some(extension) if extension.eq(&OsString::from("inc")) => { 42 | let path = path.to_str().expect("Invalid UTF-8 for file path"); 43 | inc_files.push(path.to_string()) 44 | } 45 | _ => (), 46 | } 47 | })?; 48 | 49 | inc_files = inc_files 50 | .iter() 51 | .map(|e| { 52 | let e = e.split("/").collect::>(); 53 | e[..e.len() - 1].join("/").to_string() 54 | }) 55 | .collect::>(); 56 | 57 | visit_directory(Path::new("src"), &mut |entry: &DirEntry| { 58 | let path = entry.path(); 59 | 60 | let object_os = path.file_name().expect("Failed to get file name"); 61 | let object_file = object_os.to_str().expect("Invalid UTF-8 for file name"); 62 | 63 | match path.extension() { 64 | Some(extension) if extension.eq(&OsString::from("asm")) => { 65 | let mut build = nasm_rs::Build::new(); 66 | 67 | build 68 | .file(&path) 69 | .flag("-felf64") 70 | .target("x86_64-unknown-none"); 71 | 72 | println!("{:?}", inc_files); 73 | 74 | for include in &inc_files { 75 | build.include(include); 76 | } 77 | 78 | build 79 | .compile(object_file) 80 | .expect("Failed to compile assembly"); 81 | 82 | println!("cargo:rustc-link-lib=static={}", object_file); 83 | } 84 | 85 | _ => (), 86 | } 87 | })?; 88 | 89 | println!("cargo:rerun-if-changed=.cargo/kernel.ld"); 90 | 91 | Ok(()) 92 | } 93 | -------------------------------------------------------------------------------- /hyper_kernel/limine.cfg: -------------------------------------------------------------------------------- 1 | TIMEOUT=3 2 | GRAPHICS=yes 3 | 4 | :HyperOS 5 | PROTOCOL=limine 6 | RESOLUTION=1600x900x32 7 | KASLR=no 8 | KERNEL_PARTITION=0 9 | KERNEL_PATH=boot:///hyper_kernel 10 | KERNEL_PROTO=limine 11 | -------------------------------------------------------------------------------- /hyper_kernel/src/arch/cpu.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, SkillerRaptor 3 | * 4 | * SPDX-License-Identifier: MIT 5 | */ 6 | 7 | use core::arch::asm; 8 | 9 | pub fn enable_interrupts() { 10 | unsafe { 11 | asm!("sti", options(nomem, nostack)); 12 | } 13 | } 14 | 15 | pub fn disable_interrupts() { 16 | unsafe { 17 | asm!("cli", options(nomem, nostack)); 18 | } 19 | } 20 | 21 | pub fn halt() { 22 | unsafe { 23 | asm!("hlt", options(nomem, nostack)); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /hyper_kernel/src/arch/gdt.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, SkillerRaptor 3 | * 4 | * SPDX-License-Identifier: MIT 5 | */ 6 | 7 | use bitflags::bitflags; 8 | use core::{arch::asm, mem}; 9 | use log::info; 10 | 11 | pub const KERNEL_CODE_SELECTOR: u64 = 0x28; 12 | pub const KERNEL_DATA_SELECTOR: u64 = 0x30; 13 | 14 | bitflags! { 15 | struct AccessAttribute: u8 { 16 | const NULL = 0; 17 | const ACCESS = 1 << 0; 18 | const READ_WRITE = 1 << 1; 19 | const EXECUTABLE = 1 << 3; 20 | const CODE_DATA = 1 << 4; 21 | const PRESENT = 1 << 7; 22 | } 23 | 24 | struct FlagAttribute: u8 { 25 | const NULL = 0; 26 | const GRANULARITY_1B = 0 << 3; 27 | const GRANULARITY_4K = 1 << 3; 28 | const SIZE_16 = 0 << 2; 29 | const SIZE_32 = 1 << 2; 30 | const SIZE_64 = 1 << 1; 31 | } 32 | } 33 | 34 | #[repr(C, packed)] 35 | #[derive(Debug, Clone, Copy)] 36 | struct Entry { 37 | limit_low: u16, 38 | base_low: u16, 39 | base_middle: u8, 40 | access: u8, 41 | limit_high_flags: u8, 42 | base_high: u8, 43 | } 44 | 45 | impl Entry { 46 | fn new(base: u32, limit: u32, access: AccessAttribute, flags: FlagAttribute) -> Self { 47 | Self { 48 | limit_low: limit as u16, 49 | base_low: base as u16, 50 | base_middle: (base >> 16) as u8, 51 | access: access.bits(), 52 | limit_high_flags: (flags.bits() << 4) & 0xf0 | ((limit >> 16) as u8) & 0x0f, 53 | base_high: (base >> 24) as u8, 54 | } 55 | } 56 | 57 | const fn default() -> Self { 58 | Self { 59 | limit_low: 0, 60 | base_low: 0, 61 | base_middle: 0, 62 | access: 0, 63 | limit_high_flags: 0, 64 | base_high: 0, 65 | } 66 | } 67 | } 68 | 69 | #[repr(C, packed)] 70 | #[derive(Debug, Clone, Copy)] 71 | struct Table { 72 | null_entry: Entry, 73 | kernel_entries_16: [Entry; 2], 74 | kernel_entries_32: [Entry; 2], 75 | kernel_entries_64: [Entry; 2], 76 | } 77 | 78 | impl Table { 79 | fn new( 80 | null_entry: Entry, 81 | kernel_entries_16: [Entry; 2], 82 | kernel_entries_32: [Entry; 2], 83 | kernel_entries_64: [Entry; 2], 84 | ) -> Self { 85 | Self { 86 | null_entry, 87 | kernel_entries_16, 88 | kernel_entries_32, 89 | kernel_entries_64, 90 | } 91 | } 92 | 93 | const fn default() -> Self { 94 | Self { 95 | null_entry: Entry::default(), 96 | kernel_entries_16: [Entry::default(); 2], 97 | kernel_entries_32: [Entry::default(); 2], 98 | kernel_entries_64: [Entry::default(); 2], 99 | } 100 | } 101 | } 102 | 103 | #[repr(C, packed)] 104 | #[derive(Debug, Clone, Copy)] 105 | struct Descriptor { 106 | size: u16, 107 | address: u64, 108 | } 109 | 110 | impl Descriptor { 111 | fn new(size: u16, address: u64) -> Self { 112 | Self { size, address } 113 | } 114 | 115 | const fn default() -> Self { 116 | Self { 117 | size: 0, 118 | address: 0, 119 | } 120 | } 121 | } 122 | 123 | static mut TABLE: Table = Table::default(); 124 | static mut DESCRIPTOR: Descriptor = Descriptor::default(); 125 | 126 | pub fn init() { 127 | let null_entry = Entry::new( 128 | 0x00000000, 129 | 0x00000000, 130 | AccessAttribute::NULL, 131 | FlagAttribute::NULL, 132 | ); 133 | 134 | let kernel_entries_16 = [ 135 | Entry::new( 136 | 0x00000000, 137 | 0x0000ffff, 138 | AccessAttribute::PRESENT 139 | | AccessAttribute::CODE_DATA 140 | | AccessAttribute::EXECUTABLE 141 | | AccessAttribute::READ_WRITE, 142 | FlagAttribute::NULL, 143 | ), 144 | Entry::new( 145 | 0x00000000, 146 | 0x0000ffff, 147 | AccessAttribute::PRESENT 148 | | AccessAttribute::CODE_DATA 149 | | AccessAttribute::READ_WRITE 150 | | AccessAttribute::ACCESS, 151 | FlagAttribute::NULL, 152 | ), 153 | ]; 154 | 155 | let kernel_entries_32 = [ 156 | Entry::new( 157 | 0x00000000, 158 | 0xffffffff, 159 | AccessAttribute::PRESENT 160 | | AccessAttribute::CODE_DATA 161 | | AccessAttribute::EXECUTABLE 162 | | AccessAttribute::READ_WRITE, 163 | FlagAttribute::GRANULARITY_4K | FlagAttribute::SIZE_32, 164 | ), 165 | Entry::new( 166 | 0x00000000, 167 | 0xffffffff, 168 | AccessAttribute::PRESENT 169 | | AccessAttribute::CODE_DATA 170 | | AccessAttribute::READ_WRITE 171 | | AccessAttribute::ACCESS, 172 | FlagAttribute::GRANULARITY_4K | FlagAttribute::SIZE_32, 173 | ), 174 | ]; 175 | 176 | let kernel_entries_64 = [ 177 | Entry::new( 178 | 0x00000000, 179 | 0xffffffff, 180 | AccessAttribute::PRESENT 181 | | AccessAttribute::CODE_DATA 182 | | AccessAttribute::EXECUTABLE 183 | | AccessAttribute::READ_WRITE 184 | | AccessAttribute::ACCESS, 185 | FlagAttribute::GRANULARITY_4K | FlagAttribute::SIZE_64, 186 | ), 187 | Entry::new( 188 | 0x00000000, 189 | 0xffffffff, 190 | AccessAttribute::PRESENT 191 | | AccessAttribute::CODE_DATA 192 | | AccessAttribute::READ_WRITE 193 | | AccessAttribute::ACCESS, 194 | FlagAttribute::GRANULARITY_4K | FlagAttribute::SIZE_64, 195 | ), 196 | ]; 197 | 198 | unsafe { 199 | TABLE = Table::new( 200 | null_entry, 201 | kernel_entries_16, 202 | kernel_entries_32, 203 | kernel_entries_64, 204 | ); 205 | 206 | DESCRIPTOR = Descriptor::new( 207 | (mem::size_of::() - 1) as u16, 208 | (&TABLE as *const _) as u64, 209 | ); 210 | } 211 | 212 | load(); 213 | 214 | info!("GDT: Initialized"); 215 | } 216 | 217 | fn load() { 218 | unsafe { 219 | asm!( 220 | "lgdt [{descriptor}]", 221 | "push {tmp}", 222 | "mov {tmp}, rsp", 223 | "push {data_offset}", 224 | "push {tmp}", 225 | "pushf", 226 | "push {code_offset}", 227 | "lea {tmp}, [rip + 1f]", 228 | "push {tmp}", 229 | "iretq", 230 | "1:", 231 | "pop {tmp}", 232 | "mov ds, {data_offset:x}", 233 | "mov es, {data_offset:x}", 234 | "mov fs, {data_offset:x}", 235 | "mov gs, {data_offset:x}", 236 | "mov ss, {data_offset:x}", 237 | descriptor = in(reg) &DESCRIPTOR, 238 | code_offset = in(reg) KERNEL_CODE_SELECTOR, 239 | data_offset = in(reg) KERNEL_DATA_SELECTOR, 240 | tmp = lateout(reg) _, 241 | ); 242 | } 243 | } 244 | -------------------------------------------------------------------------------- /hyper_kernel/src/arch/idt.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, SkillerRaptor 3 | * 4 | * SPDX-License-Identifier: MIT 5 | */ 6 | 7 | use crate::{ 8 | arch::gdt, 9 | arch::{cpu, pic, registers::Registers}, 10 | }; 11 | 12 | use bitflags::bitflags; 13 | use core::{arch::asm, mem}; 14 | use log::{error, info}; 15 | 16 | bitflags! { 17 | struct Attributes: u8 { 18 | const INTERRUPT_GATE = 1<<1 | 1<< 2 | 1 << 3; 19 | const PRESENT = 1 << 7; 20 | } 21 | } 22 | 23 | #[repr(C, packed)] 24 | #[derive(Debug, Clone, Copy)] 25 | struct Entry { 26 | offset_low: u16, 27 | selector: u16, 28 | ist: u8, 29 | attribute: u8, 30 | offset_middle: u16, 31 | offset_high: u32, 32 | zero: u32, 33 | } 34 | 35 | impl Entry { 36 | fn new(index: usize, handler: *const u8, attribute: Attributes) -> Self { 37 | let handler_address = handler as usize; 38 | Self { 39 | offset_low: handler_address as u16, 40 | selector: gdt::KERNEL_CODE_SELECTOR as u16, 41 | ist: 0, 42 | attribute: attribute.bits(), 43 | offset_middle: (handler_address >> 16) as u16, 44 | offset_high: (handler_address >> 32) as u32, 45 | zero: 0, 46 | } 47 | } 48 | 49 | const fn default() -> Self { 50 | Self { 51 | offset_low: 0, 52 | selector: 0, 53 | ist: 0, 54 | attribute: 0, 55 | offset_middle: 0, 56 | offset_high: 0, 57 | zero: 0, 58 | } 59 | } 60 | } 61 | 62 | #[repr(C, packed)] 63 | #[derive(Debug, Clone, Copy)] 64 | struct Descriptor { 65 | size: u16, 66 | address: u64, 67 | } 68 | 69 | impl Descriptor { 70 | fn new(size: u16, address: u64) -> Self { 71 | Self { size, address } 72 | } 73 | 74 | const fn default() -> Self { 75 | Self { 76 | size: 0, 77 | address: 0, 78 | } 79 | } 80 | } 81 | 82 | static mut TABLE: [Entry; 256] = [Entry::default(); 256]; 83 | static mut DESCRIPTOR: Descriptor = Descriptor::default(); 84 | static mut HANDLERS: [Option; 256] = [None; 256]; 85 | 86 | pub fn init() { 87 | extern "C" { 88 | static interrupt_handlers: [*const u8; 256]; 89 | } 90 | 91 | unsafe { 92 | // Exception Handlers 93 | HANDLERS[0] = Some(divide_by_zero); 94 | HANDLERS[1] = Some(debug); 95 | HANDLERS[2] = Some(non_maskable_interrupt); 96 | HANDLERS[3] = Some(breakpoint); 97 | HANDLERS[4] = Some(overflow); 98 | HANDLERS[5] = Some(bound_range_exceeded); 99 | HANDLERS[6] = Some(invalid_opcode); 100 | HANDLERS[7] = Some(device_not_available); 101 | HANDLERS[8] = Some(double_fault); 102 | 103 | HANDLERS[10] = Some(invalid_tss); 104 | HANDLERS[11] = Some(segment_not_present); 105 | HANDLERS[12] = Some(stack_segment_fault); 106 | HANDLERS[13] = Some(general_protection_fault); 107 | HANDLERS[14] = Some(page_fault); 108 | 109 | HANDLERS[16] = Some(x87_floating_point_exception); 110 | HANDLERS[17] = Some(alignment_check); 111 | HANDLERS[18] = Some(machine_check); 112 | HANDLERS[19] = Some(simd_floating_point_exception); 113 | HANDLERS[20] = Some(virtualization_exception); 114 | 115 | HANDLERS[30] = Some(security_exception); 116 | 117 | // Interrupt Handlers (starting at 0x20) 118 | 119 | for (i, entry) in &mut TABLE.iter_mut().enumerate() { 120 | *entry = Entry::new( 121 | i, 122 | interrupt_handlers[i], 123 | Attributes::PRESENT | Attributes::INTERRUPT_GATE, 124 | ); 125 | } 126 | 127 | DESCRIPTOR = Descriptor::new( 128 | (mem::size_of::<[Entry; 256]>() - 1) as u16, 129 | (&TABLE as *const _) as u64, 130 | ); 131 | } 132 | 133 | load(); 134 | 135 | info!("IDT: Initialized"); 136 | } 137 | 138 | fn load() { 139 | unsafe { 140 | asm!( 141 | "lidt [{descriptor}]", 142 | descriptor = in(reg) &DESCRIPTOR, 143 | ); 144 | } 145 | 146 | cpu::enable_interrupts(); 147 | } 148 | 149 | #[no_mangle] 150 | extern "C" fn idt_raise(isr: usize, registers: *mut Registers) { 151 | let mut registers = unsafe { &mut *registers }; 152 | if let Some(handler) = unsafe { HANDLERS[isr] } { 153 | handler(&mut registers); 154 | } 155 | 156 | pic::end_of_interrupt(isr as u8); 157 | } 158 | 159 | #[macro_export] 160 | macro_rules! exception_handler { 161 | ($name:ident => $message:expr) => { 162 | fn $name(_: &mut Registers) { 163 | error!("Exception: {}", $message); 164 | 165 | loop { 166 | cpu::halt(); 167 | } 168 | } 169 | }; 170 | } 171 | 172 | exception_handler!(divide_by_zero => "Divide-by-zero Error"); 173 | exception_handler!(debug => "Debug"); 174 | exception_handler!(non_maskable_interrupt => "Non-maskable Interrupt"); 175 | exception_handler!(breakpoint => "Breakpoint"); 176 | exception_handler!(overflow => "Overflow"); 177 | exception_handler!(bound_range_exceeded => "Bound Range Exceeded"); 178 | exception_handler!(invalid_opcode => "Invalid Opcode"); 179 | exception_handler!(device_not_available => "Device Not Available"); 180 | exception_handler!(double_fault => "Double Fault"); 181 | 182 | exception_handler!(invalid_tss => "Invalid TSS"); 183 | exception_handler!(segment_not_present => "Segment Not Present"); 184 | exception_handler!(stack_segment_fault => "Stack-Segment-Fault"); 185 | exception_handler!(general_protection_fault => "General-Protection-Fault"); 186 | exception_handler!(page_fault => "Page Fault"); 187 | 188 | exception_handler!(x87_floating_point_exception => "x87 Floating-Point Exception"); 189 | exception_handler!(alignment_check => "Alignment Check"); 190 | exception_handler!(machine_check => "Machine Check"); 191 | exception_handler!(simd_floating_point_exception => "SIMD Floating-Point Exception "); 192 | exception_handler!(virtualization_exception => "Virtualization Exception"); 193 | 194 | exception_handler!(security_exception => "Security Exception"); 195 | -------------------------------------------------------------------------------- /hyper_kernel/src/arch/interrupts.asm: -------------------------------------------------------------------------------- 1 | ; 2 | ; Copyright (c) 2022, SkillerRaptor 3 | ; 4 | ; SPDX-License-Identifier: MIT 5 | ; 6 | 7 | bits 64 8 | 9 | section .text 10 | 11 | %macro pushaq 0 12 | push rax 13 | push rbx 14 | push rcx 15 | push rdx 16 | push rbp 17 | push rdi 18 | push rsi 19 | push r8 20 | push r9 21 | push r10 22 | push r11 23 | push r12 24 | push r13 25 | push r14 26 | push r15 27 | %endmacro 28 | 29 | %macro popaq 0 30 | pop r15 31 | pop r14 32 | pop r13 33 | pop r12 34 | pop r11 35 | pop r10 36 | pop r9 37 | pop r8 38 | pop rsi 39 | pop rdi 40 | pop rbp 41 | pop rdx 42 | pop rcx 43 | pop rbx 44 | pop rax 45 | %endmacro 46 | 47 | extern idt_raise 48 | 49 | %macro interrupt_handler 1 50 | align 16 51 | interrupt_handler_%1: 52 | cld 53 | pushaq 54 | push rax 55 | mov rdi, %1 56 | mov rsi, rsp 57 | call idt_raise 58 | add rsp, 8 59 | popaq 60 | iretq 61 | %endmacro 62 | 63 | %assign i 0 64 | %rep 256 65 | interrupt_handler i 66 | %assign i i+1 67 | %endrep 68 | 69 | section .data 70 | 71 | %macro interrupt_handler_address 1 72 | dq interrupt_handler_%1 73 | %endmacro 74 | 75 | global interrupt_handlers 76 | interrupt_handlers: 77 | %assign i 0 78 | %rep 256 79 | interrupt_handler_address i 80 | %assign i i+1 81 | %endrep 82 | -------------------------------------------------------------------------------- /hyper_kernel/src/arch/io.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, SkillerRaptor 3 | * 4 | * SPDX-License-Identifier: MIT 5 | */ 6 | 7 | use core::arch::asm; 8 | 9 | pub fn in8(port: u16) -> u8 { 10 | let mut ret: u8 = 0; 11 | 12 | unsafe { 13 | asm!( 14 | "in al, dx", 15 | in("dx") port, 16 | out("al") ret, 17 | options(preserves_flags, nomem, nostack) 18 | ); 19 | } 20 | 21 | ret 22 | } 23 | 24 | pub fn out8(port: u16, value: u8) { 25 | unsafe { 26 | asm!( 27 | "out dx, al", 28 | in("dx") port, 29 | in("al") value, 30 | options(preserves_flags, nomem, nostack) 31 | ); 32 | } 33 | } 34 | 35 | pub fn in16(port: u16) -> u16 { 36 | let mut ret: u16 = 0; 37 | 38 | unsafe { 39 | asm!( 40 | "in ax, dx", 41 | in("dx") port, 42 | out("ax") ret, 43 | options(preserves_flags, nomem, nostack) 44 | ); 45 | } 46 | 47 | ret 48 | } 49 | 50 | pub fn out16(port: u16, value: u16) { 51 | unsafe { 52 | asm!( 53 | "out dx, ax", 54 | in("dx") port, 55 | in("ax") value, 56 | options(preserves_flags, nomem, nostack) 57 | ); 58 | } 59 | } 60 | 61 | pub fn in32(port: u16) -> u32 { 62 | let mut ret: u32 = 0; 63 | 64 | unsafe { 65 | asm!( 66 | "in eax, dx", 67 | in("dx") port, 68 | out("eax") ret, 69 | options(preserves_flags, nomem, nostack) 70 | ); 71 | } 72 | 73 | ret 74 | } 75 | 76 | pub fn out32(port: u16, value: u32) { 77 | unsafe { 78 | asm!( 79 | "out dx, eax", 80 | in("dx") port, 81 | in("eax") value, 82 | options(preserves_flags, nomem, nostack) 83 | ); 84 | } 85 | } 86 | 87 | pub fn wait() { 88 | out8(0x80, 0x00); 89 | } 90 | -------------------------------------------------------------------------------- /hyper_kernel/src/arch/mod.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, SkillerRaptor 3 | * 4 | * SPDX-License-Identifier: MIT 5 | */ 6 | 7 | pub mod cpu; 8 | pub mod gdt; 9 | pub mod idt; 10 | pub mod io; 11 | pub mod pic; 12 | pub mod registers; 13 | -------------------------------------------------------------------------------- /hyper_kernel/src/arch/pic.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, SkillerRaptor 3 | * 4 | * SPDX-License-Identifier: MIT 5 | */ 6 | 7 | use log::info; 8 | 9 | use crate::arch::io; 10 | 11 | const MASTER_COMMAND_SELECTOR: u16 = 0x20; 12 | const MASTER_DATA_SELECTOR: u16 = 0x21; 13 | const MASTER_OFFSET: u8 = 0x20; 14 | 15 | const SLAVE_COMMAND_SELECTOR: u16 = 0xA0; 16 | const SLAVE_DATA_SELECTOR: u16 = 0xA1; 17 | const SLAVE_OFFSET: u8 = 0x28; 18 | 19 | const ICW1_ICW4: u8 = 1 << 0; 20 | const ICW1_INIT: u8 = 1 << 4; 21 | const ICW1_8086: u8 = 1 << 0; 22 | 23 | const MASTER_IDENTITY: u8 = 0x04; 24 | const SLAVE_IDENTITY: u8 = 0x02; 25 | 26 | const END_INTERRUPT_CODE: u8 = 0x20; 27 | 28 | pub fn remap() { 29 | io::out8(MASTER_COMMAND_SELECTOR, ICW1_INIT | ICW1_ICW4); 30 | io::out8(SLAVE_COMMAND_SELECTOR, ICW1_INIT | ICW1_ICW4); 31 | 32 | io::out8(MASTER_DATA_SELECTOR, MASTER_OFFSET); 33 | io::out8(SLAVE_DATA_SELECTOR, SLAVE_OFFSET); 34 | 35 | io::out8(MASTER_DATA_SELECTOR, MASTER_IDENTITY); 36 | io::out8(SLAVE_DATA_SELECTOR, SLAVE_IDENTITY); 37 | 38 | io::out8(MASTER_DATA_SELECTOR, ICW1_8086); 39 | io::out8(SLAVE_DATA_SELECTOR, ICW1_8086); 40 | } 41 | 42 | pub fn end_of_interrupt(isr: u8) { 43 | if isr >= 0x8 { 44 | io::out8(SLAVE_COMMAND_SELECTOR, END_INTERRUPT_CODE); 45 | } 46 | 47 | io::out8(MASTER_COMMAND_SELECTOR, END_INTERRUPT_CODE); 48 | } 49 | -------------------------------------------------------------------------------- /hyper_kernel/src/arch/registers.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, SkillerRaptor 3 | * 4 | * SPDX-License-Identifier: MIT 5 | */ 6 | 7 | #[repr(C)] 8 | #[derive(Debug, Copy, Clone)] 9 | pub struct Registers { 10 | r15: u64, 11 | r14: u64, 12 | r13: u64, 13 | r12: u64, 14 | r11: u64, 15 | r10: u64, 16 | r9: u64, 17 | r8: u64, 18 | 19 | rsi: u64, 20 | rdi: u64, 21 | rbp: u64, 22 | rdx: u64, 23 | rcx: u64, 24 | rbx: u64, 25 | rax: u64, 26 | 27 | isr: u64, 28 | error: u64, 29 | 30 | rip: u64, 31 | cs: u64, 32 | flags: u64, 33 | rsp: u64, 34 | ss: u64, 35 | } 36 | -------------------------------------------------------------------------------- /hyper_kernel/src/common/logger.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, SkillerRaptor 3 | * 4 | * SPDX-License-Identifier: MIT 5 | */ 6 | 7 | use crate::{print, println}; 8 | 9 | use log::{Level, LevelFilter, Log}; 10 | 11 | static LOGGER: HyperLogger = HyperLogger; 12 | 13 | struct HyperLogger; 14 | 15 | impl Log for HyperLogger { 16 | fn enabled(&self, _: &log::Metadata) -> bool { 17 | true 18 | } 19 | 20 | fn log(&self, record: &log::Record) { 21 | if !self.enabled(record.metadata()) { 22 | return; 23 | } 24 | 25 | // TODO: Add locks for scheduler 26 | match record.level() { 27 | Level::Info => print!("\x1b[32;1minfo"), 28 | Level::Warn => print!("\x1b[93;1mwarn"), 29 | Level::Error => print!("\x1b[31;1merror"), 30 | Level::Debug => print!("\x1b[36;1mdebug"), 31 | Level::Trace => print!("\x1b[35;1mtrace"), 32 | } 33 | 34 | println!("\x1b[0m: {}", record.args()); 35 | } 36 | 37 | fn flush(&self) {} 38 | } 39 | 40 | pub fn init() { 41 | let log_level = if cfg!(debug_assertions) { 42 | LevelFilter::Trace 43 | } else { 44 | LevelFilter::Info 45 | }; 46 | 47 | log::set_logger(&LOGGER) 48 | .map(|()| log::set_max_level(log_level)) 49 | .unwrap(); 50 | } 51 | -------------------------------------------------------------------------------- /hyper_kernel/src/common/mod.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, SkillerRaptor 3 | * 4 | * SPDX-License-Identifier: MIT 5 | */ 6 | 7 | pub mod logger; 8 | pub mod writer; 9 | -------------------------------------------------------------------------------- /hyper_kernel/src/common/writer.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, SkillerRaptor 3 | * 4 | * SPDX-License-Identifier: MIT 5 | */ 6 | 7 | use core::fmt::{self, Arguments, Write}; 8 | use limine::{LimineTerminalRequest, LimineTerminalResponse}; 9 | 10 | static TERMINAL_REQUEST: LimineTerminalRequest = LimineTerminalRequest::new(0); 11 | 12 | struct Writer; 13 | 14 | impl Write for Writer { 15 | fn write_str(&mut self, s: &str) -> fmt::Result { 16 | static mut CACHED_RESPONSE: Option<&'static LimineTerminalResponse> = None; 17 | 18 | if unsafe { CACHED_RESPONSE.is_none() } { 19 | let response = TERMINAL_REQUEST.get_response().get().unwrap(); 20 | unsafe { 21 | CACHED_RESPONSE = Some(response); 22 | } 23 | } 24 | 25 | let writer = unsafe { CACHED_RESPONSE.unwrap() }; 26 | let terminal = &writer.terminals()[0]; 27 | writer.write().unwrap()(&terminal, s); 28 | 29 | Ok(()) 30 | } 31 | } 32 | 33 | #[macro_export] 34 | macro_rules! print { 35 | ($($arg:tt)*) => ($crate::common::writer::_print(format_args!($($arg)*))); 36 | } 37 | 38 | #[macro_export] 39 | macro_rules! println { 40 | () => (print!("\n")); 41 | ($($arg:tt)*) => (print!("{}\n", format_args!($($arg)*))); 42 | } 43 | 44 | #[doc(hidden)] 45 | pub fn _print(args: Arguments) { 46 | let mut writer = Writer; 47 | writer.write_fmt(args).unwrap(); 48 | } 49 | -------------------------------------------------------------------------------- /hyper_kernel/src/main.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, SkillerRaptor 3 | * 4 | * SPDX-License-Identifier: MIT 5 | */ 6 | 7 | #![no_std] 8 | #![no_main] 9 | mod arch; 10 | mod common; 11 | 12 | use crate::{ 13 | arch::{cpu, gdt, idt, pic}, 14 | common::logger, 15 | }; 16 | 17 | use core::panic::PanicInfo; 18 | use limine::*; 19 | use log::info; 20 | 21 | static BOOTLOADER_INFO: LimineBootInfoRequest = LimineBootInfoRequest::new(0); 22 | 23 | #[panic_handler] 24 | fn panic(_: &PanicInfo) -> ! { 25 | loop {} 26 | } 27 | 28 | #[no_mangle] 29 | #[allow(unconditional_panic)] 30 | extern "C" fn kernel_main() -> ! { 31 | logger::init(); 32 | 33 | let bootloader_info = BOOTLOADER_INFO.get_response().get().unwrap(); 34 | let bootloader_name = { 35 | let c_string = bootloader_info.name.to_str().unwrap(); 36 | c_string.to_str().unwrap() 37 | }; 38 | let bootloader_version = { 39 | let c_string = bootloader_info.version.to_str().unwrap(); 40 | c_string.to_str().unwrap() 41 | }; 42 | 43 | info!(""); 44 | info!("_ _ _ _ ___ ____ ____ ____ ____ "); 45 | info!("|__| \\_/ |__] |___ |__/ | | [__ "); 46 | info!("| | | | |___ | \\ |__| ___] "); 47 | info!(""); 48 | info!("Booted with {} v{}", bootloader_name, bootloader_version); 49 | info!(""); 50 | 51 | gdt::init(); 52 | pic::remap(); 53 | idt::init(); 54 | 55 | loop { 56 | cpu::halt(); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /run.sh: -------------------------------------------------------------------------------- 1 | set -e 2 | 3 | qemu-system-x86_64 -cdrom boot/hyper_os.iso --no-reboot --no-shutdown -d int -D qemulog.log 4 | -------------------------------------------------------------------------------- /rust-toolchain.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | channel = "nightly" 3 | components = ["rust-src", "rustfmt", "clippy"] 4 | --------------------------------------------------------------------------------