aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksa Vuckovic <aleksa@vuckovic.cc>2023-12-13 01:38:14 +0100
committerAleksa Vuckovic <aleksa@vuckovic.cc>2024-04-02 23:17:31 +0200
commit36137438446c1754a522c5b3cc3aff92c43ac1ee (patch)
treef7358ef0aec7023321e52e116f94fba95e52611f
Initial commitHEADmaster
X86/X86_64 debug/release WORKING riscv64 WORKING uart idk
-rw-r--r--.bochsrc9
-rw-r--r--.cargo/config.toml3
-rw-r--r--.gitignore8
-rw-r--r--Cargo.lock57
-rw-r--r--Cargo.toml13
-rw-r--r--Makefile152
-rw-r--r--README.md0
-rw-r--r--arch/riscv64.json15
-rw-r--r--arch/riscv64.ld25
-rw-r--r--arch/x86.json15
-rw-r--r--arch/x86.ld74
-rw-r--r--arch/x86_64.json15
-rw-r--r--arch/x86_64.ld81
-rwxr-xr-xriscv64-uboot.sh3
-rw-r--r--src/Makefile18
-rw-r--r--src/arch/mod.rs14
-rw-r--r--src/arch/riscv64/boot/entry.S37
-rw-r--r--src/arch/riscv64/io/mod.rs2
-rw-r--r--src/arch/riscv64/io/uart.rs27
-rw-r--r--src/arch/riscv64/mod.rs2
-rw-r--r--src/arch/x86/boot/boot.S126
-rw-r--r--src/arch/x86/common/boot/mod.rs2
-rw-r--r--src/arch/x86/common/boot/multiboot.S11
-rw-r--r--src/arch/x86/common/boot/multiboot.rs79
-rw-r--r--src/arch/x86/common/boot/multiboot2.S42
-rw-r--r--src/arch/x86/common/forall.rs5
-rw-r--r--src/arch/x86/common/io/mod.rs2
-rw-r--r--src/arch/x86/common/io/writer.rs72
-rw-r--r--src/arch/x86/common/mod.rs8
-rw-r--r--src/arch/x86/mod.rs10
-rw-r--r--src/arch/x86/once.rs6
-rw-r--r--src/arch/x86_64/boot/boot.S128
-rw-r--r--src/arch/x86_64/boot/boot64.S26
-rw-r--r--src/arch/x86_64/mod.rs4
-rw-r--r--src/arch/x86_64/once.rs6
-rw-r--r--src/grub.cfg7
-rw-r--r--src/lib.rs39
-rw-r--r--tftp/dnsmasq.conf20
-rw-r--r--tftp/dnsmasq.service20
-rwxr-xr-xtftp/setup.sh15
40 files changed, 1198 insertions, 0 deletions
diff --git a/.bochsrc b/.bochsrc
new file mode 100644
index 0000000..0524112
--- /dev/null
+++ b/.bochsrc
@@ -0,0 +1,9 @@
+ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
+ata0-master: type=cdrom, path="kernel.iso", status=inserted
+boot: cdrom
+log: xbochs.log
+megs: 128
+magic_break: enabled=1
+com1: enabled=1, mode=file, dev=serial.log
+display_library: x, options="gui_debug"
+cpu: count=4
diff --git a/.cargo/config.toml b/.cargo/config.toml
new file mode 100644
index 0000000..f5905ac
--- /dev/null
+++ b/.cargo/config.toml
@@ -0,0 +1,3 @@
+[unstable]
+build-std-features = ["compiler-builtins-mem"]
+build-std = ["core", "compiler_builtins"]
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..7fba126
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,8 @@
+/target
+/isodir
+*.o
+*.d
+*.bin
+*.iso
+*.log
+bx_enh_dbg.ini
diff --git a/Cargo.lock b/Cargo.lock
new file mode 100644
index 0000000..09605ba
--- /dev/null
+++ b/Cargo.lock
@@ -0,0 +1,57 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "autocfg"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
+
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+dependencies = [
+ "spin 0.5.2",
+]
+
+[[package]]
+name = "lock_api"
+version = "0.4.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45"
+dependencies = [
+ "autocfg",
+ "scopeguard",
+]
+
+[[package]]
+name = "myrustkernel"
+version = "0.1.0"
+dependencies = [
+ "lazy_static",
+ "spin 0.9.8",
+]
+
+[[package]]
+name = "scopeguard"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
+
+[[package]]
+name = "spin"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
+
+[[package]]
+name = "spin"
+version = "0.9.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
+dependencies = [
+ "lock_api",
+]
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..8c8cf11
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,13 @@
+[package]
+name = "myrustkernel"
+version = "0.1.0"
+edition = "2021"
+
+[lib]
+crate-type = ["staticlib"]
+
+[dependencies]
+
+[target.'cfg(any(target_arch = "x86", target_arch = "x86_64"))'.dependencies]
+lazy_static = { version = "1.4.0", default-features = false, features = ["spin_no_std"] }
+spin = "0.9.8"
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..d370666
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,152 @@
+export
+ARCH ?= x86_64
+DEBUG ?= 1
+RUST_LIB_PATH=debug
+CARGO_FLAGS =
+#QEMU_DEBUG=-d int -no-reboot -no-shutdown
+TARGET=kernel.iso
+
+ifeq ($(DEBUG), 0)
+ RUST_LIB_PATH=release
+ CARGO_FLAGS=--release
+endif
+
+ifeq ($(ARCH), x86)
+ QEMU = qemu-system-i386
+ QEMU_OPTS = -serial file:serial.log
+ MACHINE = -machine q35
+ BOOT = -cdrom kernel.iso
+ ARCH_PREFIX = i386-elf-
+ target = "./arch/x86.json"
+ RUST_OBJS = ../target/x86/$(RUST_LIB_PATH)/libmyrustkernel.a
+ ASM_PATHS = ./arch/x86/boot
+ ASM_PATHS += ./arch/x86/common/boot
+ CARGO_B = --target "./arch/x86.json"
+ LD_SCRIPT=../arch/x86.ld
+endif
+
+ifeq ($(ARCH), x86_64)
+ QEMU = qemu-system-x86_64
+ QEMU_OPTS = -serial file:serial.log
+ MACHINE = -machine q35
+ BOOT = -cdrom kernel.iso
+ ARCH_PREFIX = x86_64-elf-
+ target = "./arch/x86_64.json"
+ RUST_OBJS = ../target/x86_64/$(RUST_LIB_PATH)/libmyrustkernel.a
+ ASM_PATHS = ./arch/x86_64/boot
+ ASM_PATHS += ./arch/x86/common/boot
+ CARGO_B = --target "./arch/x86_64.json"
+ LD_SCRIPT=../arch/x86_64.ld
+endif
+
+ifeq ($(ARCH), riscv64)
+ QEMU = qemu-system-riscv64
+ QEMU_OPTS = -nographic -serial mon:stdio
+ MACHINE = -machine virt -bios none
+ BOOT = -kernel ./src/kernel.bin
+ ARCH_PREFIX = riscv64-elf-
+ target = "./arch/riscv64.json"
+ RUST_OBJS = ../target/riscv64/$(RUST_LIB_PATH)/libmyrustkernel.a
+ ASM_PATHS = ./arch/riscv64/boot
+ CARGO_B = --target "./arch/riscv64.json"
+ LD_SCRIPT=../arch/riscv64.ld
+ TARGET=src/kernel.bin
+endif
+
+ifndef ARCH_PREFIX
+$(error ARCH available: "x86_64", "x86", "riscv64")
+endif
+
+CC = $(ARCH_PREFIX)gcc
+AS = $(ARCH_PREFIX)as
+LD = $(ARCH_PREFIX)ld
+OBJDUMP = $(ARCH_PREFIX)objcopy
+OBJCOPY = $(ARCH_PREFIX)objdump
+
+W := -Wall -Werror -Wextra -Wshadow -Wcast-align
+# W:= -Wpointer-arith -pedantic -Wmissing-prototypes -Wmissing-declarations
+W += -Wwrite-strings -Wredundant-decls -Wnested-externs -Winline -Wno-long-long
+W += -Wconversion -Wstrict-prototypes
+WNO := -Wno-error=unused-parameter -Wno-error=unused-variable
+WNO += -Wno-error=unused-but-set-variable -Wno-error=unused-but-set-parameter
+WNO += -Wno-error=infinite-recursion
+
+CFLAGS = $(W) $(WNO) -fno-omit-frame-pointer
+CFLAGS += -MD -O3 -ffreestanding -nostdlib -std=gnu89
+CFLAGS += -fno-common -fno-stack-protector
+CFLAGS += -fno-pie -no-pie -fno-pic
+CFLAGS += -g -fsanitize=undefined
+#CFLAGS += -fstack-protector-all
+LDFLAGS = -z max-page-size=4096
+
+ifeq ($(ARCH), x86)
+ CFLAGS += -mgeneral-regs-only
+endif
+
+ifeq ($(ARCH), x86_64)
+ CFLAGS += -mcmodel=large
+ CFLAGS += -mgeneral-regs-only
+endif
+
+ifeq ($(ARCH), riscv64)
+ CFLAGS += -mcmodel=medany
+endif
+
+MAKE:=$(MAKE) -s
+
+all: $(TARGET)
+
+FORCE:
+
+src/kernel.bin: FORCE
+ cargo b $(CARGO_B) $(CARGO_FLAGS)
+ @rm -f src/kernel.bin
+ @$(MAKE) -C $(@D)
+
+isodir:
+ $(info [all] $@)
+ @mkdir -p isodir/boot/grub
+ @cp src/grub.cfg isodir/boot/grub/grub.cfg
+ @mkdir -p isodir/modules
+ @dd if=/dev/zero of=isodir/modules/ext2.img bs=4M count=2 > /dev/null 2>&1
+ @mkfs.ext2 isodir/modules/ext2.img > /dev/null 2>&1
+
+kernel.iso: src/kernel.bin src/grub.cfg Makefile isodir FORCE
+ $(info [all] $@)
+ @cp src/kernel.bin isodir/boot/kernel.bin
+ @sudo cp src/kernel.bin /srv/tftp/boot/kernel.bin
+ @grub-mkrescue -o kernel.iso isodir > /dev/null 2>&1
+
+
+.PHONY: all build qemu bochs mount umount clean
+
+BOCHS = bochs -q
+
+qemu: kernel.iso
+ $(QEMU) $(MACHINE) $(BOOT) $(QEMU_OPTS) $(QEMU_DEBUG)
+ @cat serial.log
+
+bochs: kernel.iso
+ @$(BOCHS) -qf .bochsrc
+ @cat serial.log
+
+mount: isodir
+ifeq ("$(wildcard /mnt/ext2/lost+found/)","")
+ $(info [all] $@)
+ @doas mount isodir/modules/ext2.img /mnt/ext2 -o loop
+ @doas chown -R aleksa:aleksa /mnt/ext2
+endif
+
+umount:
+ifneq ("$(wildcard /mnt/ext2/lost+found/)","")
+ $(info [all] $@)
+ @doas umount /mnt/ext2
+endif
+
+clean:
+ @find ./src/ -name "*.o" -exec rm {} \;
+ @find ./src/ -name "*.d" -exec rm {} \;
+ @rm -f kernel.iso src/kernel.bin xbochs.log bx_enh_dbg.ini log serial.log
+ @rm -rf isodir
+ @cargo clean
+ @$(MAKE) umount
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/README.md
diff --git a/arch/riscv64.json b/arch/riscv64.json
new file mode 100644
index 0000000..ea84208
--- /dev/null
+++ b/arch/riscv64.json
@@ -0,0 +1,15 @@
+{
+ "llvm-target": "riscv64-unknown-none-elf",
+ "data-layout": "e-m:e-p:64:64-i64:64-n32:64-S128",
+ "arch": "riscv64",
+ "target-endian": "little",
+ "target-pointer-width": "64",
+ "target-c-int-width": "32",
+ "os": "none",
+ "executables": true,
+ "linker-flavor": "ld.lld",
+ "linker": "rust-lld",
+ "panic-strategy": "abort",
+ "disable-redzone": true,
+ "features": "+m,+a,+c,+f,+d"
+}
diff --git a/arch/riscv64.ld b/arch/riscv64.ld
new file mode 100644
index 0000000..cad0f07
--- /dev/null
+++ b/arch/riscv64.ld
@@ -0,0 +1,25 @@
+ENTRY(start);
+
+. = 0x80200000;
+
+SECTIONS {
+ .text : ALIGN(4K) {
+ *(.init);
+ *(.text);
+ }
+ .bss : ALIGN(4K) {
+ PROVIDE(bss_start = .);
+ *(.bss);
+ . += 4096;
+ PROVIDE(stack_top = .);
+ . += 4096;
+ PROVIDE(global_pointer = .);
+ PROVIDE(bss_end = .);
+ }
+ .rodata : ALIGN(4K) {
+ *(.rodata);
+ }
+ .data : ALIGN(4K) {
+ *(.data);
+ }
+}
diff --git a/arch/x86.json b/arch/x86.json
new file mode 100644
index 0000000..9b558de
--- /dev/null
+++ b/arch/x86.json
@@ -0,0 +1,15 @@
+{
+ "llvm-target": "i686-unknown-none",
+ "data-layout": "e-m:e-p:32:32-i64:64-f80:32-n8:16:32-S128",
+ "arch": "x86",
+ "target-endian": "little",
+ "target-pointer-width": "32",
+ "target-c-int-width": "32",
+ "os": "none",
+ "executables": true,
+ "linker-flavor": "ld.lld",
+ "linker": "rust-lld",
+ "panic-strategy": "abort",
+ "disable-redzone": true,
+ "features": "-mmx,-sse,+soft-float"
+}
diff --git a/arch/x86.ld b/arch/x86.ld
new file mode 100644
index 0000000..440e513
--- /dev/null
+++ b/arch/x86.ld
@@ -0,0 +1,74 @@
+ENTRY (_start)
+
+KERNEL_PMA = 0x00100000;
+KERNEL_VMA = 0xC0000000;
+
+SECTIONS
+{
+ . = KERNEL_PMA;
+
+
+ .multiboot.data : {
+ *(.multiboot2.header)
+ *(.boot32.rodata)
+ }
+
+ .multiboot.text : {
+ *(.multiboot.text)
+ }
+
+ . += KERNEL_VMA;
+
+ .text ALIGN (4K) : AT (ADDR (.text) - KERNEL_VMA)
+ {
+ *(.text)
+ }
+
+ .got ALIGN (4K) : AT (ADDR (.got) - KERNEL_VMA)
+ {
+ *(.got)
+ }
+
+ .got.plt ALIGN (4K) : AT (ADDR (.got.plt) - KERNEL_VMA)
+ {
+ *(.got.plt)
+ }
+
+ .rodata ALIGN(4K) : AT (ADDR (.rodata) - KERNEL_VMA)
+ {
+ *(.rodata)
+ }
+
+ .data ALIGN (4K) : AT (ADDR (.data) - KERNEL_VMA)
+ {
+ *(.data)
+ }
+
+ .bss ALIGN (4K) : AT (ADDR (.bss) - KERNEL_VMA)
+ {
+ *(COMMON)
+ *(.bss)
+ *(.bootstrap_stack)
+ }
+
+ /DISCARD/ :
+ {
+ *(.debug_abbrev)
+ *(.debug_aranges)
+ *(.debug_frame)
+ *(.debug_gdb_scripts)
+ *(.debug_info)
+ *(.debug_line)
+ *(.debug_line_str)
+ *(.debug_loc)
+ *(.debug_pubnames)
+ *(.debug_pubtypes)
+ *(.debug_ranges)
+ *(.debug_str)
+
+ *(.comment)
+ *(.note.*)
+ }
+
+ _kernel_end = .;
+}
diff --git a/arch/x86_64.json b/arch/x86_64.json
new file mode 100644
index 0000000..23da62b
--- /dev/null
+++ b/arch/x86_64.json
@@ -0,0 +1,15 @@
+{
+ "llvm-target": "x86_64-unknown-none",
+ "data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
+ "arch": "x86_64",
+ "target-endian": "little",
+ "target-pointer-width": "64",
+ "target-c-int-width": "32",
+ "os": "none",
+ "executables": true,
+ "linker-flavor": "ld.lld",
+ "linker": "rust-lld",
+ "panic-strategy": "abort",
+ "disable-redzone": true,
+ "features": "-mmx,-sse,+soft-float"
+}
diff --git a/arch/x86_64.ld b/arch/x86_64.ld
new file mode 100644
index 0000000..da6663e
--- /dev/null
+++ b/arch/x86_64.ld
@@ -0,0 +1,81 @@
+ENTRY(_start)
+
+KERNEL_AP_PMA = 0x0000000000008000;
+KERNEL_PMA = 0x0000000000100000;
+KERNEL_VMA = 0xffffffff80000000;
+
+SECTIONS
+{
+ /*
+ . = KERNEL_AP_PMA;
+
+ .apinit BLOCK(4K) : ALIGN(4K)
+ {
+ *(.apinit)
+ }
+ */
+
+ . = KERNEL_PMA;
+
+ .boot BLOCK(4K) : ALIGN(4K)
+ {
+ KEEP(*(.multiboot2.header))
+ *(.boot32.text)
+ *(.boot32.rodata)
+ *(.boot32.bss)
+ *(.boot64.text)
+ }
+
+ . += KERNEL_VMA;
+
+ .text ALIGN(4K) : AT (ADDR (.text) - KERNEL_VMA)
+ {
+ *(.text)
+ }
+
+ .rodata ALIGN(4K) : AT (ADDR (.rodata) - KERNEL_VMA)
+ {
+ *(.rodata)
+ }
+
+ .rodata. ALIGN(4K) : AT (ADDR (.rodata.) - KERNEL_VMA)
+ {
+ *(.rodata.*)
+ }
+
+ .data ALIGN(4K) : AT (ADDR (.data) - KERNEL_VMA)
+ {
+ *(.data)
+ }
+
+ .bss ALIGN(4K) : AT (ADDR (.bss) - KERNEL_VMA)
+ {
+ *(.bss)
+ }
+
+ .bss. ALIGN(4K) : AT (ADDR (.bss.) - KERNEL_VMA)
+ {
+ *(.bss.*)
+ }
+
+ /DISCARD/ :
+ {
+ *(.debug_abbrev)
+ *(.debug_aranges)
+ *(.debug_frame)
+ *(.debug_gdb_scripts)
+ *(.debug_info)
+ *(.debug_line)
+ *(.debug_line_str)
+ *(.debug_loc)
+ *(.debug_pubnames)
+ *(.debug_pubtypes)
+ *(.debug_ranges)
+ *(.debug_str)
+
+ *(.comment)
+ *(.note.*)
+ }
+
+ _kernel_end = .;
+}
diff --git a/riscv64-uboot.sh b/riscv64-uboot.sh
new file mode 100755
index 0000000..7055608
--- /dev/null
+++ b/riscv64-uboot.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+qemu-system-riscv64 -machine virt -kernel /usr/share/qemu/u-boot-riscv64.bin -device loader,file=./src/kernel.bin,addr=0x80200000 -nographic -serial mon:stdio
diff --git a/src/Makefile b/src/Makefile
new file mode 100644
index 0000000..d5c03fb
--- /dev/null
+++ b/src/Makefile
@@ -0,0 +1,18 @@
+CFLAGS += -I include
+
+ASM_OBJS := $(foreach path, $(ASM_PATHS), $(patsubst %.S, %.o, $(wildcard $(path)/*.S)))
+
+OBJS = \
+ $(ASM_OBJS) \
+ $(RUST_OBJS)
+
+kernel.bin: $(OBJS) $(LD_SCRIPT) ../Makefile Makefile
+ $(info [kernel] $@)
+ @$(LD) $(LDFLAGS) -T $(LD_SCRIPT) $(OBJS) -o kernel.bin
+
+%.o: %.S
+ $(info [kernel] $@)
+ @$(CC) $(CFLAGS) -c $< -o $@
+
+
+.PHONY: all
diff --git a/src/arch/mod.rs b/src/arch/mod.rs
new file mode 100644
index 0000000..5735bed
--- /dev/null
+++ b/src/arch/mod.rs
@@ -0,0 +1,14 @@
+#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+mod x86;
+#[cfg(target_arch = "x86")]
+pub use x86::*;
+
+#[cfg(target_arch = "x86_64")]
+mod x86_64;
+#[cfg(target_arch = "x86_64")]
+pub use x86_64::*;
+
+#[cfg(target_arch = "riscv64")]
+mod riscv64;
+#[cfg(target_arch = "riscv64")]
+pub use riscv64::*;
diff --git a/src/arch/riscv64/boot/entry.S b/src/arch/riscv64/boot/entry.S
new file mode 100644
index 0000000..f5fa092
--- /dev/null
+++ b/src/arch/riscv64/boot/entry.S
@@ -0,0 +1,37 @@
+.section .init
+
+.option norvc
+
+.type start, @function
+.global start
+start:
+ .cfi_startproc
+
+.option push
+.option norelax
+ la gp, global_pointer
+.option pop
+
+ /* Reset satp */
+ csrw satp, zero
+
+ /* Setup stack */
+ la sp, stack_top
+
+ /* Clear the BSS section */
+ la t5, bss_start
+ la t6, bss_end
+bss_clear:
+ sd zero, (t5)
+ addi t5, t5, 8
+ bltu t5, t6, bss_clear
+
+ la t0, kernel_main
+ csrw sepc, t0
+
+ /* Jump to kernel! */
+ tail kernel_main
+
+ .cfi_endproc
+
+.end
diff --git a/src/arch/riscv64/io/mod.rs b/src/arch/riscv64/io/mod.rs
new file mode 100644
index 0000000..6d91cab
--- /dev/null
+++ b/src/arch/riscv64/io/mod.rs
@@ -0,0 +1,2 @@
+mod uart;
+pub use uart::*;
diff --git a/src/arch/riscv64/io/uart.rs b/src/arch/riscv64/io/uart.rs
new file mode 100644
index 0000000..7aafeef
--- /dev/null
+++ b/src/arch/riscv64/io/uart.rs
@@ -0,0 +1,27 @@
+use core::fmt;
+use core::fmt::Write;
+
+pub fn _print(args: fmt::Arguments) {
+ // Not thread safe but no dependencies
+ let mut stdout = Stdout;
+ fmt::write(&mut stdout, args);
+}
+
+struct Stdout;
+impl Write for Stdout {
+ fn write_str(&mut self, s: &str) -> fmt::Result {
+ print_string(s);
+ Ok(())
+ }
+}
+
+pub fn print_string(s: &str) {
+ let uart_base = 0x10000000 as *mut u8;
+ while unsafe { uart_base.add(5).read_volatile() } & 0x20 == 0 {}
+
+ for c in s.chars() {
+ unsafe {
+ uart_base.write_volatile(c as u8);
+ }
+ }
+}
diff --git a/src/arch/riscv64/mod.rs b/src/arch/riscv64/mod.rs
new file mode 100644
index 0000000..608d4e1
--- /dev/null
+++ b/src/arch/riscv64/mod.rs
@@ -0,0 +1,2 @@
+mod io;
+pub use io::*;
diff --git a/src/arch/x86/boot/boot.S b/src/arch/x86/boot/boot.S
new file mode 100644
index 0000000..02f6e91
--- /dev/null
+++ b/src/arch/x86/boot/boot.S
@@ -0,0 +1,126 @@
+.section .bootstrap_stack, "aw", @nobits
+stack_bottom:
+.skip 16384
+stack_top:
+
+.section .bss, "aw", @nobits
+ .align 4096
+page_directory:
+ .skip 4096
+page_table1:
+ .skip 4096
+page_table2:
+ .skip 4096
+
+
+.set P, 1<<0
+.set RW, 1<<1
+.set FLAGS, P | RW
+.set KERNEL_VM, 0xC0000000
+
+
+.section .multiboot.text, "a"
+.global _start
+.type _start, @function
+_start:
+_start:
+ cli
+ mov $stack_top - KERNEL_VM, %esp
+ pushl %eax
+ pushl %ebx
+
+ movl $page_table1 - KERNEL_VM + FLAGS, page_directory - KERNEL_VM + 0 * 4
+ movl $page_table2 - KERNEL_VM + FLAGS, page_directory - KERNEL_VM + 1 * 4
+ movl $page_table1 - KERNEL_VM + FLAGS, page_directory - KERNEL_VM + 768 * 4
+ movl $page_table2 - KERNEL_VM + FLAGS, page_directory - KERNEL_VM + 769 * 4
+
+ mov $0, %ecx
+not_done:
+ mov $0x1000, %eax
+ mul %ecx
+ orl $FLAGS, %eax
+ mov %eax, %edi
+
+ // page_table1[%ecx] = 0x1000 * %ecx | 0x3
+ mov $4, %eax
+ mul %ecx
+ add $page_table1 - KERNEL_VM, %eax
+ movl %edi, (%eax)
+
+ // page_table2[%ecx] = 0x1000 * %ecx | 0x3
+ mov $4, %eax
+ mul %ecx
+ add $1024 * 0x1000, %edi
+ add $page_table2 - KERNEL_VM, %eax
+ movl %edi, (%eax)
+
+ inc %ecx
+ cmp $1024, %ecx
+ je done
+ jmp not_done
+done:
+
+ movl $(page_directory - KERNEL_VM), %ecx
+ movl %ecx, %cr3
+
+ movl %cr0, %ecx
+ orl $0x80001000, %ecx
+ movl %ecx, %cr0
+
+ lea 7f, %ecx
+ jmp *%ecx
+
+
+.section .boot32.rodata
+
+gdt:
+gdt_null = . - gdt
+ .quad 0
+kernel_code = . - gdt
+ .long 0xFFFF
+ .byte 0
+ .byte 0x9A
+ .byte 0xCF
+ .byte 0
+kernel_data = . - gdt
+ .long 0xFFFF
+ .byte 0
+ .byte 0x92
+ .byte 0xCF
+ .byte 0
+user_code = . - gdt
+ .long 0xFFFF
+ .byte 0
+ .byte 0xFA
+ .byte 0xCF
+ .byte 0
+user_data = . - gdt
+ .long 0xFFFF
+ .byte 0
+ .byte 0xF2
+ .byte 0xCF
+ .byte 0
+
+.global gdtp
+gdtp:
+ .word . - gdt - 1
+ .long gdt
+
+
+.section .text
+
+7:
+ addl $KERNEL_VM, %esp
+ lgdtl gdtp
+ ljmp $0x08, $code
+
+code:
+ movw $0x10, %ax
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %fs
+ movw %ax, %gs
+ movw %ax, %ss
+
+ call kernel_main
+ hlt
diff --git a/src/arch/x86/common/boot/mod.rs b/src/arch/x86/common/boot/mod.rs
new file mode 100644
index 0000000..b6aebe5
--- /dev/null
+++ b/src/arch/x86/common/boot/mod.rs
@@ -0,0 +1,2 @@
+mod multiboot;
+pub use multiboot::*;
diff --git a/src/arch/x86/common/boot/multiboot.S b/src/arch/x86/common/boot/multiboot.S
new file mode 100644
index 0000000..8773b1f
--- /dev/null
+++ b/src/arch/x86/common/boot/multiboot.S
@@ -0,0 +1,11 @@
+.set ALIGN, 1<<0
+.set MEMINFO, 1<<1
+.set FLAGS, ALIGN | MEMINFO
+.set MAGIC, 0x1BADB002
+.set CHECKSUM, -(MAGIC + FLAGS)
+
+.section .multiboot.header, "aw"
+.align 4
+.long MAGIC
+.long FLAGS
+.long CHECKSUM
diff --git a/src/arch/x86/common/boot/multiboot.rs b/src/arch/x86/common/boot/multiboot.rs
new file mode 100644
index 0000000..09789ce
--- /dev/null
+++ b/src/arch/x86/common/boot/multiboot.rs
@@ -0,0 +1,79 @@
+pub const MULTIBOOT2_BOOTLOADER_MAGIC: u32 = 0x36d76289;
+pub const MULTIBOOT_TAG_TYPE_END: u32 = 0;
+pub const MULTIBOOT_TAG_TYPE_MMAP: u32 = 6;
+pub const MULTIBOOT_TAG_TYPE_FB: u32 = 8;
+
+use crate::{print, println};
+
+pub fn parse_fb_multiboot(mut mem: *mut u32) {
+ let framebuffer_addr: u64 = unsafe { *(mem as *mut u64) };
+ let framebuffer_pitch: u32 = unsafe { *mem.wrapping_add(2) };
+ let framebuffer_width: u32 = unsafe { *mem.wrapping_add(3) };
+ let framebuffer_height: u32 = unsafe { *mem.wrapping_add(4) };
+ let framebuffer_bpp: u8 = unsafe { *(mem.wrapping_add(5) as *mut u8) };
+ let framebuffer_type: u8 = unsafe { *(mem.wrapping_add(5) as *mut u8).wrapping_add(1) };
+ let reserved: u8 = unsafe { *(mem.wrapping_add(5) as *mut u8).wrapping_add(1) };
+
+ println!(
+ "0x{:x} {:x} {:x} {:x}",
+ framebuffer_addr, framebuffer_pitch, framebuffer_width, framebuffer_height
+ );
+}
+
+pub fn parse_mem_multiboot(mut mem: *mut u32, _size: u32) {
+ let mut curr_size: u32 = 16;
+
+ while curr_size < _size {
+ let base_addr: u64 = unsafe { *(mem as *mut u64) };
+ let length: u64 = unsafe { *(mem.wrapping_add(2) as *mut u64) };
+ let _type: u32 = unsafe { *mem.wrapping_add(4) };
+ let reserved: u32 = unsafe { *mem.wrapping_add(5) };
+ assert_eq!(reserved, 0, "reserved not 0");
+
+ //println!("{:x} {:x} {:x}", base_addr, length, _type);
+
+ mem = mem.wrapping_add(6);
+ curr_size += 24;
+ }
+}
+
+pub fn parse_multiboot(mut multiboot_bootinfo: *mut u32, multiboot_magic: u32) {
+ assert_eq!(
+ multiboot_magic, MULTIBOOT2_BOOTLOADER_MAGIC,
+ "MULTIBOOT2_BOOTLOADER_MAGIC"
+ );
+
+ let total_size: u32 = unsafe { *multiboot_bootinfo };
+ let mut size = 8;
+ multiboot_bootinfo = multiboot_bootinfo.wrapping_add(2);
+
+ while size < total_size {
+ let _type: u32 = unsafe { *multiboot_bootinfo };
+ let _size: u32 = unsafe { *(multiboot_bootinfo.wrapping_add(1)) };
+ let mem: *mut u32 = multiboot_bootinfo.wrapping_add(4);
+ let mem2: *mut u32 = multiboot_bootinfo.wrapping_add(2);
+
+ match _type {
+ MULTIBOOT_TAG_TYPE_FB => {
+ parse_fb_multiboot(mem2);
+ }
+ MULTIBOOT_TAG_TYPE_MMAP => {
+ parse_mem_multiboot(mem, _size);
+ }
+ _ => {}
+ }
+
+ let inc_size = (_size / 8 + (_size % 8 != 0) as u32) * 8;
+ size += inc_size;
+
+ println!("{} {} {}", _type, _size, inc_size);
+ multiboot_bootinfo = multiboot_bootinfo.wrapping_add((inc_size / 4).try_into().unwrap());
+
+ if _type == MULTIBOOT_TAG_TYPE_END {
+ assert_eq!(_size, 8, "MULTIBOOT_TAG_TYPE_END");
+ break;
+ }
+ }
+
+ assert_eq!(total_size, size, "Multiboot");
+}
diff --git a/src/arch/x86/common/boot/multiboot2.S b/src/arch/x86/common/boot/multiboot2.S
new file mode 100644
index 0000000..d767ca0
--- /dev/null
+++ b/src/arch/x86/common/boot/multiboot2.S
@@ -0,0 +1,42 @@
+/* multiboot tags */
+.set TAG_END, 0
+.set TAG_FRAMEBUFFER, 5
+
+/* multiboot flags */
+.set TAG_REQUIRED, 0
+.set TAG_OPTIONAL, 1
+
+/* multiboot2 header constants */
+.set MAGIC, 0xe85250d6
+.set ARCH, 0
+.set HEADER_LENGTH, (header_end - header_start)
+.set CHECKSUM, 0x100000000 - (MAGIC + ARCH + HEADER_LENGTH)
+
+.section .multiboot2.header, "a"
+.align 4
+header_start:
+ /* magic */
+ .align 8
+ .long MAGIC
+ .long ARCH
+ .long HEADER_LENGTH
+ .long CHECKSUM
+
+/*
+ // framebuffer
+ .align 8
+ .word TAG_FRAMEBUFFER
+ .word TAG_REQUIRED
+ .long 20
+ .long 1024
+ .long 768
+ .long 32
+*/
+
+ /* end tag */
+ .align 8
+ .word TAG_END
+ .word TAG_REQUIRED
+ .long 8
+
+header_end:
diff --git a/src/arch/x86/common/forall.rs b/src/arch/x86/common/forall.rs
new file mode 100644
index 0000000..39988e6
--- /dev/null
+++ b/src/arch/x86/common/forall.rs
@@ -0,0 +1,5 @@
+use crate::{print, println};
+
+pub fn forall() {
+ println!("forall");
+}
diff --git a/src/arch/x86/common/io/mod.rs b/src/arch/x86/common/io/mod.rs
new file mode 100644
index 0000000..604e84c
--- /dev/null
+++ b/src/arch/x86/common/io/mod.rs
@@ -0,0 +1,2 @@
+mod writer;
+pub use writer::*;
diff --git a/src/arch/x86/common/io/writer.rs b/src/arch/x86/common/io/writer.rs
new file mode 100644
index 0000000..7361693
--- /dev/null
+++ b/src/arch/x86/common/io/writer.rs
@@ -0,0 +1,72 @@
+use core::fmt;
+use core::fmt::Write;
+use lazy_static::lazy_static;
+use spin::Mutex;
+
+#[doc(hidden)]
+pub fn _print(args: fmt::Arguments) {
+ WRITER.lock().write_fmt(args).unwrap();
+}
+
+lazy_static! {
+ pub static ref WRITER: Mutex<Writer> = Mutex::new(Writer::new());
+}
+
+#[derive(Default)]
+pub struct Writer {
+ max_y: isize,
+ max_x: isize,
+ x: isize,
+ y: isize,
+ addr: u32,
+}
+
+impl Writer {
+ pub fn new() -> Self {
+ Self {
+ x: 0,
+ y: 0,
+ max_y: 25,
+ max_x: 80,
+ addr: 0xb8000,
+ }
+ }
+
+ pub fn write(&mut self, c: char, b: u8) {
+ let off: isize = self.y * self.max_x + self.x;
+ let vga_buffer = self.addr as *mut u8;
+
+ if c != '\n' {
+ unsafe {
+ *vga_buffer.offset(2 * off) = c as u8;
+ *vga_buffer.offset(2 * off + 1) = b;
+ }
+ self.x += 1;
+ } else {
+ self.x = 0;
+ self.y += 1;
+ }
+
+ if self.x >= self.max_x {
+ self.x = 0;
+ self.y += 1;
+ }
+
+ if self.y >= self.max_y {
+ self.y = 0;
+ }
+ }
+
+ pub fn print(&mut self, s: &str, b: u8) {
+ for i in s.chars() {
+ self.write(i, b);
+ }
+ }
+}
+
+impl fmt::Write for Writer {
+ fn write_str(&mut self, s: &str) -> fmt::Result {
+ self.print(s, 0xb);
+ Ok(())
+ }
+}
diff --git a/src/arch/x86/common/mod.rs b/src/arch/x86/common/mod.rs
new file mode 100644
index 0000000..d1d4d98
--- /dev/null
+++ b/src/arch/x86/common/mod.rs
@@ -0,0 +1,8 @@
+mod forall;
+pub use forall::*;
+
+mod io;
+pub use io::*;
+
+mod boot;
+pub use boot::*;
diff --git a/src/arch/x86/mod.rs b/src/arch/x86/mod.rs
new file mode 100644
index 0000000..c47ad74
--- /dev/null
+++ b/src/arch/x86/mod.rs
@@ -0,0 +1,10 @@
+#[cfg(target_arch = "x86")]
+mod common;
+#[cfg(target_arch = "x86")]
+pub use common::*;
+
+#[cfg(target_arch = "x86_64")]
+pub mod common;
+
+mod once;
+pub use once::*;
diff --git a/src/arch/x86/once.rs b/src/arch/x86/once.rs
new file mode 100644
index 0000000..9397afb
--- /dev/null
+++ b/src/arch/x86/once.rs
@@ -0,0 +1,6 @@
+use crate::{print, println};
+
+pub fn once()
+{
+ println!("x86");
+}
diff --git a/src/arch/x86_64/boot/boot.S b/src/arch/x86_64/boot/boot.S
new file mode 100644
index 0000000..1dc2320
--- /dev/null
+++ b/src/arch/x86_64/boot/boot.S
@@ -0,0 +1,128 @@
+.code32
+.extern begin_long_mode
+
+.section .boot32.text, "a"
+
+.set STACK_TOP, 0x03008000
+
+.global _start
+_start:
+ cli
+ mov $STACK_TOP, %esp
+ pushl $0
+ pushl %eax
+ pushl $0
+ pushl %ebx
+
+ call setup_page_tables
+ call enable_paging
+
+ lgdt gdtp
+ ljmp $0x08, $begin_long_mode
+
+setup_page_tables:
+/* first 2mb */
+ mov $pt_lvl3, %eax
+ or $0x3, %eax
+ mov %eax, pt_lvl4
+
+ mov $pt_lvl2, %eax
+ or $0x3, %eax
+ mov %eax, pt_lvl3
+
+ xor %ecx, %ecx
+1:
+ movl $0x00200000, %eax
+ mul %ecx
+ or $0b10000011, %eax
+ movl $pt_lvl2, %edx
+ leal (%edx, %ecx, 8), %edx
+ movl %eax, (%edx)
+ inc %ecx
+ cmp $25, %ecx
+ jne 1b
+
+/* first 2mb in hh */
+ mov $pt_lvl3_hh, %eax
+ or $0x3, %eax
+ mov %eax, pt_lvl4 + 4096 - 8
+
+ mov $pt_lvl2_hh, %eax
+ or $0x3, %eax
+ mov %eax, pt_lvl3_hh + 4096 - 16
+
+ xor %ecx, %ecx
+2:
+ movl $0x00200000, %eax
+ mul %ecx
+ or $0b10000011, %eax
+ movl $pt_lvl2_hh, %edx
+ leal (%edx, %ecx, 8), %edx
+ movl %eax, (%edx)
+ inc %ecx
+ cmp $25, %ecx
+ jne 2b
+
+ ret
+
+.global enable_paging
+enable_paging:
+ /* enable PAE */
+ mov %cr4, %edx
+ or $1<<5 ,%edx
+ mov %edx, %cr4
+
+ /* set LME (long mode enable) */
+ mov $0xC0000080, %ecx
+ rdmsr
+ or $1<<8, %eax
+ wrmsr
+
+ /* pt_lvl4 */
+ mov $pt_lvl4, %eax
+ mov %eax, %cr3
+
+ /* enable paging (+ protected mode if not already enabled) */
+ mov %cr0, %eax
+ or $1<<31 + 1<<0, %eax
+ mov %eax, %cr0
+
+ ret
+
+
+.section .boot32.rodata
+
+gdt:
+gdt_null = . - gdt
+ .quad 0
+gdt_code = . - gdt
+ .long 0xFFFF
+ .byte 0
+ .byte 0x9A
+ .byte 0xAF
+ .byte 0
+gdt_data = . - gdt
+ .long 0xFFFF
+ .byte 0
+ .byte 0x92
+ .byte 0xAF
+ .byte 0
+.global gdtp
+gdtp:
+ .word . - gdt - 1
+ .quad gdt
+
+
+.section .boot32.bss
+.align 4096
+
+pt_lvl4:
+ .skip 4096
+pt_lvl3:
+ .skip 4096
+pt_lvl3_hh:
+ .skip 4096
+pt_lvl2:
+ .skip 4096
+pt_lvl2_hh:
+ .skip 4096
diff --git a/src/arch/x86_64/boot/boot64.S b/src/arch/x86_64/boot/boot64.S
new file mode 100644
index 0000000..848256f
--- /dev/null
+++ b/src/arch/x86_64/boot/boot64.S
@@ -0,0 +1,26 @@
+.code64
+
+.set KERNEL_VMA, 0xffffffff80000000
+.set GDT_KERNEL_CS, 0x10
+
+.section .boot64.text, "a"
+
+.global begin_long_mode
+begin_long_mode:
+ mov $GDT_KERNEL_CS, %ax
+ mov %ax, %ds
+ mov %ax, %es
+ mov %ax, %ss
+ mov %ax, %fs
+ mov %ax, %gs
+
+ add $KERNEL_VMA, %rsp
+ movabs $jump_main, %rax
+ jmp *%rax
+
+.section .text
+jump_main:
+ popq %rdi
+ popq %rsi
+ call kernel_main
+ hlt
diff --git a/src/arch/x86_64/mod.rs b/src/arch/x86_64/mod.rs
new file mode 100644
index 0000000..a5f019b
--- /dev/null
+++ b/src/arch/x86_64/mod.rs
@@ -0,0 +1,4 @@
+pub use crate::arch::x86::common::*;
+
+mod once;
+pub use once::*;
diff --git a/src/arch/x86_64/once.rs b/src/arch/x86_64/once.rs
new file mode 100644
index 0000000..8aebbcb
--- /dev/null
+++ b/src/arch/x86_64/once.rs
@@ -0,0 +1,6 @@
+use crate::{print, println};
+
+pub fn once()
+{
+ println!("x86_64");
+}
diff --git a/src/grub.cfg b/src/grub.cfg
new file mode 100644
index 0000000..95df700
--- /dev/null
+++ b/src/grub.cfg
@@ -0,0 +1,7 @@
+set timeout=0
+set default=0
+
+insmod efi_gop
+menuentry "myrustkernel" {
+ multiboot2 /boot/kernel.bin
+}
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000..26dc19d
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1,39 @@
+#![no_std]
+#![no_main]
+
+use core::panic::PanicInfo;
+pub mod arch;
+
+#[macro_export]
+macro_rules! print {
+ ($($arg:tt)*) => ($crate::arch::_print(format_args!($($arg)*)));
+}
+
+#[macro_export]
+macro_rules! println {
+ () => (print!("\n"));
+ ($($arg:tt)*) => (print!("{}\n", format_args!($($arg)*)));
+}
+
+#[panic_handler]
+fn panic(info: &PanicInfo) -> ! {
+ println!("{}", info);
+ loop {}
+}
+
+#[no_mangle]
+//pub extern "C" fn kernel_main(multiboot_bootinfo: *mut u32, multiboot_magic: u32) -> ! {
+pub extern "C" fn kernel_main() -> ! {
+ //arch::parse_multiboot(multiboot_bootinfo, multiboot_magic);
+ //arch::forall();
+ //arch::once();
+
+ let mut x = 10;
+ for i in 0..100 {
+ x += i;
+ }
+
+ println!("Hello World! {}", x);
+
+ loop {}
+}
diff --git a/tftp/dnsmasq.conf b/tftp/dnsmasq.conf
new file mode 100644
index 0000000..01a1782
--- /dev/null
+++ b/tftp/dnsmasq.conf
@@ -0,0 +1,20 @@
+interface=enp7s0
+bind-interfaces
+domain=example.org
+dhcp-option=3,0.0.0.0
+dhcp-option=6,0.0.0.0
+dhcp-option=121,192.168.111.0/24,192.168.111.1
+dhcp-range=192.168.111.50,192.168.111.100,5m
+dhcp-range=::f,::ff,constructor:enp7s0
+dhcp-host=30:85:a9:88:61:0e,192.168.111.69
+
+enable-tftp
+tftp-root=/srv/tftp
+
+dhcp-match=set:efi-x86_64,option:client-arch,7
+dhcp-match=set:efi-x86_64,option:client-arch,9
+dhcp-match=set:efi-x86,option:client-arch,6
+dhcp-match=set:bios,option:client-arch,0
+dhcp-boot=tag:efi-x86_64,boot/grub/x86_64-efi/core.efi
+dhcp-boot=tag:efi-x86,boot/grub/i386-efi/core.efi
+dhcp-boot=tag:bios,boot/grub/i386-pc/core.0
diff --git a/tftp/dnsmasq.service b/tftp/dnsmasq.service
new file mode 100644
index 0000000..c30c334
--- /dev/null
+++ b/tftp/dnsmasq.service
@@ -0,0 +1,20 @@
+[Unit]
+Description=dnsmasq - A lightweight DHCP and caching DNS server
+Documentation=man:dnsmasq(8)
+After=network.target
+Before=network-online.target nss-lookup.target
+Wants=nss-lookup.target
+
+[Service]
+Type=dbus
+BusName=uk.org.thekelleys.dnsmasq
+ExecStartPre=/usr/bin/dnsmasq --test
+ExecStartPre=/home/aleksa/mygit/myrustkernel/tftp/setup.sh
+ExecStart=/usr/bin/dnsmasq -k --enable-dbus --user=dnsmasq --pid-file
+ExecReload=/bin/kill -HUP $MAINPID
+Restart=on-failure
+PrivateDevices=true
+ProtectSystem=full
+
+[Install]
+WantedBy=multi-user.target
diff --git a/tftp/setup.sh b/tftp/setup.sh
new file mode 100755
index 0000000..7e1737c
--- /dev/null
+++ b/tftp/setup.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+INTERFACE="enp7s0"
+IP_ADDRESS="192.168.111.1/24"
+
+if ! ip addr show dev $INTERFACE | grep -q "$IP_ADDRESS"; then
+ sudo nmcli dev set $INTERFACE managed no
+ sudo ip link set $INTERFACE up
+ sudo ip addr add $IP_ADDRESS dev $INTERFACE
+ sudo systemctl restart dnsmasq
+ echo "Configuration applied successfully."
+else
+ echo "IP address $IP_ADDRESS is already assigned to $INTERFACE."
+ echo "No changes made."
+fi