From bbf798c6448db61a9a14bdf3defaa0a1e012e8fd Mon Sep 17 00:00:00 2001 From: antifallobst Date: Thu, 9 Feb 2023 13:29:31 +0100 Subject: [PATCH] docs: added wiki markdown files to codebase --- .wiki/Build-instructions.md | 41 ++++ .wiki/Code-Style.md | 61 ++++++ .wiki/Contribution-guide.md | 38 ++++ .wiki/Home.md | 9 + .wiki/Kernel-documentation.md | 377 ++++++++++++++++++++++++++++++++++ 5 files changed, 526 insertions(+) create mode 100644 .wiki/Build-instructions.md create mode 100644 .wiki/Code-Style.md create mode 100644 .wiki/Contribution-guide.md create mode 100644 .wiki/Home.md create mode 100644 .wiki/Kernel-documentation.md diff --git a/.wiki/Build-instructions.md b/.wiki/Build-instructions.md new file mode 100644 index 0000000..d8c781f --- /dev/null +++ b/.wiki/Build-instructions.md @@ -0,0 +1,41 @@ +# Build instructions +**DISCLAIMER: To build this project you need a linux system (WSL could work for windows users, but I haven't tested it)** + + +First you need to clone the repository: + +`git clone https://codeberg.org/antifallobst/noxos/` + +then there are a few tools required, that need to be installed: +* **gcc** - compiler +* **ld** - linker +* **nasm** - assembler +* **cmake** - build system +* **xorriso** - ISO creation tools +* **qemu** - emulator + +There is a shell script to setup the workspace and compile. +Just run it using the following commands: +```bash +cd noxos +./build.sh +``` +If the Bootloader (Limine ([github](https://github.com/limine-bootloader/limine))) isn't downloaded yet, the script will download it. + +The final ISO file will be written to the *build* directory. + +To launch the ISO, run the `run.sh` script. + +# Debugging +## Logs +When running through the script, qemu is configured to write the kernels logs to *STDOUT* and a file called *noxos.log*. +## GDB +You can connect GDB to qemu. +To achieve this, run `./run.sh debug`. +QEMU will wait until you connect GDB to it as a 'remote' target on `localhost:1234`. +```bash +gdb build/cmake/kernel/kernel +target remote localhost:1234 +c +``` +(note, that the last to commands have to be 'executed' in gdb not in your shell) \ No newline at end of file diff --git a/.wiki/Code-Style.md b/.wiki/Code-Style.md new file mode 100644 index 0000000..cb6f53b --- /dev/null +++ b/.wiki/Code-Style.md @@ -0,0 +1,61 @@ +# Code Style +## Naming conventions +- **structs** are suffixed with **_T** +- **typedefs** are suffixed with **_t** +- **enums** are suffixed with **_E** +- **global** variables are prefixed with **g_** + +Everything is **snake_case**. + +## Code readability +To make the code as readable and self explaining as possible, there are a few patterns that should be used. + +### Avoid abbreviations +Give your variables, functions, etc. meaningfull names. +The times of 80char wide screens are over, feel free to use that space :D + +Example: `sym_at_idx` -> `get_symbol_at_index` + +But you're not forced to (anything) write out everything. +For example the **Interrupt Descriptor Table** is simply referred to as **idt** (this abbreviation is btw standard). + +### Avoid indentation nesting +In a perfect codebase, the maximum indention level would be 3. +The goal of NoxOS is not to be a perfect codebase, but please avoid huge indention nesting. +To achieve this, you can break parts into extra functions and/or use the early return pattern. + +Example: +```c +bool likes_pigs (void* a) { + if (a != NULL) { + if (a == 0xACAB) { + return false; + } + } + return true; +} +``` +-> +```c +bool likes_pigs (void* a) { + if (a != NULL) { return true; } + if (a != 0xACAB) { return true; } + + return false; +} +``` + +### align declarations + +Please align declarations, definitions, etc like in the example: +```c +char am_i_a_variable = '?'; +uint64_t number = 0; +bool i_waste_bits = true; +``` + +### namespaces +Unlike C++ C has no namespaces. +To achieve the goal of namespaces, please prefix your functions, structs, etc. with the "namespace" they are in. + +Example: `out_byte` -> `io_out_byte` diff --git a/.wiki/Contribution-guide.md b/.wiki/Contribution-guide.md new file mode 100644 index 0000000..05eb9b5 --- /dev/null +++ b/.wiki/Contribution-guide.md @@ -0,0 +1,38 @@ +Welcome :D + +Nice, that you're interested in contributing. + +# Before Contribution +Please read the [Code-Style wiki entry](https://codeberg.org/antifallobst/noxos/wiki/Code-Style) before you start to contribute. + +For workspace setup and build instructions look at [this wiki entry](https://codeberg.org/antifallobst/noxos/wiki/Build-instructions). + +**We don't accept any Assholes! If you're a fascist, racist, or discriminate others for anything, go fuck yourself.** + +# Contributing + +When you contribute code, please [document](https://codeberg.org/antifallobst/noxos/wiki/Kernel-documentation) it. +You don't have to (and you also shouldn't) write romans, but a few lines for every in a header exposed function, struct etc. help others (and yourself) understanding how to interact with your code. + + +## What dafuq is ...? +OS development can be quite complicated/confusing. That's Ok. +Stuff like Paging can be really weird, if you don't have osdev experience. +But there are learning resources and places, where you can ask questions. + +**A small overview about such resources and places:** +- The [osdev wiki](https://wiki.osdev.org) is like wikipedia - just for hobby os developers. +- The [osdev subreddit](https://reddit.com/r/osdev) is a great place to ask questions and share knowledge +- Intel's [developer manual](https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html) is a more advanced but kinda precise information source + +Also feel free to join the [NoxOS Matrix space](https://matrix.to/#/#noxos:systemausfall.org), +where you can chat with other NoxOS devs and ask questions. +**But Stay Respectful, Or We `sudo rm -rf /` Your PC ;)** + +# Where to start? + +Get the codebase and play a bit around with it. +Try to understand basic concepts of the codebase, the [documentation](https://codeberg.org/antifallobst/noxos/wiki/Kernel-documentation) will help you. +After that you can search the [Issues](https://codeberg.org/antifallobst/noxos/issues) for the `Good First Issue` label, +to find easy improvements, etc. that you can try to implement. +Another option is to ask in the [Matrix Space](https://matrix.to/#/#noxos:systemausfall.org). \ No newline at end of file diff --git a/.wiki/Home.md b/.wiki/Home.md new file mode 100644 index 0000000..77154f8 --- /dev/null +++ b/.wiki/Home.md @@ -0,0 +1,9 @@ +**DISCLAIMER: We don't accept any Assholes! If you're a fascist, racist, or discriminate others for anything, go fuck yourself.** If not, welcome :) + +Wiki Content: + +* [Contribution guide](https://codeberg.org/antifallobst/noxos/wiki/Contribution-guide) +* [Build instructions](https://codeberg.org/antifallobst/noxos/wiki/Build-instructions) +* [Code Style](https://codeberg.org/antifallobst/noxos/wiki/Code-Style) +* [Kernel Documentation](https://codeberg.org/antifallobst/noxos/wiki/Kernel-documentation) +* [Project Roadmap](https://codeberg.org/antifallobst/noxos/wiki/Roadmap) \ No newline at end of file diff --git a/.wiki/Kernel-documentation.md b/.wiki/Kernel-documentation.md new file mode 100644 index 0000000..9f0b1b4 --- /dev/null +++ b/.wiki/Kernel-documentation.md @@ -0,0 +1,377 @@ +# Kernel Documentation +The kernel is booted using the limine boot protocol. + +## Directory structure + - **boot** - all stuff related to booting / jumping into the kernel + - **drivers** - everything from the graphics driver, to the FS drivers + - **mm** - memory management stuff like page frames and page maps + - **platform** - universal API to the platform specific code in the subdirs + - **proc** - all the process/thread related stuff like the scheduler + - **utils** - utilities like type definitions, math functions, high-level memory management + +--- + +# General concepts +## kernel initialization +The single parts of the kernel are initialized in the following order: + - **Global Descriptor Table** + - **Page Frame Manager** + - **Interrupt Descriptor Table** + +## interrupt handling +OSDev Wiki: [Interrupts](https://wiki.osdev.org/Interrupts) + +Unfortunatly the x86 architecture doesn't provide a method to get the ID of the current interrupt. +To solve this problem, there is a simple assembly function for every interrupt used by NoxOS. +This function pushes its ID on the stack. +After that it calls a common Interrupt handler, this handler will generate the current `cpu_state_T` and call the C interrupt handler implementation. +The C implementation returns a `cpu_state_T` that will then be loaded. + +## paging +OSDev Wiki: [Paging](https://wiki.osdev.org/Paging) + +There is a difference between `Virtual Memory Spaces` and the `Physical Memory Space`. +The Physical memory space is how the data lies directly in the RAM. + +Virtual memory spaces are a bit more tricky. +To understand them, we have to understand first, that the physical memory space is divided into so-called **pages** / **page frames**. +These pages have a size of 4KB. + +A virtual memory space is a table of page mappings. +Per default there are no pages mapped to such a table. +When the OS maps a page to a **page table**, it says: +"This page is now accessible from this virtual space, at this address". +When the Computer is in paging mode, only mapped pages are accessible. +Now every Process gets its own page table and tada: we have successfully isolated the processes from each other, +because every process can only access the data that it needs to access. + +--- + +**DISCLAIMER:** Only the headers are documented, because documenting the whole code itself would be very time intensive and the headers as 'public' API are the most important to document. + +## boot + +### boot_info.h +The goal of this file is to provide a universal struct of information needed by the kernel at start time. +At the moment this information is very limine specific, but the goal is to make it easy to add support for other boot protocols. + +#### `boot_info_T` - struct + - **framebuffer** - struct with information about the graphics buffer + - **terminal** - bootloader terminal / log + - **memory_map** - information about the memory layout / regions + - **rsdp** - pointer to RSDP + +### limine.h +This header provides the API to "communicate" with the limine bootloader. +More information can be found on the limine project's [GitHub](https://github.com/limine-bootloader/limine/blob/trunk/PROTOCOL.md). + + +## mm + +### page_frame.h +This header provides the functions for basic interactions with pages (in the physical memory space). + +#### `pframe_manager_init()` - function (void) +Initializes the page frame manager, needs to be called once at kernel init. + +#### `pframe_reserve(address)` - function (void) [Thread Safe] +Blocks a page, so it can't be requested or anything else. +If the page is already blocked by anything else, e.g. by a request, it won't be reserved. + +#### `pframe_reserve_multi(address, n)` - function (void) [Thread Safe] +Reserves the page at the given address, plus *n* pages after that page. + +#### `pframe_unreserve(address)` - function (void) [Thread Safe] +Unreserves a reserved page and makes it accessible again. + +#### `pframe_unreserve_multi(address, n)` - function (void) [Thread Safe] +Unreserves the page at the given address, plus *n* pages after that page. + +#### `pframe_request()` - function (void*) [Thread Safe] +Returns the physical address of a page. +This is kind of the low level version of malloc. + +#### `pframe_free(address)` - function (void) [Thread Safe] +Needs a valid page address produced by `pframe_request()` as argument. +Invalidates the address and frees it, so it can be requested again. +This is kind of the low level version of free. + +#### `pframe_free_multi(address, n)` - function (void) [Thread Safe] +Frees the page at the given address, plus *n* pages after that page. + +## platform + +### cpu.h +This header contains stuff directly related to the CPU. + +OSDev Wiki: [x86 CPU Registers](https://wiki.osdev.org/CPU_Registers_x86) + +#### `cpu_state_T` - struct + - **cr3** - Control register 3, holds the current page table + - **rax** - General purpose register + - **rbx** - General purpose register + - **rcx** - General purpose register + - **rdx** - General purpose register + - **rsi** - General purpose register + - **rdi** - General purpose register + - **rbp** - The Bottom of the current stack frame + - **interrupt_id** - The ID of the interrupt, that captured the cpu state + - **error_code** - Some exceptions such as the Page fault push more detailed information into here + - **rip** - The current instruction address + - **crs** - Segment selector of the associated IDT descriptor + - **flags** - The CPU's FLAGS register, a status bitmap + - **rsp** - The Top of the current stack frame + - **ss** - Not totally sure, what this does, but it has to do with security rings + +This struct defines a *complete* CPU state, that can be saved and restored. +It is saved when the CPU fires an interrupt and restored by the interrupt handler when it's finished. +This allows multithreading and exception analysis. + +#### `cpu_flags_E` - enum + - **CPU_FLAG_CARRY** + - **CPU_FLAG_PARITY** + - **CPU_FLAG_AUXILIARY** + - **CPU_FLAG_ZERO** + - **CPU_FLAG_SIGN** + - **CPU_FLAG_TRAP** + - **CPU_FLAG_INTERRUPT_ENABLE** + - **CPU_FLAG_DIRECTION** + - **CPU_FLAG_OVERFLOW** + - **CPU_FLAG_IO_PRIVILEGE_0** + - **CPU_FLAG_IO_PRIVILEGE_1** + - **CPU_FLAG_NESTED_TASK** + - **CPU_FLAG_RESUME** + - **CPU_FLAG_VIRTUAL_8086** + - **CPU_FLAG_ALIGNMENT_CHECK** + - **CPU_FLAG_VIRTUAL_INTERRUPT** + - **CPU_FLAG_VIRTUAL_INTERRUPT_PENDING** + - **CPU_FLAG_CPUID** + +### exceptions.h +OSDev Wiki: [Exceptions](https://wiki.osdev.org/Exceptions) + +#### `exception_type_E` - enum +These are just the definitions of the CPU-exception interrupt IDs. + +#### `g_exception_type_strings` - global variable +This array of strings defines the names of the Exceptions. + +#### `exception_handle(cpu_state)` - function (cpu_state_T*) +If an interrupt is an exception, the interrupt handler will call this function to handle the exception. +At the moment it will just panic, but in far future this could get expanded for page swapping, etc. + +### gdt.h +OSDev Wiki: [Global Descriptor Table](https://wiki.osdev.org/GDT) + +#### `gdt_selector_E` - enum +- **Null** +- **Kernel Code** +- **Kernel Data** +- **User Null** +- **User Code** +- **User Data** + +#### `gdt_descriptor_T` - struct [packed] +**Well documented on the osdev wiki.** + +#### `gdt_entry_T` - struct [packed] +**Well documented on the osdev wiki.** + +#### `gdt_T` - struct [packed / page aligned] +A template that holds a `gdt_entry_T` for every selector + +#### `g_default_gdt` - global variable +The default GDT configuration loaded when the GDT gets initialized. + +#### `gdt_init()` - function (void) +Loads a descriptor of `g_default_gdt` as the system GDT. + +### interrupts.h +This header contains all the stuff, needed to init and handle Interrupts. + +#### `idt_register_T` - struct [packed] +This struct is very similar to the GDT descriptor. +It holds the size and address of the Table, where the interrupt handlers are looked up. + +#### `idt_descriptor_entry_T` - struct +This struct stores information about one interrupt handler. +The osdev wiki explains this more detailed. + +#### `g_idt_register` - global variable +The default IDT configuration loaded when the IDT gets initialized. + +#### `idt_init()` - function (void) +This function fills all the interrupt gates (handlers) into the IDT and loads it. + + +## utils + +### bitmap.h +Provides functionalities to create, destruct and work with bitmaps. + +#### `bitmap_T` - struct +This struct holds a buffer for a bitmap and its size. +The size is the size of the buffer in bytes, to get the amount of storable bits multiply size with 8. + +#### `bitmap_init_from_buffer(buffer, size)` - function (bitmap_T) +Creates a bitmap object from a given buffer and size + +#### `bitmap_init(size)` - function (bitmap_T) [NOT IMPLEMENTED YET] +Allocates memory to hold a bitmap in the given size and returns a `bitmap_T` with that buffer and size. + +#### `bitmap_destruct(bitmap*)` - function (void) [NOT IMPLEMENTED YET] +Frees the memory of the given bitmap created with `bitmap_init`. + +#### `bitmap_set(bitmap*, index, value)` - function (bool) +Sets the bit at the given index in the given bitmap to the given boolean value. +Returns **false**, if the index is out of the bitmaps size bounds. +Returns **true**, if the operation was successful. + +#### `bitmap_get(bitmap*, index)` - function (bool) +Returns the boolean value stored at the given index in the given bitmap. +Always returns **false**, if the index is out of the bitmaps size bounds. + +### core.h +All the utils, which I didn't know how to name. + +#### `CORE_HALT_WHILE(a)` - macro +This halts until **_a_** is true. +Used when working with blocking variables in e.g. thread safe functions. + +#### `CORE_HALT_FOREVER` - macro +This halts forever and warns about this in the log. + +### io.h +Provides basic Input/Output functionalities. + +#### `io_out_byte(port, data)` - function (void) +Writes one byte of **_data_** to **_port_**. +This is a wrapper around the assembly `outb` instruction. + +#### `io_in_byte(port)` - function (uint8_t) +Reads one byte from **_port_** and returns it. +This is a wrapper around the assembly `inb` instruction. + +### logger.h +Functionalities to write logs to QEMU's serial port. + +#### `log_level_E` - enum + - **Info** - General information, that could be useful + - **Debug** - Should only be used to find bugs and removed (or commented out) after the bug is found + - **Warning** - Used for warnings and not important errors + - **Error** - Used for Fatal Errors / Will be printed to the screen (graphics driver is not Implemented yet) + +#### `log(log_level, string)` - function (void) +Logs the given string to QEMU's log port, the string is prefixed with the log type. + +### math.h +Mathematical functions, definitions, etc. + +#### `MAX(a, b)` - macro +Returns the bigger one of the given values. + +#### `MIN(a, b)` - macro +Returns the smaller one of the given values. + +#### `CEIL_TO(a, b)` - macro +Aligns **_a_** upwards to **_b_**. +Example: `CEIL_TO(13, 8)` would return 16, because 16 is the next higher multiple of 8 after 13. + +#### `FLOOR_TO(a, b)` - macro +Aligns **_a_** downwards to **_b_**. +Example: `FLOOR_TO(13, 8)` would return 8, because 8 is the next smaller multiple of 8 before 13. + +#### `pow(base, exponent)` - function (uint64_t) +Returns the power of `base ^ exponent`. + +### memory.h +Basic memory functionalities. + +#### `memory_copy(source, destination, num)` - function (void) +Copies **_num_** bytes from **_source_** to **_destination_**. +On linux this function is called _memcpy_. + +#### `memory_set(destination, data, num)` - function (void) +Sets **_num_** bytes at **_destination_** to **_data_**. +On linux this function is called _memset_. + +#### `memory_compare(a, b, num)` - function (bool) +Compares the first **_num_** bytes at **_a_** and **_b_**. +Returns **false** if there is a different byte. +Returns **true** if the data is the same. +There is a similar function on linux called _memcmp_. + +### panic.h +Ahhhhh - the kernel is burning! + +#### `panic(state, message)` - function (void) +This prints out the error message, a stack backtrace (planned) and a register dump (planned). +After that, the kernel halts forever. +This function is called, when a fatal error occurs + +### stdtypes.h +Standard type definitions, that are used almost everywhere. + +#### `uint8_t` - typedef +8-bit wide unsigned int. + +Range: `0` - `255` + +#### `int8_t` - typedef +8-bit wide signed int. + +Range: `-128` - `127` + +#### `uint16_t` - typedef +16-bit wide unsigned int. + +Range: `0` - `65536` + +#### `int16_t` - typedef +16-bit wide signed int. + +Range: `-32768` - `32767` + +#### `uint32_t` - typedef +32-bit wide unsigned int. + +Range: `0` - `4294967296` + +#### `int32_t` - typedef +32-bit wide signed int. + +Range: `-2147483648` - `2147483647` + +#### `uint64_t` - typedef +64-bit wide unsigned int. + +Range: `0` - `18446744073709551616` + +#### `int64_t` - typedef +64-bit wide unsigned int. + +Range: `-9223372036854775808` - `9223372036854775807` + +#### `bool` - typedef +Boolean type, can hold a logical value **true** or **false**. + +#### `true` - macro +Logical **true** value. + +#### `false` - macro +Logical **false** value + +#### `NULL` - macro +A pointer to nowhere. + +### string.h + +#### `string_t` - typedef +A null-terminated array of chars. + +#### `string_length(string)` - function (uint32_t) +Returns the amount of chars a string has before it's null-terminator. + +#### `string_compare(a, b)` - function (bool) +Returns **true** when the strings **_a_** and **_b_** are equal. +Returns **false** if they aren't equal. \ No newline at end of file