diff --git a/build-instructions.md b/build-instructions.md new file mode 100644 index 0000000..46fc75a --- /dev/null +++ b/build-instructions.md @@ -0,0 +1,48 @@ +# 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://git.nerdcult.net/noxos/kernel` + +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 +* **ovmf** - UEFI firmware + +you can check if you have all tools installed, with `./build.sh check`. + +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](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. + +# BIOS Emulation +To emulate a BIOS system, you can run `./run.sh bios`. + +# 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) diff --git a/codestyle.md b/codestyle.md new file mode 100644 index 0000000..2f41b26 --- /dev/null +++ b/codestyle.md @@ -0,0 +1,66 @@ +# Code Style +**Read this before contributing** + +The following code style should be applied to the whole noxos codebase. +Pull Requests that don't follow this code style will be rejected. + +# 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. meaningfully names. +The times of 80-char 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 (definitely written 100% sober): +```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/kernel/README.md b/kernel/README.md new file mode 100644 index 0000000..92a257d --- /dev/null +++ b/kernel/README.md @@ -0,0 +1,4 @@ +# Codebase + +Every header in the codebase has its own page. +The structure is identically to the codebase directory structure. diff --git a/kernel/boot/README.md b/kernel/boot/README.md new file mode 100644 index 0000000..a504180 --- /dev/null +++ b/kernel/boot/README.md @@ -0,0 +1,3 @@ +# boot + +boot process control and bootloader communication \ No newline at end of file diff --git a/kernel/boot/boot_info.h.md b/kernel/boot/boot_info.h.md new file mode 100644 index 0000000..a33ff63 --- /dev/null +++ b/kernel/boot/boot_info.h.md @@ -0,0 +1,13 @@ +# 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 +| Name | Description | +|-------------|---------------------------------------------------| +| framebuffer | struct with information about the graphics buffer | +| terminal | bootloader terminal / graphical log | +| memory_map | information about the memory layout / regions | +| kernel_file | The unparsed kernel ELF file | +| rsdp | _Root System Description Pointer_ | \ No newline at end of file diff --git a/kernel/boot/limine.h.md b/kernel/boot/limine.h.md new file mode 100644 index 0000000..acfdd69 --- /dev/null +++ b/kernel/boot/limine.h.md @@ -0,0 +1,4 @@ +# 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). diff --git a/kernel/drivers/README.md b/kernel/drivers/README.md new file mode 100644 index 0000000..e7c31ec --- /dev/null +++ b/kernel/drivers/README.md @@ -0,0 +1,3 @@ +# drivers + +everything from the graphics driver, to the FS drivers \ No newline at end of file diff --git a/kernel/drivers/acpi/README.md b/kernel/drivers/acpi/README.md new file mode 100644 index 0000000..a614abe --- /dev/null +++ b/kernel/drivers/acpi/README.md @@ -0,0 +1,5 @@ +# acpi + +This directory holds everything, that is needed to talk to the ACPI (_Advanced Configuration and Power Interface_). + +OSDev Wiki: [ACPI](https://wiki.osdev.org/ACPI) diff --git a/kernel/drivers/acpi/acpi.h.md b/kernel/drivers/acpi/acpi.h.md new file mode 100644 index 0000000..15ee8dc --- /dev/null +++ b/kernel/drivers/acpi/acpi.h.md @@ -0,0 +1,5 @@ +# acpi.h + +# `acpi_init(boot_info)` - function (void) +Initializes the ACPI implementation. +This function needs to be called once during the kernel initialization. diff --git a/kernel/drivers/acpi/rsdp.h.md b/kernel/drivers/acpi/rsdp.h.md new file mode 100644 index 0000000..55b897e --- /dev/null +++ b/kernel/drivers/acpi/rsdp.h.md @@ -0,0 +1,33 @@ +# rsdp.h + +The infrastructure to parse the _Root System Description Pointer_ Table. + +OSDev Wiki: [RSDP](https://wiki.osdev.org/RSDP) + +# `rsdp_descriptor_v1_T` - struct [packed] +The RSDP Table used in ACPI v1.0 + +| Name | Type | Description | +|--------------|----------|-----------------------------------------------------------| +| signature | char[8] | Needs to be `"RSD PTR "` (with the withespace at the end) | +| checksum | uint8_t | Used to validate the table | +| oem_id | char[6] | This string identifies the OEM | +| revision | uint8_t | Tells whether the RSDP is version 1 or 2+ | +| rsdt_address | uint32_t | The Physical Address of the RSDT | + +# `rsdp_descriptor_v2_T` - struct [packed] +The RSDP Table used in ACPI v2.0 or higher + +| Name | Type | Description | +|-------------------|-------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------| +| descriptor_v1 | [rsdp_descriptor_v1_T](https://nerdcult.net/projects/noxos/docs/codebase/drivers/acpi/rsdp.h/#rsdp_descriptor_v1_t---struct-packed) | A table in the format of the ACPI 1.0 specification | +| length | uint32_t | The size of the whole table | +| xsdt_address | uint64_t | The Address of the XSDT (when available this should be used instead of the RSDT) | +| checksum_extended | uint8_t | Used to calculate the checksum of the whole table | +| reserved | uint8_t[3] | Can be ignored | + +# `rsdp_descriptor_v1_verify(descriptor)` - function (bool) +Verifies the integrity of **_descriptor_**. + +# `rsdp_descriptor_v2_verify(descriptor)` - function (bool) +Verifies the integrity of **_descriptor_**. diff --git a/kernel/drivers/elf/README.md b/kernel/drivers/elf/README.md new file mode 100644 index 0000000..3cc8fc4 --- /dev/null +++ b/kernel/drivers/elf/README.md @@ -0,0 +1,3 @@ +# elf + +ELF executable parser. \ No newline at end of file diff --git a/kernel/drivers/elf/elf.h.md b/kernel/drivers/elf/elf.h.md new file mode 100644 index 0000000..0d31e70 --- /dev/null +++ b/kernel/drivers/elf/elf.h.md @@ -0,0 +1,32 @@ +# elf.h + +The ELF-parsers' heart. + +#### `elf_executable_T` - struct +This struct holds the parsed data of an ELF executable. + +| Name | Type | Description | +|--------------|----------------|----------------------------------------------------------------------------------------------------------------------------------| +| header | elf_header_T | The header of the elf file | +| num_symbols | uint64_t | The size of _symbols_ | +| symbols | symbol_T* | An array containing all symbols of the elf file | +| num_mappings | uint64_t | The size of _mappings_ | +| mappings | elf_mapping_T* | An array containing the mappings needed to load the elf file | +| string_table | void* | A copy of the elf files `.strtab` section, all strings are referenced here to have them available even if the elf file is closed | + +#### `elf_executable_temp_T` - struct +This struct is used while generating an elf_executable_T. +It holds parse-time information about the elf file. + +| Name | Type | Description | +|-----------------------------|-------------------|------------------------------------------------| +| executable | elf_executable_T* | A pointer to the final elf_executable_T | +| symbol_table | elf_section_T* | A pointer to `.symtab` in _buffer_ | +| section_header_string_table | elf_section_T* | A pointer to `.shstrtab` in _buffer_ | +| buffer | uint8_t* | The buffer where the executable is loaded from | + +#### `elf_executable_create(buffer)` - function (elf_executable_T*) +Generates an elf_executable_T from an elf file loaded to **_buffer_** and returns a pointer to it. + +#### `elf_executable_destruct(executable)` - function (void) +Frees all memory allocated for **_executable_**. \ No newline at end of file diff --git a/kernel/drivers/elf/header.h.md b/kernel/drivers/elf/header.h.md new file mode 100644 index 0000000..85ee938 --- /dev/null +++ b/kernel/drivers/elf/header.h.md @@ -0,0 +1,53 @@ +# header.h + +Definitions needed to parse the ELF Header. + +# `elf_target_architecture_E` - enum +Field in elf_header_T: **identity[4]** + +# `elf_endianness_E` - enum +Field in elf_header_T: **identity[5]** + +# `elf_sysabi_E` - enum +Field in elf_header_T: **identity[7]** + +# `elf_object_type_E` - enum +Field in elf_header_T: **type** + +# `elf_instruction_set_E` - enum +Field in elf_header_T: **isa** + +# `elf_header_T` - struct + +| Name | Type | Description | +|----------------------------|-------------|-------------------------------------------------------------------| +| identity | uint8_t[16] | Information like the used endian and the SysABI is stored in here | +| type | uint16_t | The type of the elf file -> elf_object_type_E | +| isa | uint16_t | The used instruction set -> elf_instruction_set_E | +| version | uint32_t | ELF version | +| address_entry_point | uint64_t | The start point for program execution | +| offset_program_header | uint64_t | The position of the program header array in the file | +| offset_section_header | uint64_t | The position of the section header array in the file | +| flags | uint32_t | Architecture dependent, can be ignored | +| len_header | uint16_t | The size of this header | +| len_program_header_entry | uint16_t | The size of one program header | +| num_program_header_entries | uint16_t | The amount of program headers | +| len_section_header_entry | uint16_t | The size of one section header | +| num_section_header_entries | uint16_t | The amount of section headers | +| string_section_index | uint16_t | The section header index of the `.shstrtab` section | + + +# `g_elf_target_architecture_strings` - global variable +An array of strings matching elf_target_architecture_E. + +# `g_elf_endianness_strings` - global variable +An array of strings matching elf_endianess_E. + +# `g_elf_sysabi_strings` - global variable +An array of strings matching elf_sysabi_E. + +# `g_elf_object_type_strings` - global variable +An array of strings matching elf_object_type_E. + +# `g_elf_instruction_set_strings` - global variable +An array of strings matching elf_instruction_set_E. \ No newline at end of file diff --git a/kernel/drivers/elf/mapping.h.md b/kernel/drivers/elf/mapping.h.md new file mode 100644 index 0000000..bb22578 --- /dev/null +++ b/kernel/drivers/elf/mapping.h.md @@ -0,0 +1,18 @@ +# mapping.h + +Handles the memory mappings that an ELF file can request. + +# `elf_mapping_T` - struct +A mapping describes an area of memory, +that should be copied from the elf file into the RAM and how/where it should be mapped. + +| Name | Type | Description | +|----------------|----------|------------------------------------------------------------------------------------------------------------------| +| offset_file | uint64_t | The mappings' start in the elf file | +| offset_virtual | uint64_t | The mappings' start in memory | +| length_file | uint64_t | The mappings' size in the elf file | +| length_virtual | uint64_t | The mappings' size in memory, if this is bigger than _length_file_ the remaining space will be filled with zeros | + +# `elf_mappings_apply(mappings, num_mappings, buffer, base, page_map)` - function (void) +Maps all **_mappings_** into **_page_map_** and copies the related data from **_buffer_** (elf file) to the mapped memory. +**_base_** specifies where the mappings should start in the virtual address space. diff --git a/kernel/drivers/elf/section.h.md b/kernel/drivers/elf/section.h.md new file mode 100644 index 0000000..68a04fc --- /dev/null +++ b/kernel/drivers/elf/section.h.md @@ -0,0 +1,34 @@ +# section.h + +Definitions needed to parse the elf section headers. + +# `elf_section_type_E` - enum +- **Null** - These sections can be ignored +- **Program Data** - These link to segments, if I remember right +- **Symbol Table** - Here are all the executables' symbols stored +- **String Table** - Here are all strings stored +- **RelocationA** - Contains relocation information +- **Hash** - Symbol Table hash table +- **Dynamic Link** - This provides information for the dynamic linker +- **Note** - notes that were created by the compiler / toolchain +- **Nobits** - Nulled data like `.bss` + +# `elf_section_T` - struct + +| Name | Type | Description | +|-----------------|----------|-------------------------------------------------------------------| +| name_offset | uint32_t | The offset of the sections name in `.shstrtab` | +| type | uint32_t | The type of the section -> elf_section_type_E | +| flags | uint64_t | Sections attribute flags | +| virtual_address | uint64_t | The address where the section should be mapped to (if it's not 0) | +| offset | uint64_t | The sections offset in the file | +| length | uint64_t | The size of the section | +| link | uint32_t | Type specific link to another section | +| info | uint32_t | Type specific information | +| alignment | uint64_t | If the section is aligned, this value specifies the alignment | +| entry_size | uint64_t | The size of the sections entries | + + +# `g_elf_section_type_strings` - global variable +An array of strings matching elf_section_type_E. + diff --git a/kernel/drivers/elf/segment.h.md b/kernel/drivers/elf/segment.h.md new file mode 100644 index 0000000..9a01c3f --- /dev/null +++ b/kernel/drivers/elf/segment.h.md @@ -0,0 +1,28 @@ +# segment.h + +Definitions needed to parse the elf program/segment headers. + +# `elf_segment_type_E` - enum +- **Null** - Unused segment +- **Load** - Segment that should be included into mappings +- **Dynamic** - Segments of this type contain dynamic linking information +- **Interpreter** - This holds a path to an interpreter +- **Note** - These segments hold notes by the compiler / toolchain +- **Program Header Table** - This points to the table that is holding the segment headers +- **TLS** - This holds a Thread Local Storage template + +# `elf_segment_T` - struct + +| Name | Type | Description | +|------------------|----------|-----------------------------------------------------------------| +| type | uint32_t | The segments type -> elf_segment_type_E | +| flags | uint32_t | The segments flags (Read / Write / Execute) | +| offset | uint64_t | The segments position in the elf file | +| address_virtual | uint64_t | Where the segment should be mapped in the virtual address space | +| address_physical | uint64_t | Not used in the `System V` ABI | +| length_file | uint64_t | The segments size in the file | +| length_memory | uint64_t | The size of the area that should be mapped for the segment | +| align | uint64_t | The segments alignment (has to be a power of 2) | + +# `g_elf_segment_type_strings` - global variable +An array of strings matching elf_segment_type_E. diff --git a/kernel/drivers/elf/symbol.h.md b/kernel/drivers/elf/symbol.h.md new file mode 100644 index 0000000..4ee1e9e --- /dev/null +++ b/kernel/drivers/elf/symbol.h.md @@ -0,0 +1,26 @@ +# symbol.h + +Stuff needed to extract symbols from an ELFs `.symtab` section. + +# `ELF_SYMBOL_TYPE(info)` - macro +Extracts the elf_symbol_type_E from the symbols info value. + +# `elf_symbol_type_E` - enum +- **None** - Unspecified type +- **Object** - Data objects like variables, arrays, etc. +- **Func** - Function +- **Section** - Associated section +- **File** - The path to the source file associated with the object +- **Common** - Uninitialized common blocks +- **TLS** - Thread Local Storage + +# `elf_symbol_T` - struct + +| Name | Type | Description | +|-----------------------|-------------------------------------------------------------------|-------------| +| name_offset | The offset of the symbols name in `.strtab` | | +| info | Information about the symbol (type, bind) | | +| other | Information about the symbol (visibility) | | +| related_section_index | The index of the symbols related section | | +| value | Value, in most cases this is an address | | +| length | The size of the symbol (e.g. num bytes if the symbol is an array) | | diff --git a/kernel/drivers/fs/README.md b/kernel/drivers/fs/README.md new file mode 100644 index 0000000..12f34dc --- /dev/null +++ b/kernel/drivers/fs/README.md @@ -0,0 +1,3 @@ +# fs + +Filesystem drivers. \ No newline at end of file diff --git a/kernel/drivers/fs/ramfs.h.md b/kernel/drivers/fs/ramfs.h.md new file mode 100644 index 0000000..e5e7c03 --- /dev/null +++ b/kernel/drivers/fs/ramfs.h.md @@ -0,0 +1,22 @@ +# ramfs.h + +Specific driver for RAMFS. + +**Warning:** This is a filesystem specific driver, by this it should only be accessed by the VFS. + +The ramfs (ram-filesystem) is not a filesystem in the common sense. +All data that is stored in ramfs is stored in the virtual file systems cache. +This means that all data in ramfs is temporary and erased after a reboot. + +# `ramfs_file_delete(node)` - function (void) +Frees the files cache space. This won't delete the node in the vfs. + +# `ramfs_file_write(node, size, buffer_in)` - function (void) +If this file has some cache space allocated, it will be freed. +Then there will be some cache space (**_size_** bytes) allocated and **_size_** bytes from **_buffer_in_** copied into the cache. + +This use of the vfs cache isn't a great solution and should be reworked. + +# `ramfs_file_read(node, size, buffer_out)` - function (void) +Copies **_size_** bytes from the files' cache to **_buffer_out_**. +This won't copy more bytes than the allocated cache space is big. diff --git a/kernel/drivers/fs/ustar.h.md b/kernel/drivers/fs/ustar.h.md new file mode 100644 index 0000000..d0d3fb0 --- /dev/null +++ b/kernel/drivers/fs/ustar.h.md @@ -0,0 +1,42 @@ +# ustar.h + +Specific driver for USTAR. + +**Warning:** This is a filesystem specific driver, by this it should only be accessed by the VFS. + +The USTAR '_filesystem_' is probably more common known as **tar**-archive. +It is a really simple concept, where a file consists of a header block followed by data blocks. +These blocks are aligned at 512 bytes. + +OSDev Wiki: [USTAR](https://wiki.osdev.org/USTAR) + +# `ustar_type_E` - enum +The types an entry can have: +- **File** +- **Hardlink** +- **Symlink** +- **Char Device** +- **Block Device** +- **Directory** +- **Pipe** + +# `ustar_header_T` - struct [packed / 512B aligned] + +| Name | Type | Description | +|-------------------|-----------|---------------------------------------------------------------------------| +| name | char[100] | The name of the entry | +| mode | uint64_t | file mode (permissions, etc) | +| owner_id | uint64_t | The owners ID | +| group_id | uint64_t | The groups ID | +| size | char[12] | The size of the entry, represented as a string of an octal number (dafuq) | +| last_modification | char[12] | The unix-timestamp, when the entry was modified the last time | +| checksum | uint64_t | I think this is a weird checksum of the header | +| type | uint8_t | The ustar_type_E of the entry, represented as ascii numbers (dafuq) | +| name_linked | char[100] | The path to the linked entry, if this is a link-entry | +| indicator | char[6] | This needs to be `ustar` | +| version | uint16_t | The version of the **tar** command, that created the archive | +| owner_user_name | char[32] | The name of the file owner | +| owner_group_name | char[32] | The name of the file group | +| device_major | uint64_t | The devices major number | +| device_minor | uint64_t | The devices minor number | +| name_prefix | char[155] | If this is not null, this acts as a prefix for _name_ | \ No newline at end of file diff --git a/kernel/drivers/fs/vfs.h.md b/kernel/drivers/fs/vfs.h.md new file mode 100644 index 0000000..7ad723e --- /dev/null +++ b/kernel/drivers/fs/vfs.h.md @@ -0,0 +1,146 @@ +# vfs.h + +**VFS** stands for _Virtual File System_ and is an abstraction layer, +that merges all mounted filesystems into one big virtual filesystem. +It provides a general API for dealing with files, and handles all filesystem specific stuff in the background. +This VFS is node based, meaning, that every file, directory, mount point, etc. is represented as a node in memory. +Nodes have a type and a fs. +Nodes can have children and next and previous nodes. + +Example node relations: +``` ++-----------+ +| Root Node | <---------+ ++-----------+ | + | | +[Childs] [Parent] + | +-------------+---------------+ + v / | \ ++-------+ +-------+ +-------+ +| Child | --[Next]-> | Child | --[Next]-> | Child | +| 1 | <-[Prev]-- | 2 | <-[Prev]-- | 3 | . . . ++-------+ +-------+ +-------+ + | | +[Childs] [Childs] + | | + v v + . . . . . . +``` + +If a node is accessed it is linked as the first node in the childs order, to make the name resolving process faster. + +# `VFS_MAX_NAME_LENGTH` - macro +The maximum length of a nodes name. +Bigger names will be cut of at the end. + +# `fs_type_E` - enum +This enum specifies all supported filesystems: +- **RAMFS** - A filesystem, that is bound very tight to the vfs and stores data completely in the RAM. + +# `vfs_node_type_E` - enum +This enum specifies all types a node can have: +- **Directory** - A directory can contain other nodes +- **File** - A file can hold data +- **Mount Point** - A mount point is like a directory, but in the vfs backend this resolves to the root of a filesystem +- **Block Device** - Neither used nor implemented yet + +# `fs_T` - struct +This struct specifies a filesystem instance. + +| Name | Type | Description | +|-----------|-------------|-------------------------------------------------------------| +| type | fs_type_E | The type of the filesystem | +| root_node | vfs_node_T* | A pointer to the vfs node of the filesystems root directory | + +# `vfs_node_cache_T` - struct +The current node caching system is just a small placeholder that will be reworked soon. + +| Name | Type | Description | +|-------------|-------------|-----------------------------------------------------| +| buffer | void* | The actual buffer, where data is cached | +| buffer_size | uint64_t | The size of _buffer_ | +| reclaimable | bool | Not used atm, but could be important after refactor | +| node | vfs_node_T* | The node, that the cache belongs to | + + +# `vfs_node_T` - struct + +| Name | Type | Description | +|------------|------------------|------------------------------------------------| +| name | char[] | The name of the node | +| type | vfs_node_type_E | The type of the node | +| cache | vfs_node_cache_T | The nodes cache segment | +| size | uint64_t | The nodes size | +| specific | void* | General purpose pointer (details below) | +| filesystem | fs_T* | The filesystem this node actually lies in | +| prev | vfs_node_T* | The previous node | +| next | vfs_node_T* | The next node | +| parent | vfs_node_T* | The parent node (has to be dir or mount point) | +| childs | vfs_node_T* | The first child node | + +## specific +The usage of this value is specific to th nodes type: +- **Directories:** NULL +- **Files:** NULL +- **Mount points:** a pointer to the mounted filesystem. +- **Block devices:** NULL + +# `g_root_fs` - global variable +The systems root filesystem. +Every node resolve will start at this filesystem. + +# `vfs_node_cache_create(node, size)` - function (vfs_node_cache_T*) +Allocates a **_size_** bytes big cache segment for **_node_**. + +# `vfs_node_cache_destruct(node_cache)` - function (void) +Frees **_node_cache_** and its buffer. + +# `vfs_node_create(parent, name, type, specific)` - function (vfs_node_T*) +Allocates a node with the given parameters. +The nodes _fs_ value is inherited from **_parent_**, +or from **_parent_**'s specific value if **_parent_** is a mount point. + +# `vfs_node_destruct(node)` - function (void) +Recursively destructs **_node_** and all it's children. + +# `vfs_node_dump_info(node, indent)` - function (void) +Prints the complete directory structure starting at **_node_**. +**_indent_** is used for the recursive calls and should be set to 0. + +# `vfs_node_resolve_child(node, child_name)` - function (vfs_node_T*) +Searches **_node_** for a child named **_child_name_**. +Returns the first matching child or NULL if no matching child was found. + +# `vfs_file_create(filesystem, path)` - function (vfs_node_T*) +Creates a file at **_path_** in **_filesystem_** and returns a pointer to it. +The directory in **_path_** needs to exist and the filename needs to not exist. + +# `vfs_file_delete(file)` - function (void) +Deletes **_file_**. + +# `vfs_file_write(file, position, size, buffer_in)` - function (void) +Writes **_size_** bytes from **_buffer_in_** at **_position_** into **_file_**. + +**Warning:** the current ramfs implementation will ignore **_position_**! + +# `vfs_file_read(file, position, size, buffer_out)` - function (void) +Reads **_size_** bytes from **_file_** at **_position_** into **_buffer_out_**. + +**Warning:** the current ramfs implementation will ignore **_position_**! + +# `vfs_directory_create(filesystem, path)` - function (vfs_node_T*) +Creates a directory at **_path_** in **_filesystem_** and returns a pointer to it. +The directory in **_path_** needs to exist and the name of the new directory (after the last `/`) needs to not exist. + +# `vfs_directory_delete(directory)` - function (void) [not implemented yet] +Deletes a directory. + +# `vfs_init(boot_info)` - function (void) +Initializes the VFS. +The initialization process includes, that the kernel unpacks the initial ramdisk to `/initrd/` + +# `vfs_resolve_path(filesystem, path)` - function (vfs_node_T*) +Returns the node at **_path_** or NULL if **_path_** is invalid. + +# `vfs_unpack_archive_ustar(filesystem, archive)` - function (void) +This will unpack a USTAR-archive (**_archive_**) at **_filesystem_**'s root. diff --git a/kernel/drivers/graphics/README.md b/kernel/drivers/graphics/README.md new file mode 100644 index 0000000..420b974 --- /dev/null +++ b/kernel/drivers/graphics/README.md @@ -0,0 +1,4 @@ +# graphics + +The graphics renderer is just for the development time. +As soon as the kernel supports modules, the renderer will be a module, or even an userspace program. \ No newline at end of file diff --git a/kernel/drivers/graphics/color.h.md b/kernel/drivers/graphics/color.h.md new file mode 100644 index 0000000..9e04add --- /dev/null +++ b/kernel/drivers/graphics/color.h.md @@ -0,0 +1,30 @@ +# color.h + +Provides basic color definitions and operations. + +# `color_palette_E` - enum +Indexes for g_color_palette. The color palette was designed by [gogh](https://gogh-co.github.io/Gogh/). +- **Grey Dark** +- **Pink** +- **Signal Green** +- **Orange** +- **Blue** +- **Purple** +- **Green** +- **Grey Light** +- **Red** + +# `color_argb_T` - struct +| Name | Type | Description | +|-------|---------|---------------------------------| +| alpha | uint8_t | Transparency value of the color | +| red | uint8_t | Red value of the color | +| green | uint8_t | Green value of the color | +| blue | uint8_t | Blue value of the color | + +# `color_argb_blend_alpha(background, foreground)` - function (color_argb_T) +Blends **_background_** and **_foreground_** with the _alpha_ value of **_foreground_**. + +# `g_color_palette` - global variable +An array of standard colors. +This array is indexed using color_palette_E. diff --git a/kernel/drivers/graphics/font.h.md b/kernel/drivers/graphics/font.h.md new file mode 100644 index 0000000..606e503 --- /dev/null +++ b/kernel/drivers/graphics/font.h.md @@ -0,0 +1,15 @@ +# font.h + +Basic bitmap font definitions. + +# `font_T` - struct + +| Name | Type | Description | +|------------|----------|------------------------------------------------| +| width | uint8_t | The width of each char (in pixels) | +| height | uint8_t | The height of each char (in pixels) | +| glyph_size | uint8_t | The amount of bytes a char takes in the buffer | +| buffer | uint8_t* | The buffer, where the char bitmaps lay | + +# `g_font` - global variable +A globally usable 8x8 font. diff --git a/kernel/drivers/graphics/framebuffer.h.md b/kernel/drivers/graphics/framebuffer.h.md new file mode 100644 index 0000000..60efd07 --- /dev/null +++ b/kernel/drivers/graphics/framebuffer.h.md @@ -0,0 +1,18 @@ +# framebuffer.h + +Framebuffer definitions. + +#### `framebuffer_T` - struct + +| Name | Type | Description | +|-----------------|----------|-----------------------------------------------------| +| address | void* | The address of the framebuffer | +| width | uint64_t | The pixel width of the framebuffer | +| height | uint64_t | The pixel height of the framebuffer | +| pitch | uint64_t | The number of bytes in each row | +| bits_per_pixel | uint16_t | The amount of bits a pixel consumes in the buffer | +| bytes_per_pixel | uint8_t | The amount of bytes a pixel consumes in the buffer | +| shift_red | uint8_t | How many bits the red value is shifted in a pixel | +| shift_green | uint8_t | How many bits the green value is shifted in a pixel | +| shift_blue | uint8_t | How many bits the blue value is shifted in a pixel | + diff --git a/kernel/drivers/graphics/renderer.h.md b/kernel/drivers/graphics/renderer.h.md new file mode 100644 index 0000000..d8c9ddf --- /dev/null +++ b/kernel/drivers/graphics/renderer.h.md @@ -0,0 +1,88 @@ +# renderer.h + +The renderer is maybe a bit over-engineered and slow. + +The renderer has a stack of buffers, which act like canvases. +You can create, move, hide and show buffers. + +#### `graphics_buffer_layer_E` - enum +- **Standard** - The layer, where almost everything should be on +- **Overlay** - This layer should be used for stuff like a mouse cursor, that should always be visible + +#### `graphics_buffer_T` - struct + +| Name | Type | Description | +|---------|--------------------------|------------------------------------------------------------------------------| +| buffer | g_color_palette* | The buffer, where all the pixels are stored | +| width | uint32_t | The width of the buffer | +| height | uint32_t | The height of the buffer | +| pos_x | uint32_t | The buffers x offset (from the top-left corner) in the renderers main buffer | +| pos_y | uint32_t | The buffers y offset (from the top-left corner) in the renderers main buffer | +| blocked | bool | Thread safety block variable | +| render | bool | Controls, if the buffer will be rendered or not | +| layer | graphics_buffer_layer_E | The layer, on which the buffer will be rendered | +| prev | graphics_buffer_layer_E* | The previous buffer in the rendering queue | +| next | graphics_buffer_T* | The next buffer in the rendering queue | + +#### `graphics_renderer_T` - struct + +| Name | Type | Description | +|------------------------|---------------------|------------------------------------------------------------------------------------------| +| framebuffer | framebuffer_T | The systems framebuffer (requested from bootloader) | +| back_buffer | uint32_t* | The buffer, where the final image is calculated, before sending it to the framebuffer | +| buffer_size | uint64_t | The size of `back_buffer` (in bytes) | +| graphics_buffer_layers | graphics_buffer_T** | List of pointers to the first graphics_buffer_T of every layer | +| font | font_T | The font, all graphics buffers use to draw chars (could be moved to `graphics_buffer_T`) | +| initialized | bool | Indicates whether the renderer is initialized or not | +| blocked | bool | Blocking variable that is used for thread safety in graphics_renderer_update() | + + +#### `graphics_buffer_request(pos_x, pos_y, width, height, layer)` - function (graphics_buffer_T*) +Allocates a graphics buffer and pushes it on top of the rendering queue of **_layer_**. + +#### `graphics_buffer_show(graphics_buffer)` - function (void) +Enables rendering for this buffer. +Every created buffer will be rendered by default. + +#### `graphics_buffer_hide(graphics_buffer)` - function (void) +Disables rendering for this buffer. + +#### `graphics_buffer_destruct(graphics_buffer)` - function (void) +Removes **_graphics_buffer_** from the rendering queue and frees its memory allocations. + +#### `graphics_buffer_shift_up(graphics_buffer, shift)` - function (void) +Shifts **_graphics_buffer_**'s content **_shift_** rows up. + +#### `graphics_buffer_set_pixel(graphics_buffer, x, y, color)` - function (void) +Sets a pixel with the given **_color_** at position(**_x_** | **_y_**) in **_graphics_buffer_**. +**_x_** and **_y_** are graphics buffer relative. + +#### `graphics_buffer_get_pixel(graphics_buffer, x, y)` - function (color_argb_T) +Returns the color of the pixel at position(**_x_** | **_y_**) in **_graphics_buffer_**. + +#### `graphics_buffer_draw_char(graphics_buffer, x, y, color, chr)` - function (void) +Draws a character (**_chr_**) at position(**_x_** | **_y_**) in **_graphics_buffer_**. +The position is the top-left corner of the char. + +#### `graphics_buffer_draw_string(graphics_buffer, x, y, color, string)` - function (position_T) +Draws **_string_** at position(**_x_** | **_y_**) in **_graphics_buffer_**. +The position is the top-left corner of the string. +Returns the position after the last char of the string. + +#### `graphics_renderer_init(boot_info)` - function (void) +Initializes the global graphics renderer. +Needs a pointer to `boot_info` to extract information about the framebuffer. + +#### `graphics_renderer_update()` - function (void) +Updates the renderers back_buffer and swaps it into the framebuffer. +To update the back_buffer, it iterates over the rendering queue and copies every buffer to the back_buffer. +If there are overlapping graphics_buffers, it alpha-blends them. + +#### `graphics_renderer_get_top_buffer(layer)` - function (graphics_buffer_T*) +Returns a pointer to the graphics_buffer, that is on top of the rendering queue of **_layer_**. + +#### `graphics_renderer_get_width()` - function (uint32_t) +Returns the width of the framebuffer. + +#### `graphics_renderer_get_height()` - function (uint32_t) +Returns the height of the framebuffer. diff --git a/kernel/drivers/pci.h.md b/kernel/drivers/pci.h.md new file mode 100644 index 0000000..035c582 --- /dev/null +++ b/kernel/drivers/pci.h.md @@ -0,0 +1,79 @@ +# pci.h + +PCI bus stuff. + +# Class and subclasses enums +All these enums are not documented in here, because they are basically just the definitions matching the PCI device main and sub classes. +A [list of these (sub)classes](https://wiki.osdev.org/PCI#Class_Codes) can be found in the osdev wiki. + +# `pci_device_header_T` - struct +| Name | Type | Description | +|-----------------|----------|------------------------------------------------------------------------------------------------------------------------------| +| vendor_id | uint16_t | The Device manufacturers ID number | +| device_id | uint16_t | The devices ID number | +| command_reg | uint16_t | Provides control over a device's ability to generate and respond to PCI cycles. | +| status | uint16_t | The status register PCI bus related events | +| revision_id | uint8_t | The devices revision ID number | +| progif | uint8_t | Programming Interface Byte. This can specify special programming interfaces. | +| subclass | uint8_t | The special function that the device performs. | +| main_class | uint8_t | The general function class, which the device operates in. | +| cache_line_size | uint8_t | Specifies the system cache line size in 32-bit units. | +| latency_timer | uint8_t | Specifies the latency timer in units of PCI bus clocks. | +| header_type | uint8_t | Specifies whether the device is a general device or a bridge. This affects the data representation that follows this header. | +| bist | uint8_t | Built-In-Self-Test status and control. | + +# `pci_header_0_T` - struct +| Name | Type | Description | +|----------------------------|---------------------|-------------------------------------------------------------------------------------------------| +| header | pci_device_header_T | The devices base header | +| bar0 | uint32_t | Base address 0 | +| bar1 | uint32_t | Base address 1 | +| bar2 | uint32_t | Base address 2 | +| bar3 | uint32_t | Base address 3 | +| bar4 | uint32_t | Base address 4 | +| bar5 | uint32_t | Base address 5 | +| cardbus_cis_pointer | uint32_t | Used by devices that share silicon between CardBus and PCI. | +| subsystem_vendor_id | uint16_t | idk, but probably not that important | +| subsystem_id | uint16_t | idk, but probably not that important | +| expansion_rom_base_address | uint32_t | An optional max 16MB ROM BAR. | +| capabilities | uint8_t | An offset in the devices config space that points to a linked list of implemented capabilities. | +| reserved | uint8_t[7] | Reserved. | +| interrupt_line | uint8_t | The devices interrupt IRQ. | +| interrupt_pin | uint8_t | The devices interrupt pin. | +| min_grant | uint8_t | Specifies the burst period length, in 1/4 microsecond units, that the device needs. | +| max_latency | uint8_t | Specifies how often the device needs access to the PCI bus (in 1/4 microsecond units). | + +# `pci_device_T` - struct +| Name | Type | Description | +|--------|----------------------|-------------------------| +| header | pci_device_header_T* | The devices base header | +| prev | pci_device_T* | The previous device. | +| next | pci_device_T* | The next device. | + +# `pci_manager_T` - struct +| Name | Type | Description | +|---------|---------------|-----------------------------------------------| +| devices | pci_device_T* | The linked list of devices connected via PCI. | + +# `pci_init()` - function (void) +Initializes the global PCI manager and enumerates the PCI bus. +This needs to be called after `acpi_init`, because it uses the _MCFG_ table. + +# `pci_manager_add_device(header*)` - function (void) +Adds a device to the global PCI manager. +This should only be called by the PCI enumerator. + +# `pci_manager_remove_device(device*)` - function (void) +Removes a device from the global PCI manager, and frees it resources in the manager. + +# `pci_manager_find_device(class, subclass, progif)` - function (pci_device_T*) +Returns the first device with **_class_**, **_subclass_** and **_progif_** that is defined in the global PCI manager. + +# `pci_manager_dump_devices()` - function (void) +Logs a list of all registered PCI devices. + +# `pci_get_subclass_string(class, subclass)` - function (string_t) +Returns the Name of **_class_** + **_subclass_**. + +# `pci_get_vendor_string(vendor_id)` - function (string_t) +Returns the name of the vendor. \ No newline at end of file diff --git a/kernel/drivers/ps2/README.md b/kernel/drivers/ps2/README.md new file mode 100644 index 0000000..c315056 --- /dev/null +++ b/kernel/drivers/ps2/README.md @@ -0,0 +1,4 @@ +# PS/2 + +The PS/2 standard for communicating with keyboards and mice. + diff --git a/kernel/drivers/ps2/controller.h.md b/kernel/drivers/ps2/controller.h.md new file mode 100644 index 0000000..b2944d5 --- /dev/null +++ b/kernel/drivers/ps2/controller.h.md @@ -0,0 +1,38 @@ +# controller.h + +Communicates with the PS/2 controller chip. + +**Warning:** This whole code needs to be reworked! + +# `PS2_CONTROLLER_DATA_PORT` - macro +The data transmission IO port. + +# `PS2_CONTROLLER_STATUS_PORT` - macro +The Status register IO port. + +# `PS2_CONTROLLER_COMMAND_PORT` - macro +The command transmission IO port. + +# `PS2_CONTROLLER_TIMEOUT` - macro +The amount of cycles the system waits for the controller before cancelling an operation. + +# `ps2_controller_init()` - function (void) +Initializes the PS/2 controller and devices. +At the moment it trusts very much stuff blindly. +This needs to be changed. +The osdev wiki has a list of stuff to do while initializing PS/2. + +# `ps2_controller_command(command)` - function (uint8_t) +Sends the PS/2 controller a command. + +# `ps2_controller_command_with_data(command, data)` - function (uint8_t) +Sends the PS/2 controller a command that needs additional data on the data port. + +# `ps2_controller_wait_until_ready_for_input()` - function (bool) +Halts until the status register says that there can be data read, or the timeout is reached. + +# `ps2_controller_wait_until_ready_for_output()` - function (bool) +Halts until the status register says that there can be data written, or the timeout is reached. + +# `ps2_controller_read_data()` - function (uint8_t) +Reads data from the PS/2 controller. \ No newline at end of file diff --git a/kernel/drivers/ps2/keyboard.h.md b/kernel/drivers/ps2/keyboard.h.md new file mode 100644 index 0000000..10f540f --- /dev/null +++ b/kernel/drivers/ps2/keyboard.h.md @@ -0,0 +1,24 @@ +# keyboard.h + +The driver for PS/2 keyboards. + + +# `ps2_keyboard_command_E` - enum +Commands that can be issued to the keyboard. + +# `ps2_keyboard_response_E` - enum +Responses that a keyboard can reply on a command. + +# `ps2_keyboard_command(command, data)` - function (uint8_t) +Sends a command to the keyboard. + +# `ps2_keyboard_init()` - function (void) +Initializes the keyboard driver. +This should only be called by the PS/2 controller init function. + +# `ps2_keyboard_read()` - function (void) +Reads a key from the keyboard and writes it to the tty. +This should be called when IRQ1 is fired. + +# `ps2_keyboard_command_to_string(command)` - function (string_t) +Returns a matching string for **_command_** in `ps2_keyboard_command_E`. diff --git a/kernel/drivers/ps2/scancodes.h.md b/kernel/drivers/ps2/scancodes.h.md new file mode 100644 index 0000000..1d53f1a --- /dev/null +++ b/kernel/drivers/ps2/scancodes.h.md @@ -0,0 +1,4 @@ +# scancodes.h + +This holds definitions on which key is mapped to which scancode. +Currently only scancode set 1 is supported. diff --git a/kernel/drivers/time/README.md b/kernel/drivers/time/README.md new file mode 100644 index 0000000..4b0cb22 --- /dev/null +++ b/kernel/drivers/time/README.md @@ -0,0 +1,5 @@ +# time + +Drivers for time related hardware. + +Tick. Tack. Tick. Tack. \ No newline at end of file diff --git a/kernel/drivers/time/pit.h.md b/kernel/drivers/time/pit.h.md new file mode 100644 index 0000000..4fc287c --- /dev/null +++ b/kernel/drivers/time/pit.h.md @@ -0,0 +1,14 @@ +# pit.h + +Communicates with the _Programmable Interval Timer_. + +#### `PIT_CHANNEL_0_PORT` - macro +The IO port, where channel 0 of the PIT (which is capable of firing IRQs) can be configured. + +#### `PIT_DIVISOR` - macro +The standard divisor, that noxos loads into channel 0 of the PIT. +`32768` fires an interrupt every `~27ms`, what is perfect for preemptive multithreading. + +#### `pit_set_divisor(divisor)` - function (void) +Loads **_divisor_** into channel 0 of the PIT. +If **_divisor_** is smaller than 100, it will be set to 100. \ No newline at end of file diff --git a/kernel/drivers/tty.h.md b/kernel/drivers/tty.h.md new file mode 100644 index 0000000..82536e9 --- /dev/null +++ b/kernel/drivers/tty.h.md @@ -0,0 +1,45 @@ +# tty.h + +The TTY is a virtual device, that acts as a text IO layer. +It prints keyboard input and process output to the screen. +The keyboard input can be directed to a processes stdin and the processes stdout can be printed to the screen. + +Schematic: +``` ++-------------------+ +| Graphics Renderer | ++-------------------+ + ^ ^ + | | +----------+ +-----------------+ + | | | TTY | | Process (shell) | + | | | | | | + | |--|-[Input]--|-<----|-[stdout] | + | | | | | +-[Keyboard]----->-|-[Output]-|->----| [stdin] | + +----------+ +-----------------+ + +``` + +# `tty_T` - struct +| Name | Type | Description | +|-----------------|--------------------|---------------------------------------------------------------------------------------------------| +| graphics_buffer | graphics_buffer_T* | The graphics buffer where all output will be rendered to. | +| output | pipe_T* | Points to the linked processes stdin pipe. | +| input | pipe_T | This pipes content will be rendered to the screen. The linked processes stdout should point here. | +| cursor | position_T | The cursors position. | +| color | color_argb_T | The current drawing color. | + +# `tty_init()` - function (void) +Initializes `g_tty`. + +# `tty_update()` - function (void) +Renders the text from the ttys _input pipe_ onto the screen. +This will be automatically called when writing into the ttys _input pipe_. + +# `tty_write(string)` - function (uint32_t) +Renders the text from **_string_** onto the screen. +This also writes **_string_** into the ttys _output pipe_. + +# `g_tty` - global variable +This is the systems TTY. +Currently, there is no support planned for multiple ttys. diff --git a/kernel/mm/README.md b/kernel/mm/README.md new file mode 100644 index 0000000..1cd13ff --- /dev/null +++ b/kernel/mm/README.md @@ -0,0 +1,3 @@ +# mm + +Memory management. \ No newline at end of file diff --git a/kernel/mm/heap.h.md b/kernel/mm/heap.h.md new file mode 100644 index 0000000..0a58ec6 --- /dev/null +++ b/kernel/mm/heap.h.md @@ -0,0 +1,44 @@ +# heap.h + +Dynamic memory allocator. + +# `heap_segment_T` - struct +This header lies in memory, directly before the accessible buffer of the related segment. + +| Name | Type | Description | +|-------|-----------------|------------------------------------------------------------------------------------------| +| magic | uint32_t | An out of bounds memory write would override this, what would indicate a heap corruption | +| size | uint64_t | The size of the segment | +| free | bool | If this is set, the segment is reclaimable | +| next | heap_segment_T* | The next segment in the heap | +| prev | heap_segment_T* | The previous segment in the heap | + + +# `heap_T` - struct + +| Name | Type | Description | +|--------------|-----------------|-------------------------------------------------------------| +| start | void* | The start of the heaps segment pool | +| end | void* | The current end of the heaps segment pool (growing upwards) | +| last_segment | heap_segment_T* | The current last segment in the heaps segment pool | + +# `heap_init(heap*, base)` - function (void) +Initializes **_heap_** at **_base_** (virtual address). +It will automatically map some page frames to that address. + +# `heap_memory_allocate(heap*, size)` - function (void) +Returns a pointer to a free usable memory location, that has at least the given **_size_**. +It will return `NULL` and log an error, if the heap is corrupted. +Because this function iterates over the entire heap to find a free segment, it is kinda slow. + +# `heap_memory_free(heap*, address)` - function (void) +Frees a with heap_memory_allocate() created heap segment, and makes it usable again. +Does nothing, if the address doesn't point to a valid heap segment. + +# `heap_dump_segments(heap*)` - function (void) +Logs a complete list, of all heap segments. +Useful, when debugging / testing the heap. + +# `heap_destruct(heap*)` - function (void) +Invalidates all segments of a heap, frees all used page frames and unmaps them. + diff --git a/kernel/mm/memory_map.h.md b/kernel/mm/memory_map.h.md new file mode 100644 index 0000000..dd40cc8 --- /dev/null +++ b/kernel/mm/memory_map.h.md @@ -0,0 +1,9 @@ +# memory_map.h + +Functions to parse the memory map provided by the bootloader. + +# `memory_map_get_total_memory_size(boot_info*)` - function (uint64_t) +Calculates the total amount of memory available, by iterating over the memory map. +The size is stored in a static variable, so no matter how often you call this function, the size will only be calculated once. +The total amount of memory is returned in bytes. + diff --git a/kernel/mm/page_frame.h.md b/kernel/mm/page_frame.h.md new file mode 100644 index 0000000..1b5d801 --- /dev/null +++ b/kernel/mm/page_frame.h.md @@ -0,0 +1,46 @@ +# page_frame.h + +Physical memory management. + +# `PFRAME_SIZE` - macro +The size of one page (4KB). + +# `page_frame_manager_T` - struct + +| Name | Type | Description | +|-------------------|----------|------------------------------------------------------------------------------------| +| free_memory | uint64_t | The amount of free/usable memory in bytes | +| reserved_memory | uint64_t | The amount of reserved memory in bytes | +| used_memory | uint64_t | The amount of memory used by noxos in bytes | +| page_bitmap_index | uint64_t | The index to the first free page | +| page_bitmap | bitmap_T | A huge bitmap, that stores, which pages are claimable and which are already in use | +| blocked | bool | Thread safety guard | + + +#### `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 `memory_allocate`. + +#### `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 `memory_free`. + +#### `pframe_free_multi(address, n)` - function (void) [Thread Safe] +Frees the page at the given address, plus *n* pages after that page. diff --git a/kernel/mm/page_map.h.md b/kernel/mm/page_map.h.md new file mode 100644 index 0000000..3ff5442 --- /dev/null +++ b/kernel/mm/page_map.h.md @@ -0,0 +1,95 @@ +# page_map.h + +Virtual memory management. + +Virtual memory spaces are a bit more tricky than the physical memory space. +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. + +# `VIRTUAL_ADDRESS_MAX` - macro +The highest mappable virtual address. +4 level page maps have a maximum address space of 256TB. + +# `page_map_flag_E` - enum +- **Present** - This indicates if the entry is used or should be ignored. Automatically set when mapping a page. +- **Read & Write** - A mapped Page is always readable. This flag allows writing to that page. +- **User Super** - If set, user mode access to the page is allowed. +- **Write Through** - Enables _Write Through Caching_ for this page. +- **Cache Disabled** - If this bit is set, the page won't be cached. +- **Accessed** - Set by the CPU, when this PDE or PTE was read. Won't be reset by the CPU. +- **Dirty** - Set when the page has been modified. +- **Larger Pages** - When this bit is set in a PDE or PTE, the entry points to a 1GB or 2MB page. +- **Custom 1 - 3** - Not used in NoxOS. +- **No Execute** - When this bit is set, the CPU won't execute code that lies in that page. + +# `page_map_T` - struct [page aligned] +This struct contains 512 entries. +These entries contain an address and flags. +The addresses link like this: +- **PML4** --> **Page Directory** or _1GB Page_ +- **Page Directory** --> **Page Table** or _2MB Page_ +- **Page Table** --> _4KB Page_ + +A pointer to a page_map_T can be loaded into `cr3` to load this pagemap. + +# `page_map_create()` - function (page_map_T*) +Allocates a page_map_T and returns a pointer to it. +The page map is populated with the mappings for the kernel executable and the loaded IDT. + +# `page_map_fetch_current()` - function (page_map_T*) [ASM implementation] +This function will return the page map, that is currently loaded. +To achieve this, it just reads the `cr3` register. + +# `page_map_load(page_map*)` - function (void) [ASM implementation] +Loads the given page map. +To achieve this, it writes the `cr3` register. + +# `page_map_map_memory(page_map*, virtual_address, physical_address, flags)` - function (void) +This maps **_physical_address_** to **_virtual_address_** in **_page_map_**. +The **_flags_** will be applied to the page mapping / page table entry. +It always applies the _Present_ flag automatically. + +# `page_map_unmap_memory(page_map*, virtual_address)` - function (void) +Removes a page mapping from the **_page_map_**. +Page map structure intern pages won't be checked if they're still needed or not. + +# `page_map_check_memory(page_map*, virtual_address)` - function (bool) +Check if there is a page mapped at **_virtual_address_** in **_page_map_**. +Returns _true_ if there is a page mapped and _false_ if not. + +# `page_map_get_physical_address(page_map*, virtual_address)` - function (void*) +Returns the physical address of the page, that is mapped to **_virtual_address_**. + +# `page_map_destruct(page_map*)` - function (void) +Clears a page map and frees all page map structure intern pages. + +# `page_map_dump_info(page_map)` - function (void) +Logs information about **_page_map_**, including a map of all mapped regions. +A region is a block of continuously mapped pages. + +# `page_map_entry_set_flags(entry, uint64_t flags)` - function (void) +This will set the provided flags to a page map entry. + +# `page_map_entry_get_flag(entry, page_map_flag_E flag)` - function (bool) +Returns if the given flag is set in the page map entry, or not. + +# `page_map_entry_set_address(entry, void* address)` - function (void) +This will set the provided address to a page map entry. + +# `page_map_entry_get_address(entry)` - function (void*) +This will read and return the address set in the page map entry. + +# `paging_init()` - function (void) +Initializes paging. +This reads the current page map set by the kernel and writes it to g_kernel_page_map. + +# `g_kernel_page_map` - global variable +The kernels page map. This page map is provided by the bootloader and read from `cr3` at paging_init. diff --git a/kernel/mm/region.h.md b/kernel/mm/region.h.md new file mode 100644 index 0000000..a960721 --- /dev/null +++ b/kernel/mm/region.h.md @@ -0,0 +1,35 @@ +# region.h + +Virtual memory space layout. + +The first 4 digits of an address can be ignored, they are also ignored by the MMU, +but for clarity / readability reasons they are `FFFF` in the kernel space. +See _General Concepts / Memory Layout_(todo: add reference) and _General Concepts / Process Memory Isolation_(todo: add reference) for more details. + +| Name | Start | Description | +|----------------------------------|--------------------|---------------------------------------------------| +| `MEM_REGION_PROCESS` | 0x0000000000000000 | This is the start of the process space | +| `MEM_REGION_PROCESS_EXEC` | 0x0000010000000000 | Every processes' executable will be mapped here | +| `MEM_REGION_PROCESS_THREAD_BASE` | 0x0000010100000000 | The start of the _Thread Data_ regions | +| `MEM_REGION_KERNEL` | 0xFFFF800000000000 | This is the start of the kernel space | +| `MEM_REGION_KERNEL_STACK_DUMMY` | 0xFFFFF00000000000 | This area is used when preparing a threads' stack | +| `MEM_REGION_KERNEL_HEAP` | 0xFFFFF80000000000 | The kernels' heap begins here | +| `MEM_REGION_KERNEL_THREAD_BASE` | 0xFFFFFF0000000000 | The kernel processes' _Thread Data_ regions | +| `MEM_REGION_KERNELEXEC` | 0xFFFFFFFF80000000 | The kernel executable is mapped here | + +# `MEM_REGION_THREAD_OFFSET` - macro +This time the threads id specifies its offset in its processes' _Thread Data_ region. + +# `KERNEL_START_ADDRESS` - macro +Returns the address of _kernel_start. + +# `KERNEL_END_ADDRESS` - macro +Returns the address of _kernel_end. + +# `_kernel_start` - global variable +This symbol is inserted by the linker at the beginning of the kernel. +To access its value use KERNEL_START_ADDRESS. + +# `_kernel_end` - global variable +This symbol is inserted by the linker at the end of the kernel. +To access its value use KERNEL_END_ADDRESS. diff --git a/kernel/mm/stack.h.md b/kernel/mm/stack.h.md new file mode 100644 index 0000000..319d82e --- /dev/null +++ b/kernel/mm/stack.h.md @@ -0,0 +1,10 @@ +# stack.h + +Functions to extract data from the call stack. + +# `stack_dump_call_info(rip, symbol)` - function (void) +Logs information about a call. +Give this function the **_rip_** of the call and the related **_symbol_**, to make it happy. + +# `stack_trace_call_stack(rbp)` - function (void) +Analyses the stack and recursively dumps information about all calls until it hits a call to `_start` or fails to resolve the calls symbol name. \ No newline at end of file diff --git a/kernel/platform/README.md b/kernel/platform/README.md new file mode 100644 index 0000000..82b7b49 --- /dev/null +++ b/kernel/platform/README.md @@ -0,0 +1,3 @@ +# platform + +Platform specific code. \ No newline at end of file diff --git a/kernel/platform/cpu.h.md b/kernel/platform/cpu.h.md new file mode 100644 index 0000000..ff84073 --- /dev/null +++ b/kernel/platform/cpu.h.md @@ -0,0 +1,45 @@ +# cpu.h + +Stuff related directly with 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 +- **cs** - Segment selector of the associated IDT descriptor +- **flags** - The CPU's FLAGS register, a status bitmap -> cpu_flags_E +- **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. +Such a state 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** diff --git a/kernel/platform/exceptions.h.md b/kernel/platform/exceptions.h.md new file mode 100644 index 0000000..c3f0226 --- /dev/null +++ b/kernel/platform/exceptions.h.md @@ -0,0 +1,15 @@ +# exceptions.h + +CPU-exception handling. + +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 CPU-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. diff --git a/kernel/platform/gdt.h.md b/kernel/platform/gdt.h.md new file mode 100644 index 0000000..9f6483c --- /dev/null +++ b/kernel/platform/gdt.h.md @@ -0,0 +1,49 @@ +# gdt.h +Definitions to handle segments (_Global Descriptor Table_). + +Segmentation is deprecated and is only needed for backwards compatibility. + +OSDev Wiki: [Global Descriptor Table](https://wiki.osdev.org/GDT) + +# `gdt_selector_E` - enum +- **Null** +- **Kernel Code** - Readable +- **Kernel Data** - Readable + Writable +- **User Null** +- **User Code** - Readable +- **User Data** - Readable + Writable + +# `gdt_descriptor_T` - struct [packed] + +| Name | Type | Description | +|--------|----------|-----------------------------------------------------| +| size | uint16_t | The tables size in bytes (-1) | +| offset | uint64_t | The virtual address, where the table lies in memory | + + +# `gdt_entry_T` - struct [packed] +| Name | Type | Description | +|--------------|----------|--------------------------------------------------------------| +| limit0 | uint16_t | Can be ignored in long mode | +| base0 | uint16_t | Can be ignored in long mode | +| base1 | uint8_t | Can be ignored in long mode | +| access | uint8_t | Specifies permissions (details in osdev wiki) | +| limit1_flags | uint8_t | The first 4 bits can be ignored and the last 4 specify flags | +| base2 | uint8_t | Can be ignored in long mode | + +# `gdt_T` - struct [packed / page aligned] +| Name | Type | Description | +|-------------|-------------|------------------------------------------| +| null | gdt_entry_T | The entry for `GDT_SELECTOR_NULL` | +| kernel_code | gdt_entry_T | The entry for `GDT_SELECTOR_KERNEL_CODE` | +| kernel_data | gdt_entry_T | The entry for `GDT_SELECTOR_KERNEL_DATA` | +| user_null | gdt_entry_T | The entry for `GDT_SELECTOR_USER_NULL` | +| user_code | gdt_entry_T | The entry for `GDT_SELECTOR_USER_CODE` | +| user_data | gdt_entry_T | The entry for `GDT_SELECTOR_USER_DATA` | + +# `g_default_gdt` - global variable +The systems GDT. + +# `gdt_init` - function (void) +Populates and loads g_default_gdt. +This will also set all the data segment registers to 0x10 (Kernel Data) and `cs` to 0x08 (Kernel Code). diff --git a/kernel/platform/interrupts.h.md b/kernel/platform/interrupts.h.md new file mode 100644 index 0000000..8a3c60f --- /dev/null +++ b/kernel/platform/interrupts.h.md @@ -0,0 +1,21 @@ +# interrupts.h + +The infrastructure to handle x86 interrupts. + +# `idt_register_T` - struct [packed] +This struct is very similar to gdt_descriptor_T. +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. + +# `g_handling_interrupt` - global variable +When the system isn't handling an interrupt this is set to 0. +If this is greater than 0 the system is currently handling an interrupt, + +# `idt_init()` - function (void) +This function fills all the interrupt gates (handlers) into the IDT and loads it. diff --git a/kernel/proc/README.md b/kernel/proc/README.md new file mode 100644 index 0000000..793398c --- /dev/null +++ b/kernel/proc/README.md @@ -0,0 +1,54 @@ +# proc + +The general processing structure is a bit more complex, +so I've split the schematics into multiple parts. + +Processes Schematic: +``` ++----------------+ +| Kernel Process | <----+ +| [Threads] | | ++----------------+ | + | [Parent] + [Childs] | + | +--------+--------+ + v / \ + +-----------+ +-----------+ + | Process 1 | --[Next]-> | Process 2 | + | [Threads] | <-[Prev]-- | [Threads] | . . . + +-----------+ +-----------+ + | | + [Childs] [Childs] + | | + v v + . . . . . . +``` + +Thread Schematics (processes view): +``` ++---------+ +| Process | <-------+ ++---------+ | + | [Process] + [Threads] | + | +--------+--------+ + v / \ ++----------+ +----------+ +| Thread 1 | --[LocalNext]-> | Thread 2 | +| | <-[LocalPrev]-- | | . . . ++----------+ +----------+ +``` + +Thread schematics (schedulers view): +``` + [RunningThread] + | + v + +----------+ +----------+ +----------+ ++---> | Thread 1 | --[GlobalNext]-> | Thread 2 | --[GlobalNext]-> | Thread 3 | . . . ----+ +| +-- | | <-[GlobalPrev]-- | | <-[GlobalPrev]-- | | . . . <-+ | +| | +----------+ +----------+ +----------+ | | +| | | | +| +------------------------------------[GlobalPrev]------------------------------------+ | ++--------------------------------------[GlobalNext]--------------------------------------+ +``` diff --git a/kernel/proc/file_descriptor.h.md b/kernel/proc/file_descriptor.h.md new file mode 100644 index 0000000..8bf8861 --- /dev/null +++ b/kernel/proc/file_descriptor.h.md @@ -0,0 +1,55 @@ +# file_descriptor.h + +Processes have no direct access to the VFS, instead they have file descriptors. + +File descriptors are numbers that represent files. +They are mostly used in file related syscalls. + +# `FILE_DESCRIPTOR_ARRAY_CHUNK_SIZE` - macro +The amount of file descriptors a `file_descriptor_array_chunk_T` (reference needed) can hold. + +# `file_descriptor_t` - typedef +This is a typedef of `ìnt32_t` and represents a file descriptor. + +# `std_file_descriptors_E` - enum +These are reserved file descriptors. +* `FILE_DESCRIPTOR_INVALID` - This represents an invalid file descriptor, just like NULL is an invalid pointer. +* `FILE_DESCRIPTOR_STDOUT` - This represents the file descriptor that is used, when writing to the Standard-Output stream. +* `FILE_DESCRIPTOR_STDIN` - This represents the file descriptor that is used, when reading from the Standard-Input stream. +* `FILE_DESCRIPTOR_STDERR` - This represents the file descriptor that is used, when writing to the Standard-Error stream. + +# `file_descriptor_array_chunk_T` - struct +| Name | Type | Description | +|--------|------------------------------------------------|----------------------------------------------------------------------------------------| +| prev | file_descriptor_array_chunk_T* | The previous chunk | +| next | file_descriptor_array_chunk_T* | The next chunk | +| lookup | vfs_node_T* [FILE_DESCRIPTOR_ARRAY_CHUNK_SIZE] | The array of file pointers, that the file descriptors reference | +| bitmap | bitmap_T | This bitmap indicates which file descriptors of this chunk are free nad which are used | +| amount | uint32_t | The amount of file descriptors which the chunk actually holds | + +# `file_descriptor_array_T` - struct +| Name | Type | Description | +|------------|--------------------------------|------------------------------| +| base_chunk | file_descriptor_array_chunk_T* | The first chunk in the array | + +# `file_descriptor_request(fd_array, node)` - function (file_descriptor_t) +Requests and returns new file descriptor, which will be linked with _**node**_. + +# `file_descriptor_resolve(fd_array, fd)` - function (vfs_node_T*) +Returns the VFS node, with which _**fd**_ is linked. + +# `file_descriptor_free(fd_array, fd)` - function (void) +Frees _**fd**_ and marks it as reclaimable. + +# `file_descriptor_array_alloc()` - function (file_descriptor_array_T*) +Allocates a new chunked file descriptor array. + +# `file_descriptor_array_destruct(fd_array)` - function (void) +Destructs _**fd_array**_ and all its resources, like e.g. chunks. + +# `file_descriptor_array_chunk_alloc(prev)` - function (file_descriptor_array_chunk_T*) +Allocates a new chunk for a file descriptor array. +_**prev**_ has to be the last chunk of an array or NULL when the chunk is the base chunk for a fresh file descriptor array. + +# `file_descriptor_array_chunk_destruct(chunk)` - function (void) +Destructs _**chunk**_ and all its resources. \ No newline at end of file diff --git a/kernel/proc/pipe.h.md b/kernel/proc/pipe.h.md new file mode 100644 index 0000000..b3af29e --- /dev/null +++ b/kernel/proc/pipe.h.md @@ -0,0 +1,44 @@ +# pipe.h + +Pipes are data streams between processes. + +# `PIPE_MAX_SENDERS` - macro +The maximum amount of processes, which can write data to one pipe. + +# `PIPE_STD_STREAM_SIZE` - macro +The size of a pipes stream buffer, in bytes. + +# `pipe_T` - struct +| Name | Type | Description | +|----------------|-------------------------------|-----------------------------------------------------------------------------------------| +| stream | stream_T* | The stream, where the pipes data is saved. | +| receiver | process_T* | The process which is allowed to read from the pipe. | +| senders | process_T* [PIPE_MAX_SENDERS] | The processes which are allowed to write to the pipe. | +| senders_bitmap | bitmap_T | Indicates which fields of _senders_ are currently used. | +| on_write | void function pointer | If this is not NULL, this function will be called when data is written into the stream. | + + +# `pipe_init(pipe*, receiver*, (*on_write)())` - function (void) +Initializes **_pipe_** and allocates a stream for it. + +# `pipe_destruct(pipe*)` - function (void) +Destructs **_pipe_** and frees all of its resources. + +# `pipe_add_sender(pipe*, sender*)` - function (bool) +Adds **_sender_** to the sender list of **_pipe_**. +Returns if the operation was successful. + +# `pipe_remove_sender(pipe*, sender*)` - function (void) +Removes **_sender_** from the sender list of **_pipe_**. + +# `pipe_write(pipe*, buffer_in*, n)` - function (uint64_t) +Writes at most **_n_** bytes from **_buffer_in_** into **_pipe_**. +Returns the amount of bytes that were actually written. +If the amount of actually written bytes is smaller than **_n_** all sender processes of **_pipe_** will be _PIPE_OUT blocked_. +If the receiver is _PIPE_IN blocked_ the blocker will be removed. + +# `pipe_read(pipe*, buffer_out*, n)` - function (uint64_t) +Reads at most **_n_** bytes from **_buffer_in_** into **_pipe_**. +Returns the amount of bytes that were actually read. +If the amount of actually read bytes is smaller than **_n_** the receiver process of **_pipe_** will be _PIPE_IN blocked_. +If the senders are _PIPE_OUT blocked_ the blockers will be removed. diff --git a/kernel/proc/process.h.md b/kernel/proc/process.h.md new file mode 100644 index 0000000..8b28bb8 --- /dev/null +++ b/kernel/proc/process.h.md @@ -0,0 +1,84 @@ +# process.h + +Processes are the containers, in which threads are organized. + +# `MAX_THREADS_PER_PROCESS` - macro +The maximum amount of threads a process can have. +This limitation is just for the bitmap, +the overall processing structure would be capable of processes with unlimited threads, in theory. + +# `THREAD_ID_INVALID` - macro +If process_get_thread_id() returns this, the process can't spawn one more thread. + +# `pid_t` - typedef +A typedef for `uint32_t`, used for process identification. +Such an identification number is also called `pid`. + +# `processes_standard_E` - enum +These are standard pids +- **None** - This pid is invalid, like `NULL` is an invalid pointer +- **Kernel** - The kernels' main process + +# `process_blockers_E` - enum +- **PIPE_OUT** - This blocker becomes activated, when the process tries to write to a pipe, but the pipe has not enough space for the data. It becomes deactivated, when the pipe has space to fit the rest of the data. +- **PIPE_IN** - This blocker becomes activated, when the process tries to read from a pipe, but the pipe has not the requested amount of data. It becomes deactivated, when the pipe contains data again. + +# `process_T` - struct + +| Name | Type | Description | +|-------------|----------------------------|-----------------------------------------------------------------------------------------| +| name | char[128] | The processes' name | +| id | pid_t | The process-identification number | +| chunk | void* | A pointer to the chunk, where the process is stored in | +| chunk_id | uint32_t | The processes id inside of its chunk | +| page_map | page_map_T* | The processes page map. | +| executable | elf_executable_T* | The processes executable | +| fd_array | file_descriptor_array_T* | Contains the open file descriptors of the process. | +| stdout | pipe_T* | Pointer to the pipe, where **stdout** writes to. | +| stdin | pipe_T | The pipe, where **stdin** reads from. | +| stderr | pipe_T* | Pointer to the pipe, where **stderr** writes to. | +| waiting | bitmap_T | A bitmap of process blockers. If this is greater 0 the process is blocked by something. | +| num_threads | uint32_t | The amount of spawned threads, that belong to the process | +| threads | void* | A pointer to the processes' first thread | +| thread_ids | bitmap_T(reference needed) | This bitmap keeps track of the local thread ids the process has | +| parent | process_T* | The process, that spawned this process | +| childs | process_T* | A pointer to the processes' first child process | +| prev | process_T* | The previous process | +| next | process_T* | The next process | + + +# `process_kernel_spawn(executable)` - function (void) +Spawns the kernels' main process. + +**Warning:** this should only be called once, when initializing the scheduler! + +# `process_spawn(parent, name, executable, buffer)` - function (pid_t) +Spawns a process named **_name_** as child of **_parent_** and returns its pid. +The process gets its own page map with the mappings specified in **_executable_**. +In order to apply these mappings, this function needs the **_buffer_** where the executable was loaded from. + +# `process_get_thread_id(process)` - function (int32_t) +Searches for a free thread id in the process. +If it finds one it returns it, else it returns THREAD_ID_INVALID. + +# `process_clear_thread_id(process, id)` - function (void) +Frees the thread **_id_** and makes it request-able again. + +# `process_pause_pid(pid)` - function (void) +Resolves the pids process and performs `process_pause` on it. + +# `process_pause(process)` - function (void) +Pauses **_process_** and all of its threads. + +# `process_start_pid(pid)` - function (void) +Resolves the pids process and performs `process_start` on it. + +# `process_start(process)` - function (void) +Starts **_process_** and all of its threads. + +# `process_kill_pid(pid)` - function (void) +Resolves the pids process and performs `process_kill` on it. + +# `process_kill(process)` - function (void) +Kills **_process_** and all of its threads and child processes. +This will also destruct the `executable` and `page_map` associated with **_process_**. diff --git a/kernel/proc/scheduler.h.md b/kernel/proc/scheduler.h.md new file mode 100644 index 0000000..ba35895 --- /dev/null +++ b/kernel/proc/scheduler.h.md @@ -0,0 +1,84 @@ +# scheduler.h + +The scheduler is responsible for switching between threads and controlling processes. + +#### `scheduler_processes_chunk_T` - struct +These chunks are a combination of static array and linked list. +They store the process_T pointer for each valid `pid_t`. + +| Name | Type | Description | +|------------------|------------------------------|------------------------------------------------------------------------------------| +| processes | process_T** | The array of process pointers | +| processes_bitmap | bitmap_T(reference needed) | If a bit in this bitmap is set, the _processes_ entry with the same index is valid | +| num_free_pids | uint32_t | The amount of free slots in this chunk | +| prev | scheduler_processes_chunk_T* | The previous chunk | +| next | scheduler_processes_chunk_T* | The next chunk | + + +#### `scheduler_T` - struct +| Name | Type | Description | +|----------------|------------------------------|--------------------------------------------------------------------| +| num_threads | uint32_t | Total amount of currently spawned threads | +| num_processes | uint32_t | Total amount of currently spawned processes | +| running_thread | thread_T* | A pointer to the currently running thread. | +| processes | scheduler_processes_chunk_T* | The first processes store chunk | +| blocked | bool | Set to true, while switching the context. Thread safety mechanism. | +| initialized | bool | Set to true, if the scheduler is initialized and started. | + +#### `scheduler_init(boot_info)` - function (void) +Initializes the scheduler and performs a `nx_scheduler_start` kernel syscall. +**_boot_info_** is needed in to spawn the kernels' main process. +After this function, the whole kernel is in scheduling mode. + +#### `scheduler_start(state)` - function (cpu_state_T*) +Creates and starts a thread from **_state_**. +It returns the result of a context switch, I forgot, why I did it like that. +This is basically the backend for the `nx_scheduler_start` kernel syscall. + +#### `scheduler_is_initialized()` - function (bool) +Returns if the scheduler is initialized (and running) or not. + +#### `scheduler_dump_info(process, indent)` - function (void) +This recursively lists information(pid, name, threads) for all child processes of **_process_**. +**_indent_** is used intern for the recursive calls and should be set to 0 initially. + +#### `scheduler_register_thread(thread)` - function (thread_T*) +Registers **_thread_** in the scheduler. + +#### `scheduler_pause_thread(thread)` - function (void) +Pauses **_thread_**, by removing it from the scheduling queue. + +**Potential Bug:** if **_thread_** was the currently running thread, +this could cause issues, because it's _prev_ and _next_ values are nulled. + +#### `scheduler_start_thread(thread)` - function (void) +Starts **_thread_**, by linking it into the scheduling queue. + +#### `scheduler_kill_thread(thread)` - function (void) +Pauses and unregisters **_thread_**. + +#### `scheduler_register_process(process)` - function (pid_t) +Reqisters **_process_** and returns its pid. + +#### `scheduler_pause_process(process)` - function (void) +Pauses **_process_** and its threads. + +#### `scheduler_start_process(process)` - function (void) +Starts **_process_** and its threads. + +#### `scheduler_kill_process(process)` - function (void) +Kills **_process_** and its threads and childs. + +#### `scheduler_get_process(pid)` - function (process_T*) +Returns the `process_T` pointer that is associated with **_pid_**. + +#### `scheduler_get_current_thread()` - function (thread_T*) +Returns a pointer to the currently running thread. + +#### `scheduler_get_current_process()` - function (process_T*) +Returns a pointer to the currently running threads process. + +#### `scheduler_switch_context(state)` - function (cpu_state_T*) +Saves **_state_** in the running threads _state_ value and increments their _cpu_time_ value. +Then it sets the next thread as the running thread and returns its _state_. +This needs to be called from an interrupt handler, for the returned state to be loaded. diff --git a/kernel/proc/thread.h.md b/kernel/proc/thread.h.md new file mode 100644 index 0000000..c63dbee --- /dev/null +++ b/kernel/proc/thread.h.md @@ -0,0 +1,43 @@ +# thread.h + +Threading infrastructure. + +# `thread_T` - struct +| Name | Type | Description | +|-------------|--------------|--------------------------------------------------------------------------------------------------| +| state | cpu_state_T* | The last saved state of the thread ( -> _context switching_(reference needed)) | +| cpu_time | uint64_t | The amount of cpu time the thread had. (currently the amount of context switches the thread had) | +| stack | void* | The bottom of the threads stack | +| stack_size | uint32_t | The size of the threads stack (in bytes) | +| process | process_T* | The process, to which the thread belongs to | +| global_prev | thread_T* | The previous thread in the scheduling queue (**should only be accessed by the scheduler!**) | +| global_next | thread_T* | The next thread in the scheduling queue (**should only be accessed by the scheduler!**) | +| local_prev | thread_T* | The previous thread of _process_ (**should only be accessed by the scheduler!**) | +| local_next | thread_T* | The next thread of _process_ (**should only be accessed by the scheduler!**) | +| local_id | uint32_t | The threads id in its process | + + +# `thread_spawn(function)` - function (thread_T*) +Allocates a thread_T and registers it in the scheduler. +The thread starts execution at **_function_**. +The for the thread allocated stack has a size of 16 KB (4 Pages). +The thread still needs to be started with thread_start(). +Returns a pointer to the created thread. + +# `thread_spawn_from_state(state)` - function (thread_T*) +Allocates a thread_T and registers it in the scheduler. +The threads' _cpu_state_ is copied from **_state_**. +This won't allocate a stack for the stack. +The thread still needs to be started with thread_start(). +Returns a pointer to the created thread. +This function should be avoided. + +# `thread_start(thread)` - function (void) +Starts/unpauses **_thread_**. + +# `thread_pause(thread)` - function (void) +Pauses **_thread_**. + +# `thread_kill(thread)` - function (void) +Kills **_thread_**. +The threads stack and thread_T structure will be freed. diff --git a/kernel/utils/README.md b/kernel/utils/README.md new file mode 100644 index 0000000..8298687 --- /dev/null +++ b/kernel/utils/README.md @@ -0,0 +1,3 @@ +# utils + +Basic utilities that are used almost everywhere. \ No newline at end of file diff --git a/kernel/utils/bitmap.h.md b/kernel/utils/bitmap.h.md new file mode 100644 index 0000000..d0e16f4 --- /dev/null +++ b/kernel/utils/bitmap.h.md @@ -0,0 +1,29 @@ +# bitmap.h + +Utils to handle bitmaps. + +# `bitmap_T` - struct + +| Name | Type | Description | +|-----------|----------|---------------------------------------| +| size | uint32_t | The size of _buffer_ (in bytes) | +| size_bits | uint32_t | The amount of storable bits | +| buffer | uint8_t* | The buffer, where the bits are stored | + +# `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) +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) +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. diff --git a/kernel/utils/core.h.md b/kernel/utils/core.h.md new file mode 100644 index 0000000..2bb5421 --- /dev/null +++ b/kernel/utils/core.h.md @@ -0,0 +1,19 @@ +# core.h + +All the utils, which I didn't know how to name. + + +# `CORE_INTERRUPTABLE_HALT_WHILE(a)` - macro +This halts until **_a_** is true. +Used when working with blocking variables in e.g. thread safe functions. +To avoid deadlocks, this macro won't halt, while the system is handling an interrupt. + +# `CORE_HALT_WHILE(a)` - macro +This halts until **_a_** is true. +Used when working with blocking variables in e.g. thread safe functions. + +**Warning:** When a function containing this macro is used while handling an interrupt, +this could cause deadlocks, consider using CORE_INTERRUPTABLE_HALT_WHILE instead. + +# `CORE_HALT_FOREVER` - macro +This halts forever and warns about this in the log. diff --git a/kernel/utils/io.h.md b/kernel/utils/io.h.md new file mode 100644 index 0000000..1497537 --- /dev/null +++ b/kernel/utils/io.h.md @@ -0,0 +1,15 @@ +# 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. + +# `io_wait()` - function (void) +Waits one IO cycle. +Should be used to give the devices enough time to respond. diff --git a/kernel/utils/logger.h.md b/kernel/utils/logger.h.md new file mode 100644 index 0000000..a5d8e8b --- /dev/null +++ b/kernel/utils/logger.h.md @@ -0,0 +1,18 @@ +# logger.h + +Functionalities to write logs to QEMU's serial port. + +# `DEBUG(string, ...)` - macro +calls `log` with log_level _Debug_. +Puts filename and line number in front of the format text. + +# `log_level_E` - enum +- **None** - Logs just the message without a prefix +- **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. +Format strings are supported. diff --git a/kernel/utils/math.h.md b/kernel/utils/math.h.md new file mode 100644 index 0000000..878cbb9 --- /dev/null +++ b/kernel/utils/math.h.md @@ -0,0 +1,35 @@ +# 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. + +# `position_T` - struct +This describes a position in 2D space. + +| Name | Description | +|------|------------------------------| +| x | X coordinate of the position | +| y | Y coordinate of the position | + + +# `pow(base, exponent)` - function (uint64_t) +Returns the power of `base ^ exponent`. + +# `abs(number)` - function (uint64_t) +Returns the absolute value of **_number_**. + +# `octal_string_to_int(string, size)` - function (uint64_t) +Converts a base-8 **_string_** with length **_size_** into an integer and returns it. diff --git a/kernel/utils/memory.h.md b/kernel/utils/memory.h.md new file mode 100644 index 0000000..5473ede --- /dev/null +++ b/kernel/utils/memory.h.md @@ -0,0 +1,32 @@ +# 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_. + +# `memory_allocate(size)` - function (void*) +Returns the address to a buffer, that is at least **_size_** bytes big. +On linux this function is called _malloc_. + +# `memory_free(address)` - function (void) +Free the buffer at address and marks it claimable again , this buffer needs to be a buffer, that was created with memory_allocate(). +On linux this function is called _free_. + +# `memory_allocator_init(base)` - function (void) +This initializes the heap, where memory_allocate() allocates memory. + +# `memory_hexdump(address, num)` - function (void) +Logs **_num_** bytes from **_address_** as 8 byte rows. +The data is represented in hexadecimal and ascii. diff --git a/kernel/utils/panic.h.md b/kernel/utils/panic.h.md new file mode 100644 index 0000000..a9f6eb0 --- /dev/null +++ b/kernel/utils/panic.h.md @@ -0,0 +1,8 @@ +# panic.h + +ahhhh - the kernel is burning! + +# `panic(state, message)` - function (void) +This prints out the error message, a stack backtrace and a register dump. +After that, the kernel halts forever. +This function is called, when a fatal error occurs diff --git a/kernel/utils/stdtypes.h.md b/kernel/utils/stdtypes.h.md new file mode 100644 index 0000000..9292263 --- /dev/null +++ b/kernel/utils/stdtypes.h.md @@ -0,0 +1,55 @@ +# 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 signed 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. diff --git a/kernel/utils/stream.h.md b/kernel/utils/stream.h.md new file mode 100644 index 0000000..dc87ca8 --- /dev/null +++ b/kernel/utils/stream.h.md @@ -0,0 +1,27 @@ +# stream.h + +Streams are cycled buffers, that have __one__ input and __one__ output. + +# `stream_T` - struct + +| Name | Type | Description | +|--------------|----------|----------------------------------------------------------------------------------| +| buffer | uint8_t* | The buffer where all the streams data is stored in. | +| size | uint32_t | The size of _buffer_ in bytes. | +| pos_sender | uint32_t | The senders (input) position in the buffer. | +| pos_receiver | uint32_t | The receivers (output) position in the buffer. This is always behind the sender. | + + +# `stream_alloc(size)` - function (stream_T*) +Allocates and returns a new stream, with a buffer of size **_size_**. + +# `stream_destruct(stream)` - function (void) +Frees the resources of a stream. + +# `stream_write(stream, buffer_in, n)` - function (uint32_t) +Writes at most **_n_** bytes from **_buffer_in_** into **_stream_**. +Returns the amount of bytes, that where actually written into the stream. + +# `stream_read(stream, buffer_out, n)` - function (uint32_t) +Reads at most **_n_** bytes from **_stream_** into **_buffer_out_**. +Returns the amount of bytes, that where actually read from the stream. \ No newline at end of file diff --git a/kernel/utils/string.h.md b/kernel/utils/string.h.md new file mode 100644 index 0000000..b4cf1c9 --- /dev/null +++ b/kernel/utils/string.h.md @@ -0,0 +1,90 @@ +# string.h + +Basic functions for string manipulation. + +#### `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. + +#### `string_find_next(string, chr)` - function (uint32_t) +Returns the index of the next character that matches **_chr_** in **_string_**. + +#### `string_find_last(string, chr)` - function (uint32_t) +Returns the index of the last character that matches **_chr_** in **_string_**. + +#### `variadic_format_size(string, args)` - function (uint64_t) +Returns how long a format string with the given pattern (**_string_**) and **_args_** would be. +Useful to create a big enough buffer before formatting a string. + +#### `format_size(string, ...)` - function (uint64_t) +This calls `variadic_format_size`, but instead of giving it a `va_list` you can give this function the actual arguments. + +#### `variadic_format(output, string, args)` - function (void) +Formats **_string_** with **_args_** and writes the product to **_output_**. +The rules for format strings are specified on top of this document in the _General concepts_ block. + +#### `format(output, string, ...)` - function (void) +This calls `variadic_format`, but instead of giving it a `va_list` you can give this function the actual arguments. + +#### `string_unsigned_dec_to_alpha(string, value)` - function (void) +Converts the unsigned integer in **_value_** to an alphanumeric string. +The representation is decimal. +This string will be written into **_string_**. + +#### `string_dec_to_alpha(string, value)` - function (void) +Converts the signed integer in **_value_** to an alphanumeric string. +If it is negative it will be prefixed with a hyphen. +The representation is decimal. +This string will be written into **_string_**. + +#### `string_hex_8bit_to_alpha(string, value)` - function (void) +Converts the byte in **_value_** to an alphanumeric string. +The representation is hexadecimal. +This string will be written into **_string_**. + +#### `string_hex_16bit_to_alpha(string, value)` - function (void) +Converts the word(16-bits) in **_value_** to an alphanumeric string. +The representation is hexadecimal. +This string will be written into **_string_**. + +#### `string_hex_32bit_to_alpha(string, value)` - function (void) +Converts the dword(32-bits) in **_value_** to an alphanumeric string. +The representation is hexadecimal. +This string will be written into **_string_**. + +#### `string_hex_64bit_to_alpha(string, value)` - function (void) +Converts the qword(64-bits) in **_value_** to an alphanumeric string. +The representation is hexadecimal. +This string will be written into **_string_**. + +#### `string_bin_to_alpha(string, num_bits, value)` - function (void) +Converts the data in **_value_** to an alphanumeric string. +The representation is binary. +**_num_bits_** specifies how many bits, starting at the least significant bit, will be converted. +This string will be written into **_string_**. + +#### `string_bool_to_alpha(string, value`) - function (void) +Converts the boolean in **_value_** to an alphanumeric string. +The representation is `true` or `false`. +This string will be written into **_string_**. + +#### `string_is_char_text(chr)` - function (bool) +Returns whether the char (**_chr_**) contains text(a-z, A-Z, 0-9, special chars) or not. + +#### `string_is_char_number(chr)` - function (bool) +Returns whether the char (**_chr_**) is a number(0-9) or not. + +#### `string_is_char_alpha(chr)` - function (bool) +Returns whether the char (**_chr_**) is alphanumeric(a-z, A-Z, 0-9) or not. + +#### `string_is_char_uppercase(chr)` - function (bool) +Returns whether the char (**_chr_**) is uppercase(A-Z) or not. + +#### `string_is_char_lowercase(chr)` - function (bool) +Returns whether the char (**_chr_**) is lowercase(a-z) or not. diff --git a/kernel/utils/symbol.h.md b/kernel/utils/symbol.h.md new file mode 100644 index 0000000..4f6bcdf --- /dev/null +++ b/kernel/utils/symbol.h.md @@ -0,0 +1,22 @@ +# symbol.h + +Basic functions to define and resolve symbols. + +#### `symbol_type_E` - enum +- **Function** +- **Variable** +- **Unknown** + +#### `symbol_T` - struct + +| Name | Type | Description | +|---------|---------------|-------------------------------------------------------------------------------------| +| name | string_t | The name of the symbol (e.g. the name of the kernels entry symbol would be `_start` | +| type | symbol_type_E | The symbols type (elf types like `File` are of type `Unknown`) | +| address | uint64_t | The symbols address | + +#### `symbol_resolve_from_name(symbols, num_symbols, name);` - function (symbol_T*) +This searches **_symbols_** for a symbol with a matching **_name_**. + +#### `symbol_resolve_from_rip(symbols, num_symbols, rip);` - function (symbol_T*) +Give it a list of **_symbols_** and an instruction pointer (**_rip_**) and it will return the symbol (function), where **_rip_** lays in. diff --git a/roadmap.md b/roadmap.md new file mode 100644 index 0000000..7f0d022 --- /dev/null +++ b/roadmap.md @@ -0,0 +1,30 @@ +# Roadmap + +- [x] Bootable system +- [x] Logger +- [x] Page frame manager +- [x] Interrupts +- [x] Page maps +- [x] Heap +- [x] Format strings +- [x] Graphics Renderer + - [x] Text + - [x] Double buffering + - [x] Buffer requests +- [x] Panic Screen + - [x] Register dump + - [x] Stack tracing +- [x] Scheduler +- [x] (Kernel) Threads +- [x] Ramdisk + - [x] USTAR + - [x] RAMFS + - [x] VFS +- [x] ELF loading +- [x] Processes +- [X] Keyboard input (ps/2 int) +- [ ] Shell +- [X] JSON parser for system config +- [ ] FAT32 +- [ ] Text Editor +- [ ] TCC \ No newline at end of file diff --git a/sysabi.md b/sysabi.md new file mode 100644 index 0000000..af1b84d --- /dev/null +++ b/sysabi.md @@ -0,0 +1,80 @@ +# SysABI + +Syscalls are a way for programms to communicate with the kernel. + +To perform a syscall, you need to populate the following registers: + +| Register | Value | +|----------|-----------------| +| rax | The syscalls ID | +| rdi | Argument 1 | +| rsi | Argument 2 | +| rdx | Argument 3 | +| rcx | Argument 4 | + +--- + +The following calls should be implemented to some degree in noxos 1.0. + +# Categories +## Files +| ID | Name | Description | Arg1 | Arg2 | Arg3 | Arg4 | Result | Status | +|--------|--------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------|--------|------|-------------|--------|-------------| +| 0x0101 | `nx_fopen` | Opens the file at the _len_ bytes long path _path_ and writes a file descriptor to the referenced file into _fd_ (which needs to be a pointer). | path | len | *fd | | status | Implemented | +| 0x0102 | `nx_fclose` | Closes the file which is indicated by descriptor _fd_. This should always be called, otherwise the OS will have to unload files without knowledge of usage. | fd | | | | status | Implemented | +| 0x0103 | `nx_fread` | Reads at most _n_ bytes from a file given as descriptor _fd_ and at a specific position _offset_ into a given memory region _mem_. | fd | offset | mem | n | status | Implemented | +| 0x0104 | `nx_fwrite` | Writes _n_ bytes from a given memory region _mem_ into the file referenced by _fd_ at the given position _offset_, not inserting but either overwriting existing content or appending to the file. | fd | offset | mem | n | status | Implemented | +| 0x0105 | `nx_fdelete` | Completely delete the file or folder at a given path _path_, which is _len_ bytes long. | path | len | | | status | Implemented | +| 0x0106 | `nx_flist` | List all files and/or directories at the _len_ bytes long path _path_ and write their NULL-separated names into _mem_. When _mem_ is NULL, _needed_mem_ (which needs to be a pointer to an 32-bit integer) is filled with the appropriate value. | path | len | mem | *needed_mem | status | Implemented | +| 0x0107 | `nx_finfo` | Writes the information about the files attribute _attr_ into mem. Types of attributes are described below. | fd | attr | mem | | status | N/A | + +**Note:** The _len_ argument of paths isn't used at the moment, rather than using _len_, _path_ needs to be Null-Terminated. + +## Memory +| ID | Name | Description | Arg1 | Arg2 | Arg3 | Arg4 | Result | Status | +|--------|-------------|-------------------------------------------------------------------------------------------------------------------------------------------------|------|------|-------|------|--------|-------------| +| 0x0201 | `nx_mmap` | Maps _n_ 4KB pages to address _addr_. You can provide a bitmap of flags with the _flags_ argument. Which flags can be used, is described below. | addr | n | flags | | status | Implemented | +| 0x0202 | `nx_munmap` | Unmaps _n_ 4KB pages at address _addr_. | addr | n | | | status | Implemented | + +## Processes +| ID | Name | Description | Arg1 | Arg2 | Arg3 | Arg4 | Result | Status | +|-----|------|-------------|------|------|------|------|--------|--------| +| | | | | | | | | | + +## Runtime / Dynamic Linker +| ID | Name | Description | Arg1 | Arg2 | Arg3 | Arg4 | Result | Status | +|-----|------|-------------|------|------|------|------|--------|--------| +| | | | | | | | | | + +## Compatibility & Safety +| ID | Name | Description | Arg1 | Arg2 | Arg3 | Arg4 | Result | Status | +|-----|------|-------------|------|------|------|------|--------|--------| +| | | | | | | | | | + +## Kernel +The kernel syscalls can only be called from the kernels main process [link to processing article needed]. +If another process calls them, they will just return without doing anything. + + +| ID | Name | Description | Arg1 | Arg2 | Arg3 | Arg4 | Result | Status | +|-----|------|-------------|------|------|------|------|--------|--------| +| | | | | | | | | | + +--- + +## Appendixes + +### Types of file attributes + +| ID | Name | Description | Data Type | Status | +|-----|---------------|--------------------------------------------|-----------|--------| +| 0 | `permissions` | Who has what permission to access the file | uint16_t | N/A | +| 1 | `size` | The files size in bytes | uint64_t | N/A | + + +### Memory mapping flags + +| Bit | Name | Description | +|-----|-----------|-------------------------------------------| +| 0 | `write` | Enables write access to the mapped pages. | +| 1 | `no_exec` | Prevents execution of the mapped pages. |