|
| 1 | +# Retro Rocket Boot Flow |
| 2 | + |
| 3 | +This document describes the execution path from power-on to a running shell in **Retro Rocket** - a modern-day BBC Micro–inspired operating system. It walks through each stage of the boot process, from initial assembly handoff to the multitasking interpreter loop that drives userland programs. |
| 4 | + |
| 5 | +--- |
| 6 | + |
| 7 | +## Overview |
| 8 | + |
| 9 | +| Stage | Description | |
| 10 | +|-----------------------------|--------------------------------------------------| |
| 11 | +| `boot.asm` | Enables FPU/SSE, calls `kmain()` | |
| 12 | +| `kmain()` | Calls `init()` to bring up system subsystems | |
| 13 | +| `init()` | Sets up memory, devices, filesystems, etc | |
| 14 | +| `init_process()` | Creates process from `/programs/init` | |
| 15 | +| `/programs/init` (BASIC) | Mounts filesystems, sets globals, chains shell | |
| 16 | +| `/programs/rocketsh` | Shell process - user interaction begins | |
| 17 | + |
| 18 | +--- |
| 19 | + |
| 20 | +## 1. Boot Assembly: `boot.asm` |
| 21 | + |
| 22 | +The kernel is entered via the symbol `boot_bsp`, defined in NASM assembly. |
| 23 | + |
| 24 | +``` |
| 25 | +bits 64 |
| 26 | +section .text |
| 27 | +
|
| 28 | +extern kmain |
| 29 | +extern boot_bsp |
| 30 | +extern exception_handlers |
| 31 | +extern enable_fpu |
| 32 | +extern enable_sse |
| 33 | +
|
| 34 | +boot_bsp: |
| 35 | + call enable_fpu |
| 36 | + call enable_sse |
| 37 | + mov rax, kmain |
| 38 | + call rax |
| 39 | + jmp $ ; park the CPU |
| 40 | +``` |
| 41 | + |
| 42 | +- FPU and SSE are enabled for floating point support |
| 43 | +- `kmain()` is the first C-level entry point |
| 44 | +- Limine has already set up the page tables and higher-half mapping |
| 45 | +- No paging, GDT, or IDT setup is done here - all handled later |
| 46 | + |
| 47 | +--- |
| 48 | + |
| 49 | +## 2. Kernel Entry Point: `kmain()` |
| 50 | + |
| 51 | +```c |
| 52 | +void kmain() |
| 53 | +{ |
| 54 | + init(); |
| 55 | + |
| 56 | + if (!filesystem_mount("/", "cd0", "iso9660")) { |
| 57 | + preboot_fail("Failed to mount boot drive to VFS!"); |
| 58 | + } |
| 59 | + |
| 60 | + init_rtl8139(); |
| 61 | + init_e1000(); |
| 62 | + netdev_t* network = get_active_network_device(); |
| 63 | + if (network) { |
| 64 | + kprintf("Active network card: %s\n", network->description); |
| 65 | + network_up(); |
| 66 | + } |
| 67 | + |
| 68 | + init_process(); |
| 69 | +} |
| 70 | +``` |
| 71 | + |
| 72 | +- Calls `init()` to bring up subsystems |
| 73 | +- Mounts the boot filesystem |
| 74 | +- Starts networking drivers |
| 75 | +- Enters `init_process()` which boots into userland |
| 76 | + |
| 77 | +--- |
| 78 | + |
| 79 | +## 3. Core System Initialisation: `init()` |
| 80 | + |
| 81 | +```c |
| 82 | +init_func_t init_funcs[] = { |
| 83 | + init_heap, |
| 84 | + validate_limine_page_tables_and_gdt, |
| 85 | + init_console, |
| 86 | + init_cores, |
| 87 | + init_idt, |
| 88 | + init_pci, |
| 89 | + init_realtime_clock, |
| 90 | + init_devicenames, |
| 91 | + init_keyboard, |
| 92 | + init_ide, |
| 93 | + init_ahci, |
| 94 | + init_filesystem, |
| 95 | + init_iso9660, |
| 96 | + init_devfs, |
| 97 | + init_fat32, |
| 98 | + NULL, |
| 99 | +}; |
| 100 | +``` |
| 101 | + |
| 102 | +Each function is executed in sequence with logging. |
| 103 | + |
| 104 | +### Initialisation Order |
| 105 | + |
| 106 | +| Order | Function | Purpose | |
| 107 | +|-------|--------------------------------|------------------------------------------| |
| 108 | +| 1 | `init_heap` | Memory allocation | |
| 109 | +| 2 | `validate_limine_page_tables_and_gdt` | Limine checks | |
| 110 | +| 3 | `init_console` | Terminal setup (Flanterm) | |
| 111 | +| 4 | `init_cores` | Single-core bring-up, ACPI | |
| 112 | +| 5 | `init_idt` | Interrupt Descriptor Table | |
| 113 | +| 6 | `init_pci` | PCI bus scan | |
| 114 | +| 7 | `init_realtime_clock` | Realtime wall clock | |
| 115 | +| 8 | `init_devicenames` | Friendly device names | |
| 116 | +| 9 | `init_keyboard` | Keyboard setup | |
| 117 | +| 10 | `init_ide` | IDE disk support | |
| 118 | +| 11 | `init_ahci` | AHCI disk support | |
| 119 | +| 12 | `init_filesystem` | VFS infrastructure | |
| 120 | +| 13 | `init_iso9660` | ISO9660 read-only FS | |
| 121 | +| 14 | `init_devfs` | /devices virtual filesystem | |
| 122 | +| 15 | `init_fat32` | FAT32 support | |
| 123 | + |
| 124 | +--- |
| 125 | + |
| 126 | +## 4. Process Management and Shell Launch |
| 127 | + |
| 128 | +After filesystems are ready, `init_process()` loads the first userland BASIC program: |
| 129 | + |
| 130 | +```c |
| 131 | +void init_process() |
| 132 | +{ |
| 133 | + process_by_pid = hashmap_new(...); |
| 134 | + process_t* init = proc_load("/programs/init", current_console, 0, "/"); |
| 135 | + if (!init) { |
| 136 | + preboot_fail("/programs/init missing or invalid!\n"); |
| 137 | + } |
| 138 | + proc_loop(); |
| 139 | +} |
| 140 | +``` |
| 141 | + |
| 142 | +### `proc_loop()` |
| 143 | + |
| 144 | +```c |
| 145 | +void proc_loop() |
| 146 | +{ |
| 147 | + while (true) { |
| 148 | + proc_timer(); |
| 149 | + proc_run_next(); |
| 150 | + run_idle_tasks(); |
| 151 | + } |
| 152 | +} |
| 153 | +``` |
| 154 | + |
| 155 | +- Every iteration advances the current process |
| 156 | +- Each process runs one line of code |
| 157 | +- Terminated processes are cleaned up |
| 158 | +- System halts if no processes remain |
| 159 | + |
| 160 | +--- |
| 161 | + |
| 162 | +## 5. Userland Bootstrap: `/programs/init` |
| 163 | + |
| 164 | +This BASIC program acts like a boot script (like `AUTOEXEC.BAT` or `!Boot`): |
| 165 | + |
| 166 | +```basic |
| 167 | +GLOBAL LIB$ = "/programs/libraries" |
| 168 | +
|
| 169 | +PRINT "Mounting "; |
| 170 | +COLOR 14 |
| 171 | +PRINT "filesystems"; |
| 172 | +COLOR 7 |
| 173 | +PRINT "..." |
| 174 | +
|
| 175 | +MOUNT "/devices", "", "devfs" |
| 176 | +MOUNT "/harddisk", "hd0", "fat32" |
| 177 | +
|
| 178 | +REPEAT |
| 179 | + PRINT "Launching "; |
| 180 | + COLOR 14 |
| 181 | + PRINT "shell"; |
| 182 | + COLOR 7 |
| 183 | + PRINT "..." |
| 184 | + CHAIN "/programs/rocketsh" |
| 185 | + PRINT "Shell process ended." |
| 186 | +UNTIL FALSE |
| 187 | +``` |
| 188 | + |
| 189 | +- Sets globals |
| 190 | +- Mounts extra filesystems |
| 191 | +- Launches `rocketsh` |
| 192 | +- Loops forever, reloading the shell |
| 193 | + |
| 194 | +--- |
| 195 | + |
| 196 | +## 🔚 Full Boot Timeline |
| 197 | + |
| 198 | +``` |
| 199 | +boot.asm |
| 200 | + ↓ |
| 201 | +enable_fpu / enable_sse |
| 202 | + ↓ |
| 203 | +kmain() |
| 204 | + ↓ |
| 205 | +init() → subsystems (heap, IDT, PCI, FS, etc) |
| 206 | + ↓ |
| 207 | +filesystem_mount("/", "cd0", "iso9660") |
| 208 | + ↓ |
| 209 | +init_process() |
| 210 | + ↓ |
| 211 | +proc_load("/programs/init") |
| 212 | + ↓ |
| 213 | +/programs/init (BASIC): |
| 214 | + - MOUNT |
| 215 | + - CHAIN "/programs/rocketsh" |
| 216 | + ↓ |
| 217 | +/programs/rocketsh (shell) |
| 218 | +``` |
| 219 | + |
| 220 | +--- |
| 221 | + |
| 222 | +## ✨ Why This Design Works |
| 223 | + |
| 224 | +Retro Rocket's boot process is: |
| 225 | + |
| 226 | +- **Transparent**: Fully traceable from boot to shell |
| 227 | +- **Modular**: Replace shell or init without kernel changes |
| 228 | +- **Learnable**: Great for teaching systems programming |
| 229 | +- **Retro-powered**: BASIC everywhere - even `init` |
0 commit comments