From 5f81da07741a348eda8ef147b2506700220b4e70 Mon Sep 17 00:00:00 2001 From: nigel Date: Sun, 2 May 2021 12:02:00 -0400 Subject: [PATCH] Initial setup, Basic helloworld kernel from wiki.osdev.org bare bones --- .gitignore | 1 + README.md | 49 ++++++++++++++++++++++++++++++ build.sh | 19 ++++++++++++ docs/.blank | 0 src/boot.s | 42 ++++++++++++++++++++++++++ src/kernel.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++ src/linker.ld | 43 ++++++++++++++++++++++++++ src/string.h | 8 +++++ src/vga_colors.h | 18 +++++++++++ 9 files changed, 258 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100755 build.sh create mode 100644 docs/.blank create mode 100644 src/boot.s create mode 100644 src/kernel.c create mode 100644 src/linker.ld create mode 100644 src/string.h create mode 100644 src/vga_colors.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c795b05 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +build \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..1aae946 --- /dev/null +++ b/README.md @@ -0,0 +1,49 @@ +# Writing an Operating system +## As a learning experience... Inspired by people like.. Linus Torvalds and Andreas Kling + + +### The goal +Writing a hobby operating system to better understand the basic building blocks of any operating system. + + + +### Operating System Technical specs/details +Currently the operating system is in the planning fase. +I hope to soon have the basic output and booting sequence with multiboot done. + + +### Planning + +[ ] Muliboot to kernel \ +[ ] Printing strings and integer numbers (both decimal and hex) on the screen is certainly a must. This is one of most basic ways of debugging, and virtually all of us have gone through a kprint() or kout in version 0.01. \ +[ ] Outputting to a serial port will save you a lot of debugging time. You don't have to fear losing information due to scrolling. You will be able to test your OS from a console, filter interesting debug messages, and automatize some tests. \ +[ ] Having a working and reliable interrupt/exception handling system that can dump the contents of the registers (and perhaps the address of the fault) will be very useful. \ +[ ] Plan your memory map (virtual, and physical) : decide where you want the data to be. \ +[ ] The heap: allocating memory at runtime (malloc and free) is almost impossible to go without. It should be implemented as soon as possible. + + +### Other features I am thinking of: +[ ] USTAR Filesystem ( For its simplicity this is very likely the first filesystem the OS is going to support) \ +[ ] Memory Management \ +[ ] Scheduling (Unknown what the scheduling algorithm will be, as with everything suspect simplicity) \ +[ ] RPC - for interprocess communication \ +[ ] Sync primitives - Semaphores, Mutexes, spinlocks et al. \ +[ ] ACPI support ( Or some other basic way to support shutdown, reboot and possibly hibernation ) \ +[ ] ATA support \ +[ ] Keyboard support ( must have ) \ +[ ] Basic hardware recognition ( CPU codename, memory, ATA harddisk, RAW diskSpace, CPU speed et al. ) \ +[ ] Basic Terminal \ +[ ] Simplistic draw ( maybe ?!?) \ +### Far in the future: \ +[ ] Basic Window server/client +#### Support for more filesystems if I like the challenge in writing these ... +[ ] FAT Filesystem +[ ] EXT2 Filesystem + + + +### Resources: + +[wiki.osdev.org/Main_Page](wiki.osdev.org/Main_Page) + +[Modern Operating Systems [book]](https://www.amazon.com/Modern-Operating-Systems-Tanenbaum-Andrew/dp/1292061421/ref=sr_1_1?__mk_nl_NL=%C3%85M%C3%85%C5%BD%C3%95%C3%91&dchild=1&keywords=Modern+Operating+systems&qid=1619967779&sr=8-1) diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..75f630a --- /dev/null +++ b/build.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +# Environment setup +export PATH="$HOME/opt/cross/bin:$PATH" + + +## Setup directory variables +SRC_DIR=src +BUILD_DIR=build + + +# Execute build +i686-elf-as $SRC_DIR/boot.s -o $BUILD_DIR/boot.o +i686-elf-gcc -c $SRC_DIR/kernel.c -o $BUILD_DIR/kernel.o -std=gnu99 -ffreestanding -O2 -Wall -Wextra +i686-elf-gcc -T $SRC_DIR/linker.ld -o $BUILD_DIR/myos.bin -ffreestanding -O2 -nostdlib $BUILD_DIR/boot.o $BUILD_DIR/kernel.o -lgcc + + +## How to run build +## Use the command: qemu-system-i386 -kernel build/myos.bin \ No newline at end of file diff --git a/docs/.blank b/docs/.blank new file mode 100644 index 0000000..e69de29 diff --git a/src/boot.s b/src/boot.s new file mode 100644 index 0000000..b72102a --- /dev/null +++ b/src/boot.s @@ -0,0 +1,42 @@ +/* + * Multiboot + */ +.set ALIGN, 1<<0 /* align loaded modules on page boundaries */ +.set MEMINFO, 1<<1 /* provide memory map */ +.set FLAGS, ALIGN | MEMINFO /* this is the Multiboot 'flag' field */ +.set MAGIC, 0x1BADB002 /* 'magic number' lets bootloader find the header */ +.set CHECKSUM, -(MAGIC + FLAGS) /* checksum of above, to prove we are multiboot */ + +.section .multiboot +.align 4 +.long MAGIC +.long FLAGS +.long CHECKSUM + + +.section .bss +.align 16 +stack_bottom: +.skip 16384 # 16 KiB +stack_top: + + +.section .text +.global _start +.type _start, @function +_start: + + + + mov $stack_top, %esp + + + + call kernel_main + + cli +1: hlt + jmp 1b + + +.size _start, . - _start \ No newline at end of file diff --git a/src/kernel.c b/src/kernel.c new file mode 100644 index 0000000..9f828b5 --- /dev/null +++ b/src/kernel.c @@ -0,0 +1,78 @@ +#include +#include +#include +#include "vga_colors.h" +#include "string.h" +static const size_t VGA_WIDTH = 80; +static const size_t VGA_HEIGHT = 25; + +size_t kterm_row; +size_t kterm_column; +uint8_t kterm_color; +uint16_t* kterm_buffer; + + +static inline uint8_t vga_entry_color(enum vga_color fg, enum vga_color bg) { + return fg | bg << 4; +} + +static inline uint16_t vga_entry (unsigned char uc, uint8_t color) { + return (uint16_t) uc | (uint16_t) color << 8; +} + +void init_kterm () { + kterm_row = 0; + kterm_column = 0; + kterm_color = vga_entry_color ( VGA_COLOR_LIGHT_GREY , VGA_COLOR_BLACK); + kterm_buffer = (uint16_t*) 0xB8000; + for (size_t y = 0; y < VGA_HEIGHT; y++ ){ + for( size_t x = 0; x < VGA_WIDTH; x++){ + const size_t index = y * VGA_WIDTH + x; + kterm_buffer[index] = vga_entry(' ', kterm_color); + + } + } +} + + +void kterm_setcolor(uint8_t color){ + kterm_color = color; +} + +void kterm_putat (char c, uint8_t color, size_t x, size_t y ) { + const size_t index = y * VGA_WIDTH + x; + + kterm_buffer[index] = vga_entry(c, color); + +} + +void kterm_put (char c) { + kterm_putat ( c, kterm_color, kterm_column, kterm_row); + if(kterm_column++ == VGA_WIDTH ){ + kterm_column = 0; + if(kterm_row++ == VGA_HEIGHT) + kterm_row = 0; + } + +} + +void kterm_write(const char* data, size_t size) { + for(size_t i = 0; i < size; i++){ + kterm_put(data[i]); + } +} + + +void kterm_writestring(const char* data ){ + kterm_write(data, strlen(data)); +} + + +void kernel_main (void) { + /** initialize terminal interface */ + init_kterm(); + + kterm_writestring("K: Hello world!\n"); + + +} \ No newline at end of file diff --git a/src/linker.ld b/src/linker.ld new file mode 100644 index 0000000..7292df5 --- /dev/null +++ b/src/linker.ld @@ -0,0 +1,43 @@ +/* The bootloader will look at this image and start execution at the symbol + designated as the entry point. */ +ENTRY(_start) + +/* Tell where the various sections of the object files will be put in the final + kernel image. */ +SECTIONS +{ + /* Begin putting sections at 1 MiB, a conventional place for kernels to be + loaded at by the bootloader. */ + . = 1M; + + /* First put the multiboot header, as it is required to be put very early + early in the image or the bootloader won't recognize the file format. + Next we'll put the .text section. */ + .text BLOCK(4K) : ALIGN(4K) + { + *(.multiboot) + *(.text) + } + + /* Read-only data. */ + .rodata BLOCK(4K) : ALIGN(4K) + { + *(.rodata) + } + + /* Read-write data (initialized) */ + .data BLOCK(4K) : ALIGN(4K) + { + *(.data) + } + + /* Read-write data (uninitialized) and stack */ + .bss BLOCK(4K) : ALIGN(4K) + { + *(COMMON) + *(.bss) + } + + /* The compiler may produce other sections, by default it will put them in + a segment with the same name. Simply add stuff here as needed. */ +} \ No newline at end of file diff --git a/src/string.h b/src/string.h new file mode 100644 index 0000000..579c72a --- /dev/null +++ b/src/string.h @@ -0,0 +1,8 @@ +#include +size_t strlen(const char* str){ + size_t len = 0; + while(str[len]){ + len++; + } + return len; +} \ No newline at end of file diff --git a/src/vga_colors.h b/src/vga_colors.h new file mode 100644 index 0000000..9c610a3 --- /dev/null +++ b/src/vga_colors.h @@ -0,0 +1,18 @@ +enum vga_color { + VGA_COLOR_BLACK = 0, + VGA_COLOR_BLUE = 1, + VGA_COLOR_GREEN = 2, + VGA_COLOR_CYAN = 3, + VGA_COLOR_RED = 4, + VGA_COLOR_MAGENTA = 5, + VGA_COLOR_BROWN = 6, + VGA_COLOR_LIGHT_GREY = 7, + VGA_COLOR_DARK_GREY = 8, + VGA_COLOR_LIGHT_BLUE = 9, + VGA_COLOR_LIGHT_GREEN = 10, + VGA_COLOR_LIGHT_CYAN = 11, + VGA_COLOR_LIGHT_RED = 12, + VGA_COLOR_LIGHT_MAGENTA = 13, + VGA_COLOR_LIGHT_BROWN = 14, + VGA_COLOR_WHITE = 15, +}; \ No newline at end of file