diff --git a/design/STYLE.md b/design/STYLE.md new file mode 100644 index 0000000..a239f5d --- /dev/null +++ b/design/STYLE.md @@ -0,0 +1,135 @@ +# Style Guide for Design Files + + + +\[ [Table of Contents](#table-of-contents) \] +\[ [Inline Code](#inline-code) \] +\[ [Note and ToDO](#note-and-todo) \] +\[ [Alerts / Callouts / Admonitions](#alerts--callouts--admonitions) \] + +## Table of Contents + +The auto-generated bullet point list has very limited control over content and +styling with editors like vscode where the list is automatically updated. A +cleaner solution is a single line linking to the primary sections of the +document, showing only a single level (eg. all level 2 headers). + +**Example** this is the ToC for this document. A comment is included to explain +what headers are included for future additions or changes. + +```markdown + +\[ [Table of Contents](#table-of-contents) \] +\[ [Inline Code](#inline-code) \] +\[ [Note and ToDO](#note-and-todo) \] +\[ [Alerts / Callouts / Admonitions](#alerts--callouts--admonitions) \] +``` + +One drawback is the need for manual updates, however these headers are not +frequently updated for well established documents. + +## Inline Code + + +Inline code can be used to display potentially ambiguous characters (eg. lower +and upper case L, letter O and number 0) and to distinguish text from it's +surroundings like hexadecimal numbers (eg. `0x123`). It's use is not mandatory +and typically used as needed rather than by default. + + +Inline code, however, reduce the contrast between text and background +making long strings of repeated characters more difficult to read (eg. `0000` vs +0000) or close, similar patterns of characters (eg. `0x0000` near `0x0600` vs +0x0000 near 0x06000). In most case, **bold** can be used to distinguish text +from it's surroundings (eg. **0x00000** near **0x06000**). Avoid using inline +code for tables, near formulas, in headers and in links. Exceptions can be made +when deemed necessary. Put a comment `` near these exceptional use cases +to explain why they are appropriate. + + +**Good Usage** - Inline hexadecimal numbers with area between + +> Kernel Size in Protected Mode is smaller than in real mode. Reserved memory in +> protected mode starts at `0x9fc00` while real mode starts at `0xa0000` + +**Bad Usage** - Hexadecimal column values in a table, smaller font with lower contrast + +> | Start | End | size | description | +> | -------- | --------- | --------- | -------------------------------------- | +> | `0x0000` | `0x4ff` | 1.25 KiB | Bad, small font with low contrast | +> | `0x0500` | `0x00fff` | 1.25 KiB | Bad, small font with low contrast | + +Compared to + +> | Start | End | size | description | +> | -------- | --------- | --------- | -------------------------------------- | +> | 0x7000 | 0x07bff | 3 KiB | Good, larger font with higher contrast | +> | 0x7c00 | 0x07dff | 512 bytes | Good, larger font with higher contrast | + +**Bad Usage** - Mix of numbers with plain text numbers and inline code + +>- Page size = 4096 (`0x1000`) +>- Bits per page = Page Size * 8 = 4096 * 8 = 32768 (`0x8000`) +>- Max pages per region = Bits per page = 32768 (`0x8000`) (includes bitmask page) +>- Max region size = Max pages per region * Page size = 32768 * 4096 = 134217728 +> (`0x8000000`) = 128 MiB + +**Bad Usage** - Numbers in formula without the operators + +> Bits per page = Page Size * `8` = `4096` * `8` = `32768` (`0x8000`) + +If you're going to quote a formula, include all operators and numbers in a +single quote. Exceptions can be made where impractical. + +**Good Usage** - Formula including numbers and operators + +> Bits per page = `Page Size * 8` = `4096 * 8` = `32768 (0x8000)` + +**Bad Usage** - Quote entire line + +> `Bits per page = Page Size * 8 = 4096 * 8 = 32768 (0x8000)` + +If a quote spans the entire line, try to use a code block instead. Code blocks +use a larger font with higher contrast between letters and background. + +> ``` +> Bits per page = Page Size * 8 = 4096 * 8 = 32768 (0x8000) +> ``` + +## Note and ToDo + +An alternative to alerts ia **Note** and **ToDo** (can also be upper case +**NOTE** and **TODO**). These are bold at the start of a paragraph followed by +non-bold text. **Note** is typically used to communicate details that may be +unintuitive or not obvious, but are not important enough to ues an alert. +**ToDo** is typically used as a note or reminder to the writer for future +content and communicates to the reader that a section may be incomplete or +inaccurate. + +When used with all caps, **TODO** can also be highlighted by vscode using the +[TODO Highlights](https://marketplace.visualstudio.com/items?itemName=wayou.vscode-todo-highlight) +extension. + +## Alerts / Callouts / Admonitions + +Alerts can be useful to call attention to some information or visually break up +sections of text. To retain meaning and effectiveness at capturing the readers +attention, alerts should be uses sparingly and with short content. + +**Note** In vscode, alerts can have an altered title by following the type `[!...]` with +some text. This fails to render in GitHub so should be avoided. + +> [!NOTE] +> Note block + +> [!TIP] +> Tip block + +> [!IMPORTANT] +> Important block + +> [!WARNING] +> Warning block + +> [!CAUTION] +> Caution block diff --git a/design/boot_stages.md b/design/boot_stages.md index 25468ab..43bf99e 100644 --- a/design/boot_stages.md +++ b/design/boot_stages.md @@ -1,5 +1,11 @@ # Boot Stages + +\[ [Stage 0 - BIOS](#stage-0---bios) \] +\[ [Stage 1 - Boot](#stage-1---boot) \] +\[ [Stage 2 - Loader](#stage-2---loader) \] +\[ [Stage 3 - OS](#stage-3---os) \] + This describes the planned stages and steps, it does not represent the current implementation or progress. @@ -9,22 +15,22 @@ The BIOS firmware does a lot more than this, only the steps to launch the kernel are included. 1. Power On Self Test (POST) -2. Load boot sector (512 Bytes) into memory at `0x7c00` -3. Jump to `0x7c00` +2. Load boot sector (512 Bytes) into memory at 0x7c00 +3. Jump to 0x7c00 ## Stage 1 - Boot Execution of the first 512 bytes "boot sector". 1. Store boot drive id from `dl` register -2. Set stack `sp` and base `bp` pointers to `0x6fff` -3. Read memory map to `0x500` - 1. Detect and store lower memory size using `int 0x12` - 2. Detect upper memory regions using `int 0x15` with `aex = 0xe820` -4. Read stage 2 from boot drive to `0x7e00` +2. Set stack `sp` and base `bp` pointers to 0x6fff +3. Read memory map to 0x500 + 1. Detect and store lower memory size using interrupt 18 (`int 0x12`) + 2. Detect upper memory regions using interrupt 18 (`int 0x15`) with aex = 0xe820 +4. Read stage 2 from boot drive to 0x7e00 5. Setup GDT (kernel) 6. Switch to protected mode -7. Jump to loader at `0x7e00` +7. Jump to loader at 0x7e00 ## Stage 2 - Loader @@ -42,11 +48,11 @@ initialize the kernel then load and launch init program. 5. Initialize GDT 6. Initialize TSS 7. Enable paging -8. Initialize kernel (`kernel_init`) +8. Initialize kernel (**kernel_init**) 1. Clear kernel struct 2. Install ISR and IDT 3. Setup System Calls - 4. Initialize `kmalloc` + 4. Initialize **kmalloc** 5. (TMP) Setup Event Bus 6. Create Process Manager 7. Initialize Scheduler diff --git a/design/filesystem.md b/design/filesystem.md index 048a1ab..775da59 100644 --- a/design/filesystem.md +++ b/design/filesystem.md @@ -26,6 +26,7 @@ The type show what the block type is. Example to get decode an address + ```text block = loc & 0xff group = (loc >> 8) & 0x3fff @@ -34,6 +35,7 @@ type = loc >> 30 Example to encode an address + ```text address = block address |= (group << 8) diff --git a/design/memory.md b/design/memory.md index 24432f9..7e4f6c2 100644 --- a/design/memory.md +++ b/design/memory.md @@ -1,9 +1,17 @@ # Memory Map + +\[ [Real Mode](#real-mode) \] +\[ [Protected Mode](#protected-mode) \] +\[ [Physical Allocator](#physical-allocator-ramh) \] +\[ [Paging Allocator](#paging-allocator-memoryh) \] + ## Real Mode -See https://wiki.osdev.org/Memory_Map_(x86) for reserved BIOS memory. +See [https://wiki.osdev.org/Memory_Map_(x86)](https://wiki.osdev.org/Memory_Map_(x86)) +for reserved BIOS memory. + | start | end | size | description | | ------ | ------- | --------- | --------------------------- | | 0x0000 | 0x4ff | 1.25 KiB | Unusable | @@ -13,9 +21,9 @@ See https://wiki.osdev.org/Memory_Map_(x86) for reserved BIOS memory. | 0x7c00 | 0x07dff | 512 bytes | Boot Sector | | 0x7e00 | 0x9fbff | 607.5 KiB | Kernel (second stage) | -> [!IMPORTANT] Kernel Size in Protected Mode -> Reserved memory in protected mode starts at 0x9fc00 while real mode starts at -> 0xa0000 +> [!IMPORTANT] +> Kernel Size in Protected Mode is smaller than in real mode. Reserved memory in +> protected mode starts at 0x9fc00 while real mode starts at 0xa0000 ### Boot Parameters @@ -33,8 +41,7 @@ x is the value of Memory Entry Count * 24 #### Memory Entry There is a single memory entry for each region of memory. It is possible to have -out of order and overlapping regions. See [BIOS Function: INT 0x15, EAX = -0xE820](https://wiki.osdev.org/Detecting_Memory_(x86)#BIOS_Function:_INT_0x15.2C_EAX_.3D_0xE820) +out of order and overlapping regions. See [BIOS Function: INT 0x15, EAX = 0xE820](https://wiki.osdev.org/Detecting_Memory_(x86)#BIOS_Function:_INT_0x15.2C_EAX_.3D_0xE820) | start | size | description | | ----- | ---- | ------------ | @@ -76,28 +83,28 @@ ACPI 3.0 Extended Attributes | ... | ... | ... | ... | | 0xb8000 | 0xb8fff | 0x01000 | VGA Memory | -> [!IMPORTANT] Kernel Size in Protected Mode -> Reserved memory in protected mode starts at 0x9fc00 while real mode starts at -> 0xa0000 +> [!IMPORTANT] +> Kernel Size in Protected Mode is smaller than in real mode. Reserved memory in +> protected mode starts at 0x9fc00 while real mode starts at 0xa0000 ### Virtual Address Space (stage 2) -See https://wiki.osdev.org/Paging for information about page tables and -directory. +See [https://wiki.osdev.org/Paging](https://wiki.osdev.org/Paging) for +information about page tables and directory. - The first page (0) is always null, accessing any address here will result in a (page fault?) - Each page directory and table contain 1024 entries -- 0x1000 will always point to the active page directory -- 0x2000 will always point to the ram region table -- 0xb9000 will always point to the first ram region bitmasks +- **0x1000** will always point to the active page directory +- **0x2000** will always point to the ram region table +- **0xb9000** will always point to the first ram region bitmasks - There are 512 sequential pages of ram bitmasks ending at 0x2b9fff -- _0x400000 is the first virtual address of the second page table_ +- _**0x400000** is the first virtual address of the second page table_ - It is suggested to keep kernel level memory bellow this address to allow user space application switching out the second+ page table - This can be used as the entry point address for all user space applications - This region is ~3.99 GB -- 0xffc00000 will always point to the first page table (kernel table) +- **0xffc00000** will always point to the first page table (kernel table) - This goes up to 0xffffffff as the last address in all of virtual space - Each of the 1024 tables from the page directory are stored here sequentially - The first table includes the null page and kernel memory mapping (see bellow) @@ -148,11 +155,12 @@ pages in the region. | 4 | 2 | page count | | 8 | 2 | free count | ->[!IMPORTANT] Remember to mask the address -> The low 12 bits of each address are flags because the address is always page -> aligned. Remember to mask these bits when using the address. +> [!IMPORTANT] +> Remember to mask the address. The low 12 bits of each address are flags +> because the address is always page aligned. Remember to mask these bits when +> using the address. -> [!NOTE] Region size +> [!NOTE] > Each region can be up to 128 MiB (32768 pages) >- Page size = 4096 (0x1000) >- Bits per page = Page Size * 8 = 4096 * 8 = 32768 (0x8000) @@ -173,14 +181,14 @@ bitmask for the region showing which pages are free. Any bits outside of the region should be set to 0 (ie. if the region is smaller than 128 MiB, bits for any pages after the region end should be 0). -> [!IMPORTANT] Bitmask bit 1 -> The first bit of the bitmask will always be 0 for the bitmask page itself. +> [!IMPORTANT] +> The first bit (bit 1) of the bitmask will always be 0 for the bitmask page itself. ## Paging Allocator (`memory.h`) -Paging allocator (aka `pmalloc` and `pfree`) is responsible for connecting the -physical memory allocator (ram) and page tables (mmu). This allocator keeps a -linked list of tables, 1022 entries each. +Paging allocator (aka **pmalloc** and **pfree**) is responsible for connecting +the physical memory allocator (ram) and page tables (mmu). This allocator keeps +a linked list of tables, 1022 entries each. Each entry of the table describes a region of memory with address, flags and size in bytes (page aligned). @@ -198,9 +206,9 @@ There are a total of 511 entries per table. ### Memory Table Entries The first 12 bits of a table entry are flags. The page number can be converted -to a memory address by shifting it left by 12 bits, or by using the max -(0xfffff000). Because the size is page aligned, the same strategy can be used -for getting the page number or memory address. +to a memory address by shifting it left by 12 bits, or by using the max of +0xfffff000. Because the size is page aligned, the same strategy can be used for +getting the page number or memory address. | start | size | description | | ----- | ---- | -------------------------------------- | @@ -208,11 +216,11 @@ for getting the page number or memory address. | 12 | 20 | page no (address if flags masked away) | | 32 | 32 | size in bytes (page aligned) | -> [!IMPORTANT] Size is page aligned +> [!IMPORTANT] > The size is page aligned such that a page no / address + size points to the > next valid, page aligned, address. -> [!NOTE] Size has unused bits +> [!NOTE] > Because the size is page aligned, the first 12 bits should always be 0 #### Flags @@ -233,4 +241,4 @@ the present flag set will be treated as the end of all entries. - Memory tables can be moved and removed. Only a pointer to the first table should be stored. All other tables are reachable via the linked list. -TODO - everything else here +**TODO** - everything else here diff --git a/design/process.md b/design/process.md index d96fa25..236e31d 100644 --- a/design/process.md +++ b/design/process.md @@ -1,5 +1,10 @@ # Process + +\[ [Creating a Process](#creating-a-process) \] +\[ [Switch Task](#switch-task) \] +\[ [Ring Scheduler](#ring-scheduler) \] + The process tracks and manages the following information. - Process Id @@ -11,7 +16,7 @@ The process tracks and manages the following information. - Registers - Signal callbacks - Link to next process -- *TBD Stats about process +- (TBD) Stats about process ## Creating a Process @@ -62,13 +67,13 @@ previous for list removal). When a task switch is performed, the next process in checked for fulfillment of the event filter. This is repeated until a ready to run task is found. -> [!WARNING] There must be at least one process ready to run -> -> There must always be a "next" task ready to run. In the case where the current -> process is yielding with an event filter, another process must be ready to -> launch. This will most likely be init, so there needs to be some documentation -> for init behavior written which includes that it must never yield with an -> event filter. +> [!WARNING] +> There must always be at least one process (a "next" task) ready to run. In the +> case where the current process is yielding with an event filter, another +> process must be ready to launch or resume. +> +> This will most likely be init, so documentation is needed for init behavior +> written which includes that it must never yield with an event filter. ### Process Manager diff --git a/design/signals.md b/design/signals.md index 1a2dc25..e20086f 100644 --- a/design/signals.md +++ b/design/signals.md @@ -11,7 +11,7 @@ TODO # Old -The `register_signals` call will hook a function in libc to receive all signals. -It will then store all registered callbacks of the process. +The **register_signals** call will hook a function in libc to receive all +signals. It will then store all registered callbacks of the process. TODO - keyboard event diff --git a/design/system_call.md b/design/system_call.md index fafdd15..d127f68 100644 --- a/design/system_call.md +++ b/design/system_call.md @@ -1,5 +1,10 @@ # System Calls + +\[ [Sending System Calls](#sending-system-calls) \] +\[ [Receiving System Calls](#receiving-system-calls) \] +\[ [Example Handler](#example-handler) \] + System calls are the mechanism by which processes communicate with the kernel both for sending commands and retrieving data. Some examples include file io, memory management, process management, etc. System calls are initiated by the @@ -50,9 +55,9 @@ void system_call_register(uint16_t family, sys_call_handler_t handler); ### Call Arguments -Arguments are accessible from `args_data` which is a pointer to the va_args in -the caller process stack. A struct can be used to decompose the argument values -from this pointer. +Arguments are accessible from **args_data** which is a pointer to the `va_args` +in the caller process stack. A struct can be used to decompose the argument +values from this pointer. ```c struct _args { @@ -63,10 +68,9 @@ struct _args { ``` > [!WARNING] -> -> Argument data is stored in the process stack. After changing the page directory -> the values in `arg_data` will be invalid. Copy values to the kernel stack or -> heap before switching to retrain access. +> Argument data is stored in the process stack. After changing the page +> directory the values in `arg_data` will be invalid. Copy values to the kernel +> stack or heap before switching to retrain access. ### Return Value @@ -74,7 +78,7 @@ Each call handler can optionally returns a single `int` value to the caller process by returning a value from the handler function. If no value is returned to the caller process, the call handler should return 0. -### Example Handler +## Example Handler A typical call handler uses a switch block to select the correct logic based on the `call_id`. diff --git a/design/time.md b/design/time.md index 8393f3f..99eeb39 100644 --- a/design/time.md +++ b/design/time.md @@ -17,9 +17,9 @@ Each channel counts down, starting at the reload value, and when they reach 0 the output is switched (low -> high or high -> low). In most cases the channel is then set to the reload value. -TODO in what cases is the reload value not used when a channel reaches 0? +**TODO** in what cases is the reload value not used when a channel reaches 0? -> [!NOTE] Reload Value +> [!NOTE] > The reload value of a channel is the value it will set it's count to after > reaching zero. Depending on the mode, that reset can be triggered by various > conditions. @@ -57,7 +57,7 @@ _only channel 0_ This mode will wait until a software trigger to begin the countdown. -TODO does the countdown happen with the clock or on each sw trigger? +**TODO** does the countdown happen with the clock or on each sw trigger? ### Mode 1 - Hardware Re-triggerable One-Shot @@ -120,6 +120,7 @@ selected in the command. | | 111 = Mode 3 (square wave generator, same as 011) | | 0 | BCD / Binary Mode (0 = 16-bit binary, 1 = four digit BCD) | -> [!TIP] Bits 0 - 5 are the same as the mode / command +> [!TIP] +> Bits 0 - 5 are the same as the mode / command # Real Time Clock (RTC) diff --git a/notes.md b/notes.md index a34a331..7b0be5a 100644 --- a/notes.md +++ b/notes.md @@ -59,7 +59,7 @@ section once they are finished. # Active -## 1, Task Scheduler +## 1. Task Scheduler Create a task scheduler and add a yield to most / all system calls. This scheduler should also handle the idle state when all processes are waiting. The