├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── Makefile ├── README.md ├── build.rs ├── grub.cfg ├── image ├── Dockerfile └── run.sh ├── layout.ld ├── run.sh ├── src ├── asm │ └── boot.asm ├── main.rs └── panic.rs └── x86_64-unknown-intermezzos-gnu.json /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | [root] 2 | name = "intermezzos" 3 | version = "0.1.0" 4 | 5 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "intermezzos" 3 | version = "0.1.0" 4 | authors = ["The intermezzOS team"] 5 | build = "build.rs" 6 | 7 | [workspace] 8 | 9 | [dependencies] 10 | 11 | [profile.dev] 12 | panic = "abort" 13 | 14 | [profile.release] 15 | panic = "abort" 16 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | cargo: 2 | ./run.sh xargo build --release --target x86_64-unknown-intermezzos-gnu 3 | 4 | # cargo test fails for some reason, not sure why yet 5 | test: 6 | cd console && cargo test 7 | cd interrupts && cargo test 8 | cd keyboard && cargo test 9 | cd pic && cargo test 10 | 11 | iso: cargo grub.cfg 12 | mkdir -p target/isofiles/boot/grub 13 | cp grub.cfg target/isofiles/boot/grub 14 | cp target/x86_64-unknown-intermezzos-gnu/release/intermezzos target/isofiles/boot/ 15 | ./run.sh grub-mkrescue -o target/os.iso target/isofiles 16 | 17 | run: iso 18 | qemu-system-x86_64 -cdrom target/os.iso 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # intermezzOS: kernel 2 | 3 | intermezzOS is a hobby operating system. This repository is for a "bare bones" of its kernel. 4 | See [the website](http://intermezzos.github.io/) for more about the project overall. 5 | 6 | A "bare bones" is a ready-made beginning of an operating system. The code you'll find here 7 | will go "from boot to kmain," ready for you to write your own kernel on top of. 8 | 9 | Also, feel free to join us at `#intermezzOS` on Freenode’s IRC network, if you 10 | want to chat. 11 | 12 | ## Building 13 | 14 | Make sure you have a nightly Rust installed. Something like this: 15 | 16 | ```bash 17 | $ rustc --version 18 | rustc 1.13.0-nightly (267cde259 2016-05-25) 19 | ``` 20 | 21 | If you don’t have Rust installed (and maybe even if you've installed Rust some 22 | other way), you should use [rustup](https://rustup.rs/) to get it; it makes 23 | using multiple Rust versions very easy. 24 | 25 | Then get this stuff: 26 | 27 | * `nasm` 28 | * `ld` 29 | * `grub-mkrescue`: you may also need to install `xorriso` 30 | * `qemu-system-x86_64` 31 | 32 | If you're on OS X, you might want to use [this 33 | script](http://intermezzos.github.io/book/appendix/osx-install.html) to get 34 | them. You'll also need to set this in your `~/.cargo/config`: 35 | 36 | ```toml 37 | [target.x86_64-unknown-intermezzos-gnu] 38 | linker = "/Users/yourusername/opt/bin/x86_64-pc-elf-gcc" 39 | ``` 40 | 41 | Where `yourusername` is your username. 42 | 43 | After all that setup, it’s as easy as: 44 | 45 | ```bash 46 | $ make run 47 | ``` 48 | 49 | This will: 50 | 51 | * Build the Rust code with Cargo 52 | * Compile the bit of assembly needed to boot 53 | * Link it all together 54 | * Build an ISO out of it all 55 | * Run that ISO in qemu 56 | 57 | ## License 58 | 59 | This project is dual licensed under Apache2/MIT. See the two `LICENSE-*` files 60 | for details. 61 | 62 | ## Code of conduct 63 | 64 | The intermezzOS project has a [Code of 65 | Conduct](http://intermezzos.github.io/code-of-conduct.html), please observe it. 66 | -------------------------------------------------------------------------------- /build.rs: -------------------------------------------------------------------------------- 1 | use std::process::Command; 2 | use std::env; 3 | use std::path::Path; 4 | 5 | fn main() { 6 | let out_dir = env::var("OUT_DIR").unwrap(); 7 | 8 | Command::new("nasm").args(&["src/asm/boot.asm", "-felf64", "-o"]) 9 | .arg(&format!("{}/boot.o", out_dir)) 10 | .status().unwrap(); 11 | 12 | Command::new("ar").args(&["crus", "libboot.a", "boot.o"]) 13 | .current_dir(&Path::new(&out_dir)) 14 | .status().unwrap(); 15 | 16 | println!("cargo:rustc-link-search=native={}", out_dir); 17 | println!("cargo:rustc-link-lib=static=boot"); 18 | println!("cargo:rerun-if-changed=/src/asm/boot.asm"); 19 | } 20 | -------------------------------------------------------------------------------- /grub.cfg: -------------------------------------------------------------------------------- 1 | set timeout=0 2 | set default=0 3 | 4 | menuentry "intermezzOS" { 5 | multiboot2 /boot/intermezzos 6 | boot 7 | } 8 | -------------------------------------------------------------------------------- /image/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:16.04 2 | 3 | RUN apt-get update -y && apt-get install -y --no-install-recommends \ 4 | xorriso \ 5 | binutils \ 6 | nasm \ 7 | git \ 8 | qemu \ 9 | gcc \ 10 | libc6-dev \ 11 | curl \ 12 | ca-certificates \ 13 | make \ 14 | sudo \ 15 | grub-pc \ 16 | xorriso \ 17 | grub-common 18 | 19 | ENV RUSTUP_HOME=/rustup 20 | ENV CARGO_HOME=/cargo 21 | RUN curl https://sh.rustup.rs | sh -s -- -y --default-toolchain=nightly 22 | 23 | ENV PATH=$PATH:/cargo/bin 24 | RUN cargo install xargo --vers 0.2.1 25 | RUN rustup component add rust-src 26 | -------------------------------------------------------------------------------- /image/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | if [ "$LOCAL_USER_ID" != "" ]; then 6 | useradd --shell /bin/bash -u $LOCAL_USER_ID -o -c "" -m $LOCAL_USER 7 | export HOME=/os/target/home 8 | export LOCAL_USER_ID= 9 | exec sudo -E -u $LOCAL_USER env PATH=$PATH "$@" 10 | fi 11 | 12 | exec "$@" 13 | -------------------------------------------------------------------------------- /layout.ld: -------------------------------------------------------------------------------- 1 | ENTRY(start) 2 | 3 | MAGIC_NUMBER = 0xe85250d6; 4 | 5 | SECTIONS { 6 | . = 1M; 7 | 8 | .boot : 9 | { 10 | header_start = .; 11 | 12 | /* Magic number */ 13 | LONG(MAGIC_NUMBER) 14 | /* Architecture 0: Protected mode i386 */ 15 | LONG(0) 16 | /* Header length */ 17 | LONG(header_end - header_start) 18 | /* Checksum */ 19 | LONG(0x100000000 - (MAGIC_NUMBER + (header_end - header_start))) 20 | /* Required end tag */ 21 | /* Type */ 22 | SHORT(0) 23 | /* Flags */ 24 | SHORT(0) 25 | /* Size */ 26 | LONG(8) 27 | 28 | header_end = .; 29 | } 30 | 31 | .text : 32 | { 33 | KEEP(*(.text.start)) 34 | *(.text.*) 35 | } 36 | 37 | /DISCARD/ : 38 | { 39 | *(.note.gnu.*) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | docker build --rm -t intermezzos-bare-bones image 6 | exec docker run \ 7 | --rm \ 8 | --volume `pwd`:/os \ 9 | --env LOCAL_USER=$USER \ 10 | --env LOCAL_USER_ID=`id -u` \ 11 | --env TERM=$TERM \ 12 | --workdir /os \ 13 | --interactive \ 14 | --tty \ 15 | intermezzos-bare-bones \ 16 | image/run.sh \ 17 | "$@" 18 | -------------------------------------------------------------------------------- /src/asm/boot.asm: -------------------------------------------------------------------------------- 1 | extern kmain 2 | global start 3 | 4 | section .boot 5 | bits 32 6 | start: 7 | 8 | ; Point the first entry of the level 4 page table to the first entry in the 9 | ; p3 table 10 | mov eax, p3_table 11 | or eax, 0b11 ; 12 | mov dword [p4_table + 0], eax 13 | 14 | ; Point the first entry of the level 3 page table to the first entry in the 15 | ; p2 table 16 | mov eax, p2_table 17 | or eax, 0b11 18 | mov dword [p3_table + 0], eax 19 | 20 | ; point each page table level two entry to a page 21 | mov ecx, 0 ; counter variable 22 | .map_p2_table: 23 | mov eax, 0x200000 ; 2MiB 24 | mul ecx 25 | or eax, 0b10000011 26 | mov [p2_table + ecx * 8], eax 27 | 28 | inc ecx 29 | cmp ecx, 512 30 | jne .map_p2_table 31 | 32 | ; move page table address to cr3 33 | mov eax, p4_table 34 | mov cr3, eax 35 | 36 | ; enable PAE 37 | mov eax, cr4 38 | or eax, 1 << 5 39 | mov cr4, eax 40 | 41 | ; set the long mode bit 42 | mov ecx, 0xC0000080 43 | rdmsr 44 | or eax, 1 << 8 45 | wrmsr 46 | 47 | ; enable paging 48 | mov eax, cr0 49 | or eax, (1 << 31 | 1 << 16) 50 | mov cr0, eax 51 | 52 | lgdt [gdt64.pointer] 53 | 54 | ; update selectors 55 | mov ax, gdt64.data 56 | mov ss, ax 57 | mov ds, ax 58 | mov es, ax 59 | 60 | ; long jump to kmain setting `cs` register to `gdt64.code` 61 | jmp gdt64.code:kmain 62 | 63 | ; shouldn't ever happen 64 | hlt 65 | 66 | section .bss 67 | align 4096 68 | p4_table: 69 | resb 4096 70 | p3_table: 71 | resb 4096 72 | p2_table: 73 | resb 4096 74 | 75 | section .rodata 76 | gdt64: 77 | dq 0 ; zero entry 78 | .code: equ $ - gdt64 79 | dq (1<<44) | (1<<47) | (1<<41) | (1<<43) | (1<<53) ; code segment 80 | .data: equ $ - gdt64 81 | dq (1<<44) | (1<<47) | (1<<41) ; data segment 82 | .pointer: 83 | dw $ - gdt64 - 1 84 | dq gdt64 85 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | #![feature(lang_items)] 4 | 5 | #[cfg(not(test))] 6 | pub mod panic; 7 | 8 | #[no_mangle] 9 | pub extern "C" fn kmain() -> ! { 10 | unsafe { 11 | let vga = 0xb8000 as *mut u64; 12 | 13 | *vga = 0x2f592f412f4b2f4f; 14 | }; 15 | 16 | loop { } 17 | } 18 | -------------------------------------------------------------------------------- /src/panic.rs: -------------------------------------------------------------------------------- 1 | use core::fmt; 2 | 3 | #[lang = "panic_fmt"] 4 | #[no_mangle] 5 | pub extern fn rust_begin_panic(_msg: fmt::Arguments, 6 | _file: &'static str, 7 | _line: u32) -> ! { 8 | loop {} 9 | } 10 | -------------------------------------------------------------------------------- /x86_64-unknown-intermezzos-gnu.json: -------------------------------------------------------------------------------- 1 | { 2 | "arch": "x86_64", 3 | "cpu": "x86-64", 4 | "data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128", 5 | "executables": true, 6 | "llvm-target": "x86_64-unknown-none-gnu", 7 | "no-compiler-rt": true, 8 | "os": "intermezzos", 9 | "target-endian": "little", 10 | "target-pointer-width": "64", 11 | "features": "-mmx,-fxsr,-sse,-sse2,+soft-float", 12 | "pre-link-args": ["-Tlayout.ld", "-Wl,-n", "-nostartfiles"], 13 | "disable-redzone": true, 14 | "eliminate-frame-pointer": false 15 | } 16 | --------------------------------------------------------------------------------