├── ors-kernel
├── src
│ ├── fs.rs
│ ├── devices.rs
│ ├── sync.rs
│ ├── console
│ │ ├── Tamzen7x14b.ttf
│ │ ├── Tamzen7x14r.ttf
│ │ ├── theme.rs
│ │ ├── kbd.rs
│ │ └── screen.rs
│ ├── devices
│ │ ├── virtio.rs
│ │ ├── qemu.rs
│ │ ├── serial.rs
│ │ ├── virtio
│ │ │ ├── configuration.rs
│ │ │ ├── block.rs
│ │ │ └── queue.rs
│ │ └── pci.rs
│ ├── logger.rs
│ ├── graphics
│ │ ├── color.rs
│ │ ├── rect.rs
│ │ ├── font.rs
│ │ ├── frame_buffer.rs
│ │ └── text_buffer.rs
│ ├── fs
│ │ ├── volume
│ │ │ └── virtio.rs
│ │ ├── fat
│ │ │ ├── fat_entry.rs
│ │ │ ├── boot_sector.rs
│ │ │ └── low_level.rs
│ │ └── volume.rs
│ ├── sync
│ │ ├── lazy.rs
│ │ ├── once.rs
│ │ ├── spin.rs
│ │ ├── mutex.rs
│ │ └── queue.rs
│ ├── print.rs
│ ├── segmentation.rs
│ ├── acpi.rs
│ ├── main.rs
│ ├── paging.rs
│ ├── graphics.rs
│ ├── context.rs
│ ├── console.rs
│ ├── cpu.rs
│ ├── x64.rs
│ ├── allocator.rs
│ ├── phys_memory.rs
│ ├── interrupts.rs
│ └── task.rs
├── .cargo
│ └── config.toml
├── Cargo.toml
├── build.rs
├── x86_64-unknown-none-ors.json
└── asm.s
├── .gitignore
├── qemu
├── OVMF_CODE.fd
├── OVMF_VARS.fd
├── make_and_run_image.sh
├── run_image.sh
└── make_image.sh
├── Cargo.toml
├── docs
├── screenshots
│ └── 2022-01-30.png
└── screenshots.md
├── ors-common
├── Cargo.toml
└── src
│ ├── lib.rs
│ ├── frame_buffer.rs
│ ├── memory_map.rs
│ └── non_contiguous.rs
├── ors-loader
├── .cargo
│ └── config.toml
├── Cargo.toml
└── src
│ ├── fs.rs
│ └── main.rs
├── Makefile
├── LICENSE
└── README.md
/ors-kernel/src/fs.rs:
--------------------------------------------------------------------------------
1 | pub mod fat;
2 | pub mod volume;
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /target
2 | **/*.rs.bk
3 | .vscode/
4 |
5 | mnt
6 | disk.img
7 |
--------------------------------------------------------------------------------
/qemu/OVMF_CODE.fd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yubrot/ors/HEAD/qemu/OVMF_CODE.fd
--------------------------------------------------------------------------------
/qemu/OVMF_VARS.fd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yubrot/ors/HEAD/qemu/OVMF_VARS.fd
--------------------------------------------------------------------------------
/ors-kernel/src/devices.rs:
--------------------------------------------------------------------------------
1 | pub mod pci;
2 | pub mod qemu;
3 | pub mod serial;
4 | pub mod virtio;
5 |
--------------------------------------------------------------------------------
/Cargo.toml:
--------------------------------------------------------------------------------
1 | [workspace]
2 | members = [
3 | "ors-common",
4 | "ors-loader",
5 | "ors-kernel",
6 | ]
7 |
--------------------------------------------------------------------------------
/docs/screenshots/2022-01-30.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yubrot/ors/HEAD/docs/screenshots/2022-01-30.png
--------------------------------------------------------------------------------
/docs/screenshots.md:
--------------------------------------------------------------------------------
1 | # 2022/01/30
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/ors-kernel/src/sync.rs:
--------------------------------------------------------------------------------
1 | pub mod lazy;
2 | pub mod mutex;
3 | pub mod once;
4 | pub mod queue;
5 | pub mod spin;
6 |
--------------------------------------------------------------------------------
/ors-kernel/src/console/Tamzen7x14b.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yubrot/ors/HEAD/ors-kernel/src/console/Tamzen7x14b.ttf
--------------------------------------------------------------------------------
/ors-kernel/src/console/Tamzen7x14r.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yubrot/ors/HEAD/ors-kernel/src/console/Tamzen7x14r.ttf
--------------------------------------------------------------------------------
/ors-common/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | edition = "2021"
3 | name = "ors-common"
4 | version = "0.1.0"
5 |
6 | [dependencies]
7 |
--------------------------------------------------------------------------------
/ors-loader/.cargo/config.toml:
--------------------------------------------------------------------------------
1 | [build]
2 | target = "x86_64-unknown-uefi"
3 |
4 | [unstable]
5 | build-std = ["core", "compiler_builtins", "alloc"]
6 | build-std-features = ["compiler-builtins-mem"]
7 |
--------------------------------------------------------------------------------
/ors-common/src/lib.rs:
--------------------------------------------------------------------------------
1 | #![feature(maybe_uninit_uninit_array)] // for non_contiguous
2 | #![feature(maybe_uninit_array_assume_init)] // for non_contiguous
3 | #![no_std]
4 |
5 | #[cfg(test)]
6 | extern crate alloc;
7 |
8 | pub mod frame_buffer;
9 | pub mod memory_map;
10 | pub mod non_contiguous;
11 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | all: ors-loader.efi ors-kernel.elf
2 |
3 | ors-loader.efi:
4 | cd ors-loader && cargo build
5 |
6 | ors-kernel.elf:
7 | cd ors-kernel && cargo build
8 |
9 | qemu: ors-loader.efi ors-kernel.elf
10 | cd ors-kernel && cargo run
11 |
12 | rerun:
13 | cd ors-kernel && ../qemu/run_image.sh ./disk.img
14 |
--------------------------------------------------------------------------------
/ors-kernel/src/devices/virtio.rs:
--------------------------------------------------------------------------------
1 | //! VirtIO Drivers
2 | //!
3 | //! ors implements VirtIO Legacy Driver:
4 | //! https://docs.oasis-open.org/virtio/virtio/v1.1/virtio-v1.1.pdf
5 |
6 | pub mod block;
7 | mod configuration;
8 | mod queue;
9 |
10 | pub use configuration::Configuration;
11 | pub use queue::{Buffer, VirtQueue};
12 |
--------------------------------------------------------------------------------
/ors-kernel/src/devices/qemu.rs:
--------------------------------------------------------------------------------
1 | use x86_64::instructions::port::Port;
2 |
3 | static mut QEMU_DEBUG_EXIT: Port = Port::new(0xf4);
4 |
5 | #[derive(PartialEq, Eq, Debug, Clone, Copy)]
6 | #[repr(u32)]
7 | pub enum ExitCode {
8 | Success = 0x10,
9 | Failure = 0x11,
10 | }
11 |
12 | pub fn exit(exit_code: ExitCode) {
13 | unsafe { QEMU_DEBUG_EXIT.write(exit_code as u32) }
14 | }
15 |
--------------------------------------------------------------------------------
/qemu/make_and_run_image.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh -e
2 |
3 | if [ $# -lt 1 ]; then
4 | echo "Usage: $0 []"
5 | exit 1
6 | fi
7 |
8 | DEVENV_DIR=$(dirname "$0")
9 | DISK_IMG=./disk.img
10 | MOUNT_POINT=./mnt
11 | BOOTLOADER_EFI=$1
12 | KERNEL_ELF=$2
13 |
14 | $DEVENV_DIR/make_image.sh $DISK_IMG $MOUNT_POINT $BOOTLOADER_EFI $KERNEL_ELF
15 | $DEVENV_DIR/run_image.sh $DISK_IMG
16 |
--------------------------------------------------------------------------------
/ors-kernel/.cargo/config.toml:
--------------------------------------------------------------------------------
1 | [build]
2 | target = "./x86_64-unknown-none-ors.json"
3 |
4 | [unstable]
5 | build-std = ["core", "compiler_builtins", "alloc"]
6 | build-std-features = ["compiler-builtins-mem"]
7 |
8 | [target.'cfg(target_os = "none")']
9 | # FIXME: This assumes that the ors-loader.efi has already been built
10 | runner = ['../qemu/make_and_run_image.sh', '../target/x86_64-unknown-uefi/debug/ors-loader.efi']
11 |
--------------------------------------------------------------------------------
/ors-common/src/frame_buffer.rs:
--------------------------------------------------------------------------------
1 | #[repr(C)]
2 | #[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Clone, Copy)]
3 | pub enum PixelFormat {
4 | Rgb,
5 | Bgr,
6 | }
7 |
8 | #[repr(C)]
9 | #[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Clone, Copy)]
10 | pub struct FrameBuffer {
11 | pub frame_buffer: *mut u8,
12 | pub stride: u32,
13 | pub resolution: (u32, u32), // (horizontal, vertical)
14 | pub format: PixelFormat,
15 | }
16 |
--------------------------------------------------------------------------------
/ors-loader/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | authors = ["yubrot "]
3 | edition = "2021"
4 | name = "ors-loader"
5 | version = "0.1.0"
6 |
7 | [dependencies]
8 | goblin = {version = "0.4", features = ["elf32", "elf64", "endian_fd"], default-features = false}
9 | log = {version = "0.4", default-features = false}
10 | ors-common = {path = "../ors-common"}
11 | uefi = {version = "0.14", features = ["alloc", "logger", "exts"]}
12 | uefi-services = "0.11"
13 | x86_64 = "0.14"
14 |
--------------------------------------------------------------------------------
/ors-kernel/src/logger.rs:
--------------------------------------------------------------------------------
1 | pub fn register() {
2 | log::set_logger(&KernelLogger).unwrap();
3 | log::set_max_level(log::LevelFilter::Info);
4 | }
5 |
6 | struct KernelLogger;
7 |
8 | impl log::Log for KernelLogger {
9 | fn enabled(&self, _metadata: &log::Metadata) -> bool {
10 | true
11 | }
12 |
13 | fn log(&self, record: &log::Record) {
14 | sprintln!("{}: {}", record.level(), record.args());
15 | }
16 |
17 | fn flush(&self) {}
18 | }
19 |
--------------------------------------------------------------------------------
/ors-kernel/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | edition = "2021"
3 | name = "ors-kernel"
4 | version = "0.1.0"
5 |
6 | [dependencies]
7 | ab_glyph = {version = "0.2", default-features = false, features = ["libm"]}
8 | acpi = "4"
9 | bit_field = "0.10"
10 | derive-new = {version = "0.5", default-features = false}
11 | heapless = "0.7"
12 | libm = "0.2"
13 | log = {version = "0.4", default-features = false}
14 | ors-common = {path = "../ors-common"}
15 | pc-keyboard = "0.5"
16 | spin = "0.9"
17 | static_assertions = "1"
18 | uart_16550 = "0.2"
19 | x86_64 = "0.14"
20 |
--------------------------------------------------------------------------------
/ors-kernel/src/devices/serial.rs:
--------------------------------------------------------------------------------
1 | use crate::sync::spin::{Spin, SpinGuard};
2 | pub use uart_16550::SerialPort as Port;
3 |
4 | const DEFAULT_PORT_ADDRESS: u16 = 0x3f8;
5 |
6 | static DEFAULT_PORT: Spin = Spin::new(unsafe { Port::new(DEFAULT_PORT_ADDRESS) });
7 |
8 | pub fn default_port() -> SpinGuard<'static, Port> {
9 | DEFAULT_PORT.lock()
10 | }
11 |
12 | /// Default port with no locking mechanism.
13 | /// Used for debugging output in interrupt handlers and panic handlers.
14 | pub fn raw_default_port() -> Port {
15 | unsafe { Port::new(DEFAULT_PORT_ADDRESS) }
16 | }
17 |
--------------------------------------------------------------------------------
/ors-common/src/memory_map.rs:
--------------------------------------------------------------------------------
1 | use core::slice;
2 |
3 | #[repr(C)]
4 | #[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Clone)]
5 | pub struct MemoryMap {
6 | pub descriptors: *const Descriptor,
7 | pub descriptors_len: u64,
8 | }
9 |
10 | impl MemoryMap {
11 | pub fn descriptors(&self) -> &[Descriptor] {
12 | unsafe { slice::from_raw_parts(self.descriptors, self.descriptors_len as usize) }
13 | }
14 | }
15 |
16 | #[repr(C)]
17 | #[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Clone)]
18 | pub struct Descriptor {
19 | pub phys_start: u64,
20 | pub phys_end: u64,
21 | }
22 |
--------------------------------------------------------------------------------
/qemu/run_image.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh -e
2 |
3 | if [ $# -lt 1 ]; then
4 | echo "Usage: $0 "
5 | exit 1
6 | fi
7 |
8 | DEVENV_DIR=$(dirname "$0")
9 | DISK_IMG=$1
10 |
11 | if [ ! -f $DISK_IMG ]; then
12 | echo "No such file: $DISK_IMG"
13 | exit 1
14 | fi
15 |
16 | set +e
17 | qemu-system-x86_64 \
18 | -smp 4 \
19 | -m 1G \
20 | -drive if=pflash,format=raw,readonly=on,file=$DEVENV_DIR/OVMF_CODE.fd \
21 | -drive if=pflash,format=raw,file=$DEVENV_DIR/OVMF_VARS.fd \
22 | -drive if=none,id=drive0,format=raw,file=$DISK_IMG \
23 | -device isa-debug-exit,iobase=0xf4,iosize=0x04 \
24 | -device virtio-blk-pci,drive=drive0 \
25 | -serial mon:stdio \
26 | $QEMU_OPTS
27 | [ $? -eq 33 -o $? -eq 0 ]
28 |
--------------------------------------------------------------------------------
/ors-kernel/src/graphics/color.rs:
--------------------------------------------------------------------------------
1 | #[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Clone, Copy, Hash)]
2 | pub struct Color {
3 | pub r: u8,
4 | pub g: u8,
5 | pub b: u8,
6 | }
7 |
8 | impl Color {
9 | pub const fn new(r: u8, g: u8, b: u8) -> Self {
10 | Self { r, g, b }
11 | }
12 |
13 | pub fn mix(self, other: Self, f: f32) -> Self {
14 | let r = self.r as f32 * (1.0 - f) + other.r as f32 * f;
15 | let g = self.g as f32 * (1.0 - f) + other.g as f32 * f;
16 | let b = self.b as f32 * (1.0 - f) + other.b as f32 * f;
17 | Self::new(r as u8, g as u8, b as u8)
18 | }
19 | }
20 |
21 | impl From<(u8, u8, u8)> for Color {
22 | fn from((r, g, b): (u8, u8, u8)) -> Self {
23 | Self::new(r, g, b)
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/ors-kernel/build.rs:
--------------------------------------------------------------------------------
1 | use std::env;
2 | use std::path::PathBuf;
3 | use std::process::Command;
4 |
5 | fn main() {
6 | let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
7 | println!("cargo:rustc-link-search={}", out_dir.display());
8 |
9 | // asm.s -> asm.o -> libasm.a
10 | let out_asm = {
11 | let mut path = out_dir.clone();
12 | path.push("asm.o");
13 | path
14 | };
15 | Command::new("nasm")
16 | .args(&["-f", "elf64", "-o", out_asm.to_str().unwrap(), "asm.s"])
17 | .status()
18 | .unwrap();
19 | Command::new("ar")
20 | .args(&["crus", "libasm.a", "asm.o"])
21 | .current_dir(&out_dir)
22 | .status()
23 | .unwrap();
24 | println!("cargo:rustc-link-lib=static=asm");
25 | }
26 |
--------------------------------------------------------------------------------
/ors-kernel/x86_64-unknown-none-ors.json:
--------------------------------------------------------------------------------
1 | {
2 | "arch": "x86_64",
3 | "code-model": "kernel",
4 | "cpu": "x86-64",
5 | "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128",
6 | "disable-redzone": true,
7 | "executables": true,
8 | "exe-suffix": ".elf",
9 | "features": "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2,+soft-float",
10 | "linker-flavor": "ld.lld",
11 | "llvm-target": "x86_64-unknown-none-elf",
12 | "max-atomic-width": 64,
13 | "os": "none",
14 | "panic-strategy": "abort",
15 | "relro-level": "off",
16 | "position-independent-executables": false,
17 | "post-link-args": {
18 | "ld.lld": [
19 | "--entry=kernel_main",
20 | "--image-base=0x100000",
21 | "--static"
22 | ]
23 | },
24 | "target-pointer-width": "64"
25 | }
26 |
--------------------------------------------------------------------------------
/qemu/make_image.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh -e
2 |
3 | if [ $# -lt 3 ]; then
4 | echo "Usage: $0 []"
5 | exit 1
6 | fi
7 |
8 | DEVENV_DIR=$(dirname "$0")
9 | DISK_IMG=$1
10 | MOUNT_POINT=$2
11 | BOOTLOADER_EFI=$3
12 | KERNEL_ELF=$4
13 |
14 | if [ ! -f $BOOTLOADER_EFI ]; then
15 | echo "No such file: $BOOTLOADER_EFI"
16 | exit 1
17 | fi
18 |
19 | # Create a disk image and format it to FAT
20 | rm -f $DISK_IMG
21 | qemu-img create -f raw $DISK_IMG 200M
22 | mkfs.fat -n 'ORS' -s 2 -f 2 -R 32 -F 32 $DISK_IMG
23 |
24 | # Initialize disk image
25 | mkdir -p $MOUNT_POINT
26 | sudo mount -o loop $DISK_IMG $MOUNT_POINT
27 | sudo mkdir -p $MOUNT_POINT/EFI/BOOT
28 | sudo cp $BOOTLOADER_EFI $MOUNT_POINT/EFI/BOOT/BOOTX64.EFI
29 | if [ "$KERNEL_ELF" != "" ]; then
30 | sudo cp $KERNEL_ELF $MOUNT_POINT/ors-kernel.elf
31 | fi
32 | sleep 0.5
33 | sudo umount $MOUNT_POINT
34 |
35 |
--------------------------------------------------------------------------------
/ors-kernel/src/fs/volume/virtio.rs:
--------------------------------------------------------------------------------
1 | mod virtio {
2 | pub use crate::devices::virtio::block::*;
3 | }
4 | use super::{Sector, Volume, VolumeError, VolumeErrorKind};
5 | use derive_new::new;
6 |
7 | impl From for VolumeErrorKind {
8 | fn from(e: virtio::Error) -> Self {
9 | match e {
10 | virtio::Error::Io => Self::Io,
11 | virtio::Error::OutOfRange => Self::OutOfRange,
12 | _ => Self::Unknown,
13 | }
14 | }
15 | }
16 |
17 | /// Let the entire VirtIO block as a single volume.
18 | #[derive(Debug, Clone, Copy, new)]
19 | pub struct VirtIOBlockVolume(&'static virtio::Block);
20 |
21 | impl Volume for VirtIOBlockVolume {
22 | fn sector_count(&self) -> usize {
23 | self.0.capacity() as usize
24 | }
25 |
26 | fn sector_size(&self) -> usize {
27 | virtio::Block::SECTOR_SIZE
28 | }
29 |
30 | fn read(&self, sector: Sector, buf: &mut [u8]) -> Result<(), VolumeError> {
31 | self.0
32 | .read(sector.index() as u64, buf)
33 | .map_err(|k| VolumeError::new(sector, k.into()))
34 | }
35 |
36 | fn write(&self, sector: Sector, buf: &[u8]) -> Result<(), VolumeError> {
37 | self.0
38 | .write(sector.index() as u64, buf)
39 | .map_err(|k| VolumeError::new(sector, k.into()))
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/ors-kernel/src/sync/lazy.rs:
--------------------------------------------------------------------------------
1 | use super::once::Once;
2 | use core::cell::Cell;
3 | use core::fmt;
4 | use core::ops::Deref;
5 |
6 | /// Almost same as `spin::Lazy`, except it uses `ors_kernel::sync::once::Once`.
7 | pub struct Lazy T> {
8 | cell: Once,
9 | init: Cell