Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .vscode/settings.json

This file was deleted.

138 changes: 103 additions & 35 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,37 +1,105 @@
FILES = ./build/kernel.asm.o ./build/isr.o ./build/kernel.o ./build/vga.o ./build/panic.o ./build/idt.o ./build/pic.o ./build/keyboard.o ./build/printk.o ./build/shell.o
FLAGS = -g -ffreestanding -nostdlib -nostartfiles -nodefaultlibs -Wall -O0 -Iinc

all:
nasm -f bin ./src/boot.asm -o ./bin/boot.bin
nasm -f elf -g ./src/kernel.asm -o ./build/kernel.asm.o
nasm -f elf -g ./src/isr.asm -o ./build/isr.o
i686-elf-gcc -I./src $(FLAGS) -std=gnu99 -c ./src/kernel.c -o ./build/kernel.o
i686-elf-gcc -I./src $(FLAGS) -std=gnu99 -c ./src/vga.c -o ./build/vga.o
i686-elf-gcc -I./src $(FLAGS) -std=gnu99 -c ./src/panic.c -o ./build/panic.o
i686-elf-gcc -I./src $(FLAGS) -std=gnu99 -c ./src/idt.c -o ./build/idt.o
i686-elf-gcc -I./src $(FLAGS) -std=gnu99 -c ./src/pic.c -o ./build/pic.o
i686-elf-gcc -I./src $(FLAGS) -std=gnu99 -c ./src/keyboard.c -o ./build/keyboard.o
i686-elf-gcc -I./src $(FLAGS) -std=gnu99 -c ./src/printk.c -o ./build/printk.o
i686-elf-gcc -I./src $(FLAGS) -std=gnu99 -c ./src/shell.c -o ./build/shell.o
i686-elf-ld -g -relocatable $(FILES) -o ./build/completeKernel.o
i686-elf-gcc $(FLAGS) -T ./linkerScript.ld -o ./bin/kernel.bin -ffreestanding -O0 -nostdlib ./build/completeKernel.o

dd if=./bin/boot.bin >> ./bin/os.bin
dd if=./bin/kernel.bin >> ./bin/os.bin
dd if=/dev/zero bs=512 count=8 >> ./bin/os.bin
CROSS ?= i686-elf-
AS := nasm
CC := $(CROSS)gcc
LD := $(CROSS)ld
OBJCOPY := $(CROSS)objcopy
QEMU := qemu-system-i386

BUILD_DIR := build

STAGE1_SRC := src/bootloader/stage1/boot.asm
STAGE2_SRC := src/bootloader/stage2/main.asm
STAGE2_C_SRC := src/bootloader/stage2/main.c
STAGE2_STDIO_SRC := src/bootloader/stage2/stdio.c
STAGE2_X86_ASM_SRC := src/bootloader/stage2/x86.asm

STAGE1_BIN := $(BUILD_DIR)/boot/stage1.bin
STAGE2_OBJ := $(BUILD_DIR)/boot/stage2.o
STAGE2_C_OBJ := $(BUILD_DIR)/boot/stage2_main.o
STAGE2_STDIO_OBJ := $(BUILD_DIR)/boot/stage2_stdio.o
STAGE2_X86_ASM_OBJ := $(BUILD_DIR)/boot/stage2_x86_asm.o
STAGE2_ELF := $(BUILD_DIR)/boot/stage2.elf
STAGE2_BIN := $(BUILD_DIR)/boot/stage2.bin
STAGE2_PAD := $(BUILD_DIR)/boot/stage2.padded.bin

KERNEL_MAIN_SRC := src/kernel/main.asm
KERNEL_C_SRC := src/kernel/kernel.c
KERNEL_MAIN_OBJ := $(BUILD_DIR)/kernel/main.o
KERNEL_C_OBJ := $(BUILD_DIR)/kernel/kernel.o
KERNEL_ELF := $(BUILD_DIR)/kernel.elf
KERNEL_BIN := $(BUILD_DIR)/kernel.bin
KERNEL_PAD := $(BUILD_DIR)/kernel.padded.bin

DISK_IMAGE := $(BUILD_DIR)/ginnos.img

STAGE2_SECTORS := 4
KERNEL_SECTORS := 12
SECTOR_SIZE := 512
STAGE2_MAX_BYTES := $(shell echo $$(( $(STAGE2_SECTORS) * $(SECTOR_SIZE) )))
KERNEL_MAX_BYTES := $(shell echo $$(( $(KERNEL_SECTORS) * $(SECTOR_SIZE) )))

CFLAGS := -std=gnu11 -ffreestanding -O2 -Wall -Wextra -m32
STAGE2_CFLAGS := -std=gnu11 -ffreestanding -O2 -Wall -Wextra -m16 -fno-pic -fno-stack-protector
LDFLAGS := -T linker/kernel.ld -nostdlib
STAGE2_LDFLAGS := -T linker/stage2.ld -nostdlib

.PHONY: all run clean check-tools

all: check-tools $(DISK_IMAGE)

check-tools:
@command -v $(CC) >/dev/null 2>&1 || { echo "Missing tool: $(CC)"; exit 1; }
@command -v $(LD) >/dev/null 2>&1 || { echo "Missing tool: $(LD)"; exit 1; }
@command -v $(OBJCOPY) >/dev/null 2>&1 || { echo "Missing tool: $(OBJCOPY)"; exit 1; }
@command -v $(AS) >/dev/null 2>&1 || { echo "Missing tool: $(AS)"; exit 1; }
@command -v $(QEMU) >/dev/null 2>&1 || { echo "Missing tool: $(QEMU)"; exit 1; }

$(STAGE1_BIN): $(STAGE1_SRC)
mkdir -p $(dir $@)
$(AS) -f bin $< -o $@
@test $$(wc -c < $@) -eq 512 || { echo "stage1 must be exactly 512 bytes"; exit 1; }

$(STAGE2_BIN): $(STAGE2_SRC) $(STAGE2_C_SRC) $(STAGE2_STDIO_SRC) $(STAGE2_X86_ASM_SRC) linker/stage2.ld
mkdir -p $(dir $@)
$(AS) -f elf32 $(STAGE2_SRC) -o $(STAGE2_OBJ)
$(CC) $(STAGE2_CFLAGS) -c $(STAGE2_C_SRC) -o $(STAGE2_C_OBJ)
$(CC) $(STAGE2_CFLAGS) -c $(STAGE2_STDIO_SRC) -o $(STAGE2_STDIO_OBJ)
$(AS) -f elf32 $(STAGE2_X86_ASM_SRC) -o $(STAGE2_X86_ASM_OBJ)
$(LD) $(STAGE2_LDFLAGS) -o $(STAGE2_ELF) $(STAGE2_OBJ) $(STAGE2_C_OBJ) $(STAGE2_STDIO_OBJ) $(STAGE2_X86_ASM_OBJ)
$(OBJCOPY) -O binary $(STAGE2_ELF) $(STAGE2_BIN)
@test $$(wc -c < $(STAGE2_BIN)) -le $(STAGE2_MAX_BYTES) || { echo "stage2 exceeds $(STAGE2_MAX_BYTES) bytes"; exit 1; }

$(STAGE2_PAD): $(STAGE2_BIN)
cp $(STAGE2_BIN) $@
truncate -s $(STAGE2_MAX_BYTES) $@

$(KERNEL_MAIN_OBJ): $(KERNEL_MAIN_SRC)
mkdir -p $(dir $@)
$(AS) -f elf32 $< -o $@

$(KERNEL_C_OBJ): $(KERNEL_C_SRC)
mkdir -p $(dir $@)
$(CC) $(CFLAGS) -c $< -o $@

$(KERNEL_ELF): $(KERNEL_MAIN_OBJ) $(KERNEL_C_OBJ) linker/kernel.ld
$(LD) $(LDFLAGS) -o $@ $(KERNEL_MAIN_OBJ) $(KERNEL_C_OBJ)

$(KERNEL_BIN): $(KERNEL_ELF)
$(OBJCOPY) -O binary $(KERNEL_ELF) $@
@test $$(wc -c < $@) -le $(KERNEL_MAX_BYTES) || { echo "kernel exceeds $(KERNEL_MAX_BYTES) bytes"; exit 1; }

$(KERNEL_PAD): $(KERNEL_BIN)
cp $(KERNEL_BIN) $@
truncate -s $(KERNEL_MAX_BYTES) $@

$(DISK_IMAGE): $(STAGE1_BIN) $(STAGE2_PAD) $(KERNEL_PAD)
truncate -s 1474560 $@
dd if=$(STAGE1_BIN) of=$@ bs=512 seek=0 conv=notrunc status=none
dd if=$(STAGE2_PAD) of=$@ bs=512 seek=1 conv=notrunc status=none
dd if=$(KERNEL_PAD) of=$@ bs=512 seek=5 conv=notrunc status=none

run: check-tools $(DISK_IMAGE)
$(QEMU) -drive if=floppy,format=raw,file=$(DISK_IMAGE)

clean:
rm -f ./bin/boot.bin
rm -f ./bin/kernel.bin
rm -f ./bin/os.bin
rm -f ./build/kernel.asm.o
rm -f ./build/isr.o
rm -f ./build/kernel.o
rm -f ./build/vga.o
rm -f ./build/panic.o
rm -f ./build/idt.o
rm -f ./build/pic.o
rm -f ./build/keyboard.o
rm -f ./build/printk.o
rm -f ./build/shell.o
rm -f ./build/completeKernel.o
rm -rf $(BUILD_DIR)
114 changes: 86 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,45 +1,103 @@
# Ginnung OS
# GinnOS
GinnOS (Ginn short for Ginnungagap, and OS short for Operating System) is a personal hobby operating system, which i'm developing alongside a course on operating systems i'm taking at DTU.

This is a small personal project I am building alongside my operating systems course at DTU.
I am using it to learn more about operating systems development and therefore i don't really know what it will turn into.
I started this project because i wanted to understand how an operating system is really coded instead of just theory. I plan to keep building and improving it as i learn more.

The name GinnOS is taken from Ginnungagap, the primordial void in Norse mythology from which the world was created.

## Prerequisites
> "That was the age when nothing was; / There was no sand, nor sea, nor cool waves, / No earth nor sky nor grass there, / Only Ginnungagap."
> — Völuspá, Poetic Edda

To build this project on macOS, install:
## macOS Toolchain Setup (Manual)

- Xcode Command Line Tools: `xcode-select --install`
- Homebrew
- Build dependencies for the OSDev cross-compiler guide:
- `gmp`
- `mpfr`
- `libmpc`
- `texinfo`
- Tools used by this repository:
- `nasm`
- `qemu` or `qemu-system-i386`
### Install host dependencies

The cross-compiler is expected at `~/opt/cross/bin`, with `i686-elf-gcc` and `i686-elf-ld` available on your `PATH`.
Only install what this two-stage build needs:

## Build
```bash
brew install gmp mpfr libmpc texinfo nasm qemu
```

### Build i686 cross compiler manually

Create build directories:

```bash
mkdir -p "$HOME/src/cross"
mkdir -p "$HOME/opt/cross"
cd "$HOME/src/cross"
```

Build and install binutils:

```bash
curl -LO https://ftp.gnu.org/gnu/binutils/binutils-2.42.tar.xz
tar -xf binutils-2.42.tar.xz
mkdir -p build-binutils
cd build-binutils

../binutils-2.42/configure \
--target=i686-elf \
--prefix="$HOME/opt/cross" \
--with-sysroot \
--disable-nls \
--disable-werror

make -j"$(sysctl -n hw.ncpu)"
make install
cd ..
```

Build and install GCC (C only):

```bash
curl -LO https://ftp.gnu.org/gnu/gcc/gcc-14.2.0/gcc-14.2.0.tar.xz
tar -xf gcc-14.2.0.tar.xz
mkdir -p build-gcc
cd build-gcc

Run the build script from the repository root:
../gcc-14.2.0/configure \
--target=i686-elf \
--prefix="$HOME/opt/cross" \
--disable-nls \
--enable-languages=c \
--without-headers

```sh
./build.sh
make -j"$(sysctl -n hw.ncpu)" all-gcc all-target-libgcc
make install-gcc install-target-libgcc
cd ..
```

This creates `bin/os.bin`.
### Add cross toolchain to PATH

## Boot
```bash
echo 'export PATH="$HOME/opt/cross/bin:$PATH"' >> ~/.zshrc
source ~/.zshrc
```

After building, start the OS with:
### Verify required tools

```sh
qemu-system-i386 -m 64M -no-reboot -drive format=raw,file=bin/os.bin
```bash
i686-elf-gcc --version
i686-elf-ld --version
i686-elf-objcopy --version
nasm -v
qemu-system-i386 --version
```

## Notes
## Build and Run

From project root:

```bash
make
make run
```

## Credits and Learning Resources

- Nanobyte: https://www.youtube.com/@nanobyte-dev
Operating system tutorials that have been a big help.

- If `./build.sh` cannot find `i686-elf-gcc`, make sure your cross-compiler is installed under `~/opt/cross` and that `~/opt/cross/bin` is on `PATH`.
- If QEMU is installed under a different binary name on your system, use that executable instead.
- OSDev Wiki: https://wiki.osdev.org/
The main reference used for low level concepts and implementation.
5 changes: 0 additions & 5 deletions build.sh

This file was deleted.

27 changes: 27 additions & 0 deletions linker/kernel.ld
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
ENTRY(_start)

SECTIONS
{
. = 0x10000;

.text :
{
*(.text*)
}

.rodata :
{
*(.rodata*)
}

.data :
{
*(.data*)
}

.bss :
{
*(.bss*)
*(COMMON)
}
}
27 changes: 27 additions & 0 deletions linker/stage2.ld
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
ENTRY(_start)

SECTIONS
{
. = 0x8000;

.text :
{
*(.text*)
}

.rodata :
{
*(.rodata*)
}

.data :
{
*(.data*)
}

.bss :
{
*(.bss*)
*(COMMON)
}
}
26 changes: 0 additions & 26 deletions linkerScript.ld

This file was deleted.

Loading