Skip to content
This repository has been archived by the owner on Feb 5, 2021. It is now read-only.

Commit

Permalink
Initial rewritten committ
Browse files Browse the repository at this point in the history
  • Loading branch information
Proximyst committed Sep 24, 2018
0 parents commit 250e180
Show file tree
Hide file tree
Showing 25 changed files with 1,455 additions and 0 deletions.
662 changes: 662 additions & 0 deletions LICENCE

Large diffs are not rendered by default.

32 changes: 32 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# beeOS

## Why?

Why not?

## What does it do?

Well, have you ever wanted some computer which just prints the bee movie script?
Now you have the possibility to.

## How do I compile it?

Glad you asked! First, you need some tools:

- nasm
- nightly rust (the one as of September 24th 2018 works fine)
- xargo (cargo install xargo)
- make
- grub-mkrescue (bundled with GRUB2)
- probably an x86_64 system to compile on, that's what I used

How:

```bash
$ cd rust/beeos/
$ RUST_TARGET_PATH=$(pwd) xargo build --release --target x86_64-beeos
$ cd ../../asm
$ make build
# want to run it with qemu-system-x86_64?
$ make run
```
1 change: 1 addition & 0 deletions asm/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
build/
47 changes: 47 additions & 0 deletions asm/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
arch ?= x86_64
rust_target ?= $(arch)-beeos
build_dir := build/$(arch)
src_dir := src/arch/$(arch)
grub_cfg := src/iso/boot/grub/grub.cfg
asm_src := $(wildcard $(src_dir)/*.asm)
asm_obj := $(patsubst $(src_dir)/%.asm, $(build_dir)/%.o, $(asm_src))
kernel := $(build_dir)/iso/boot/kernel.bin
linker := $(src_dir)/link.ld
rust_interface := ../rust/beeos/target/$(arch)-beeos/release/libbeeos.a
iso := $(build_dir)/beeOS-$(arch).iso

.PHONY: build
build: $(build_dir) $(asm_obj) $(kernel)
mkdir -p $(build_dir)/iso/boot/grub
cp $(grub_cfg) $(build_dir)/iso/boot/grub

.PHONY: clean
clean:
rm -rf build

$(build_dir):
mkdir -p $(build_dir)
cp -r src/iso $(build_dir)/iso

$(build_dir)/%.o: $(src_dir)/%.asm
mkdir -p $(build_dir)
nasm -felf64 $< -o $@

$(rust_interface):

.PHONY: kernel
kernel: $(kernel)

$(kernel): $(rust_interface) $(build_dir) $(asm_obj) $(linker) $(wildcard ../rust/beeos/src/*.rs)
cd ../rust/beeos && RUST_TARGET_PATH=./ xargo build --release --target x86_64-beeos
$(LD) -n -o $(kernel) -T $(linker) $(asm_obj) $(rust_interface)

.PHONY: iso
iso: $(iso)

$(iso): $(kernel) $(grub_cfg)
grub-mkrescue -o $(iso) $(build_dir)/iso

.PHONY: run
run: iso
qemu-system-x86_64 -cdrom $(iso)
53 changes: 53 additions & 0 deletions asm/src/arch/x86_64/boot.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
global start

section .text
bits 32
;; DESCRIPTION:
;; Starts the kernel and initialises all parts needed.
;; It may at any point error, though it shouldn't on a supported system (x86_64, CPUID supported, long mode, and pages work).
;;
;; If this errors, it will halt the CPU.
;;
;; LINKS:
;; `stack.asm` for `stack_top`, `setup_page_tables`, and `enable_paging`
;; `gdt.asm` for `gdt64`
;; `longmode_check.asm` for `check_long_mode`
;; `longmode_initialise` for `long_mode_start`
;; `cpuid_check.asm` for `check_cpuid`
;; `error.asm` for `error`
start:
;; Create a stack
extern stack_top
mov esp, stack_top

;; Declare `error` for all users
extern error

;; Verify that this was executed through multiboot2
extern check_multiboot
call check_multiboot

;; Verify that the `cpuid` instruction is available
extern check_cpuid
call check_cpuid

;; Verify that longmode exists
extern check_long_mode
call check_long_mode

;; Setup CPU memory paging
extern setup_page_tables
call setup_page_tables

;; Enable the paging
extern enable_paging
call enable_paging

;; Load the GDT
extern gdt64.pointer
lgdt [gdt64.pointer]

;; Move to a 64-bit code segment
extern long_mode_start
extern gdt64.code_segment
jmp gdt64.code_segment:long_mode_start
39 changes: 39 additions & 0 deletions asm/src/arch/x86_64/cpuid_check.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
global check_cpuid

section .text
bits 32
;; DESCRIPTION:
;; Checks for if the CPUID instruction is available on the system.
;;
;; If the instruction is unavailable, it will jump to $.cpuid_absent.
;; If it's present, it will `ret`.
check_cpuid:
pushfd ; Push flags to stack
pop eax ; Pop stack to eax

mov ecx, eax ; Copy eax to ecx for later cmp

xor eax, 1 << 21 ; Flip the 21st bit (CPUID bit)

push eax ; Push back to stack
popfd ; Return the flags back to CPU

pushfd ; Get the flags back
pop eax ; Pop the flags to eax, it shouldn't be ecx

push ecx ; Restore ecx
popfd ; Flip the bit back if it was flipped

cmp eax, ecx ; Check if the flags changed when getting back
je .cpuid_absent ; Halt if the bit wasn't flipped
ret ; Return if it was

;; DESCRIPTION:
;; Halts the CPU with the error code "1".
;;
;; LINKS:
;; `error.asm` for `error`
.cpuid_absent:
mov al, "1" ; Move error "1" to `al`
extern error ; Declare `error` for linking to `error.asm`
jmp error ; Jump to `error` for halting
21 changes: 21 additions & 0 deletions asm/src/arch/x86_64/error.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
global error

section .text
bits 32
;; DESCRIPTION:
;; Prints "ERR: " to the screen together with the error code in `al`.
;; The text is all white on a red background.
;;
;; This halts the CPU.
;;
;; VARIABLES:
;; `al` - Error code in a single byte.
error:
;; 0x4f = red background on white text
mov dword [0xb8000], 0x4f524f45 ; "R" then "E" (little endian) - white text, red background
mov dword [0xb8004], 0x4f3a4f52 ; ":" then "R" (little endian) - white text, red background
mov dword [0xb8008], 0x4f204f20 ; " " then " " (little endian) - white text, red background
;; Write `al` to the byte right after the first space shown.
;; The other space is still red and white, making this byte red and white.
mov byte [0xb800a], al
hlt ; Halt the CPU
18 changes: 18 additions & 0 deletions asm/src/arch/x86_64/gdt.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
global gdt64
global gdt64.code_segment
global gdt64.pointer

section .rodata
bits 32
;; DESCRIPTION:
;; This is a GDT table. Code should be executed in the gdt64.code_segment block.
;; The top is at gdt64.pointer.
;;
;; I have no idea how this actually works, but it does, so let's leave it at that.
gdt64:
dq 0
.code_segment: equ $ - gdt64
dq (1 << 43) | (1 << 44) | (1 << 47) | (1 << 53)
.pointer:
dw $ - gdt64 - 1
dq gdt64
19 changes: 19 additions & 0 deletions asm/src/arch/x86_64/link.ld
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
ENTRY(start)

SECTIONS
{
/* Load in the first megabyte of RAM */
. = 1M;

/* Ensure the header is first */
.boot : {
/* KEEP is used due to making sure that it won't be removed if
the optimiser is used to remove unused symbols */
KEEP(*(.multiboot_header))
}

/* Actually link the .text section, and that before initialised memory is */
.text : {
*(.text)
}
}
33 changes: 33 additions & 0 deletions asm/src/arch/x86_64/longmode_check.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
global check_long_mode

section .text
bits 32
;; DESCRIPTION:
;; Checks if the CPU has support for long mode.
;;
;; If it doesn't, jump to .long_mode_absent.
;; If it does, return to stack.
;;
;; REFERENCES:
;; https://en.wikipedia.org/wiki/CPUID#EAX.3D80000001h:_Extended_Processor_Info_and_Feature_Bits
check_long_mode:
mov eax, 0x80000000 ; Set `eax` to `0x80000000`
cpuid ; Get highest supported argument into `eax`
cmp eax, 0x80000001 ; Compare `eax` to `0x80000001`; does extended function exist?
jb .long_mode_absent ; Long mode doesn't have the ability to exist

mov eax, 0x80000001 ; Set `eax` to `0x80000001`; argument for processor info
cpuid ; Get info into `ecx` and `edx`
test edx, 1 << 29 ; Check 29th bit, the long mode bit
jz .long_mode_absent ; If it's false, there is no long more support
ret

;; DESCRIPTION:
;; Hals the CPU with the error code "2".
;;
;; LINKS:
;; `error.asm` for `error`
.long_mode_absent:
mov al, "2" ; Move error "2" to `al`
extern error ; Declare `error` for linking to `error.asm`
jmp error ; Jump to `error` for halting
25 changes: 25 additions & 0 deletions asm/src/arch/x86_64/longmode_initialise.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
global long_mode_start

section .text
bits 64
;; DESCRIPTION:
;; Starts to execute kernel code in 64 bit mode and initialises basic data.
;;
;; After execution, this halts the CPU.
;;
;; LINKS:
;; The Rust part of the kernel for `rust_main`
long_mode_start:
;; Reload data segments for 64-bit use instead of 32 bit
mov ax, 0
mov ss, ax
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax

;; Starts the Rust part of the kernel.
extern rust_main
call rust_main

hlt
26 changes: 26 additions & 0 deletions asm/src/arch/x86_64/multiboot_check.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
global check_multiboot

section .text
bits 32
;; DESCRIPTION:
;; Checks whether the kernel is loaded in multiboot mode, version 2.
;;
;; If it isn't, jump to .multiboot_absent.
;; If it is, return to stack.
;;
;; VARIABLES:
;; `eax` - Given by GRUB2 once it starts the kernel
check_multiboot:
cmp eax, 0x36d76289 ; Check for magic value
jne .multiboot_absent ; Jump if not true
ret ; Return to stack

;; DESCRIPTION:
;; Halts the CPU with the error code "0".
;;
;; LINKS:
;; `error.asm` for `error`
.multiboot_absent:
mov al, "0" ; Move error "0" to `al`
extern error ; Declare `error` for linking to `error.asm`
jmp error ; Jump to `error` for halting
25 changes: 25 additions & 0 deletions asm/src/arch/x86_64/multiboot_header.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
section .multiboot_header
bits 32

;; DESCRIPTION:
;; Header for the multiboot mode, version 2 protocol.
;; All multiboot2 compatible bootloaders check for this in the kernel before boot.
header_start:
;; Multiboot 2 requires a magic number to be start
;; That is the following DWORD:
dd 0xe85250d6

;; The architecture `protected i368` is `0` and it must be provided in a DWORD:
dd 0

;; The length of the rest of the header should be provided as a DWORD:
dd header_end - header_start

;; A checksum of the header should exist and should be a DWORD:
dd 0x100000000 - (0xe85250d6 + 0 + (header_end - header_start))

;; Multiboot then wants us to end with some other magic values:
dw 0
dw 0
dd 8
header_end:
Loading

0 comments on commit 250e180

Please sign in to comment.