Add BIOS and tiny kernel roadmap phases

This commit is contained in:
2026-04-28 13:23:03 +02:00
parent 07dd8e21f0
commit e8631501e8
18 changed files with 344 additions and 77 deletions
+12 -10
View File
@@ -27,13 +27,15 @@ is to explain what to learn, what to verify, and what mistakes to avoid.
- [Phase 6 - Load/Store](phase-06-load-store/phase-06.md)
- [Phase 7 - Memory-Mapped UART](phase-07-uart-mmio/phase-07.md)
- [Phase 8 - GCC Toolchain Integration](phase-08-gcc-toolchain/phase-08.md)
- [Phase 9 - CSRs + M-Mode Traps](phase-09-csrs-traps/phase-09.md)
- [Phase 10 - Timer](phase-10-timer/phase-10.md)
- [Phase 11 - Interrupt Controller](phase-11-interrupt-controller/phase-11.md)
- [Phase 12 - Atomics](phase-12-atomics/phase-12.md)
- [Phase 13 - Pipeline](phase-13-pipeline/phase-13.md)
- [Phase 14 - SPI Flash + DRAM](phase-14-flash-dram/phase-14.md)
- [Phase 15 - M/S/U + Sv32](phase-15-privilege-sv32/phase-15.md)
- [Phase 16 - Linux Boot Contract](phase-16-linux-boot-contract/phase-16.md)
- [Phase 17 - Linux](phase-17-linux/phase-17.md)
- [Phase 9 - GCC-Built BIOS / Serial Monitor](phase-09-bios-monitor/phase-09.md)
- [Phase 10 - Minimal ELF Loader](phase-10-elf-loader/phase-10.md)
- [Phase 11 - Tiny Kernel + Command Shell](phase-11-tiny-kernel/phase-11.md)
- [Phase 12 - CSRs + M-Mode Traps](phase-12-csrs-traps/phase-12.md)
- [Phase 13 - Timer](phase-13-timer/phase-13.md)
- [Phase 14 - Interrupt Controller](phase-14-interrupt-controller/phase-14.md)
- [Phase 15 - Atomics](phase-15-atomics/phase-15.md)
- [Phase 16 - Pipeline](phase-16-pipeline/phase-16.md)
- [Phase 17 - SPI Flash + DRAM](phase-17-flash-dram/phase-17.md)
- [Phase 18 - M/S/U + Sv32](phase-18-privilege-sv32/phase-18.md)
- [Phase 19 - Linux Boot Contract](phase-19-linux-boot-contract/phase-19.md)
- [Phase 20 - Linux](phase-20-linux/phase-20.md)
@@ -27,7 +27,7 @@ more than minimizing cycles.
- Write a cycle-by-cycle timeline for a simple `addi` instruction.
- Write a cycle-by-cycle timeline for a multiply/divide instruction.
- Confirm the pre-Phase 9 illegal-instruction behavior: halt the core and expose
- Confirm the pre-Phase 12 illegal-instruction behavior: halt the core and expose
the offending PC and instruction word to the testbench.
## Pitfalls
@@ -27,7 +27,7 @@ every emitted instruction is implemented or fails loudly.
- Compare C source to generated assembly.
- Identify every load/store used for UART access.
- Confirm no CSR or `fence.i` instructions appear before Phase 9.
- Confirm no CSR or `fence.i` instructions appear before Phase 12.
## Pitfalls
@@ -0,0 +1,49 @@
# Phase 9 - GCC-Built BIOS / Serial Monitor
## Context
This phase turns the GCC bring-up work into a persistent interactive firmware. The
CPU boots into a small monitor instead of a one-off test program.
## Goals
- Build a freestanding C/assembly BIOS with its own linker script and startup code.
- Provide a UART command prompt.
- Add simple commands for memory inspection, loading, and jumping to test payloads.
## New Concepts
- Monitor: small firmware that lets you inspect and control a machine interactively.
- Command parser: text interface that maps typed commands to firmware functions.
- Firmware ABI: the calling convention and data contract between loaded code and BIOS.
- Executable RAM window: memory that software can write and the fetch path can execute.
## How To Think About It
The BIOS is both a milestone and a tool. Keep it boring and reliable: UART in, UART out,
explicit commands, clear error messages, and no hidden dependencies on host tooling.
## Learning Tasks
- Decide where UART-loaded code can live and how the I-bus fetches it.
- Define a tiny BIOS call table for console I/O and returning to the monitor.
- Write down the exact register state expected by `run <addr>`.
- Add commands one at a time and test each on hardware.
## Pitfalls
- Loading code into data memory that the instruction fetch path cannot see.
- Letting a failed command corrupt the monitor's own stack or globals.
- Building a clever shell before the load/run/debug basics work.
## Tooling And Testing
- Test the monitor in simulation with scripted UART input where practical.
- Use a terminal program that can send raw files without changing line endings.
- Keep a known-good tiny payload that prints one line and returns to the monitor.
## References
- RISC-V ELF psABI: https://github.com/riscv-non-isa/riscv-elf-psabi-doc
- GNU linker scripts: https://sourceware.org/binutils/docs/ld/Scripts.html
- OSDev bare bones background: https://wiki.osdev.org/Bare_Bones
+51
View File
@@ -0,0 +1,51 @@
# Phase 10 - Minimal ELF Loader
## Context
This phase lets the BIOS receive GCC-built programs as ELF files and run them without
rebuilding the FPGA bitstream.
## Goals
- Parse enough ELF32 to recognize RISC-V executable files.
- Load `PT_LOAD` segments into memory and zero BSS.
- Jump to `e_entry` with a fixed tiny-program ABI.
## New Concepts
- ELF header: file-level metadata describing architecture, entry point, and tables.
- Program header: runtime load description used by loaders.
- `PT_LOAD`: segment that must be copied into memory before execution.
- BSS: zero-initialized memory represented by `memsz > filesz`.
## How To Think About It
Do not build a general-purpose dynamic loader. Build a strict loader for the exact
firmware shape you produce: static, little-endian, non-relocatable RV32 ELF files with
fixed physical addresses.
## Learning Tasks
- Read the ELF header fields needed to reject unsupported files.
- Map `p_paddr` or `p_vaddr` to your executable memory window.
- Define the stack pointer and argument registers at program entry.
- Decide how a loaded program returns a status code to the BIOS.
## Pitfalls
- Trusting malformed ELF offsets or sizes.
- Forgetting to zero the BSS tail of a loadable segment.
- Accidentally accepting relocatable or dynamically linked binaries.
- Loading a segment over the BIOS itself.
## Tooling And Testing
- Use `readelf -h -l` and `objdump -d` on every early payload.
- Start with one fixed link address and one loadable segment.
- Add loud rejection messages for unsupported ELF class, endianness, machine, or type.
## References
- ELF specification overview: https://refspecs.linuxfoundation.org/elf/elf.pdf
- RISC-V ELF psABI: https://github.com/riscv-non-isa/riscv-elf-psabi-doc
- GNU binutils `readelf` documentation: https://sourceware.org/binutils/docs/binutils/readelf.html
+50
View File
@@ -0,0 +1,50 @@
# Phase 11 - Tiny Kernel + Command Shell
## Context
This phase builds an OS-shaped firmware payload before the project moves into traps,
interrupts, privilege, DRAM, and Linux.
## Goals
- Load a separate GCC-built kernel ELF from the BIOS.
- Provide a kernel-owned command shell.
- Run tiny trusted ELF programs through a simple service table.
## New Concepts
- Kernel: central program that owns machine services. Before traps, this is still
trusted bare-machine firmware, not an isolated privileged OS.
- Service table: function-pointer ABI for console I/O, exit, and simple utilities.
- Bump allocator: simple allocator that hands out memory linearly.
- Program table: small kernel data structure tracking loaded payloads.
## How To Think About It
The goal is a complete loop, not a Unix clone: compile a tiny program on the host,
send it over UART, load it as ELF, run it on the CPU, and return to the shell.
## Learning Tasks
- Decide whether kernel console I/O calls the BIOS or drives UART directly.
- Define the tiny-program ABI: entry registers, stack, service table, and return path.
- Implement the smallest useful allocator.
- Add shell commands that expose real machine state, not decorative output.
## Pitfalls
- Pretending trusted payloads are isolated before traps and privilege modes exist.
- Growing the kernel into a second large project too early.
- Hiding loader or ABI bugs behind ad hoc special cases.
## Tooling And Testing
- Keep kernel and user-payload linker scripts separate.
- Build a tiny test suite of loaded programs: hello, echo, memory copy, return status.
- Run the same payloads after Phase 12 trap handling lands to catch ABI regressions.
## References
- OSDev kernel structure notes: https://wiki.osdev.org/Kernel
- RISC-V calling convention: https://github.com/riscv-non-isa/riscv-elf-psabi-doc
- Embedded Artistry first-fit allocator background: https://embeddedartistry.com/blog/2017/02/15/implementing-malloc-first-fit-free-list/
@@ -1,4 +1,4 @@
# Phase 9 - CSRs + M-Mode Trap Handling
# Phase 12 - CSRs + M-Mode Trap Handling
## Context
@@ -1,4 +1,4 @@
# Phase 10 - Timer
# Phase 13 - Timer
## Context
@@ -1,4 +1,4 @@
# Phase 11 - Interrupt Controller
# Phase 14 - Interrupt Controller
## Context
@@ -1,4 +1,4 @@
# Phase 12 - A Extension
# Phase 15 - A Extension
## Context
@@ -1,4 +1,4 @@
# Phase 13 - Pipeline
# Phase 16 - Pipeline
## Context
@@ -1,4 +1,4 @@
# Phase 14 - SPI Flash Boot + DRAM
# Phase 17 - SPI Flash Boot + DRAM
## Context
@@ -1,4 +1,4 @@
# Phase 15 - S-Mode, U-Mode, Sv32 Virtual Memory
# Phase 18 - S-Mode, U-Mode, Sv32 Virtual Memory
## Context
@@ -1,4 +1,4 @@
# Phase 16 - Linux Boot Contract
# Phase 19 - Linux Boot Contract
## Context
@@ -1,4 +1,4 @@
# Phase 17 - Linux
# Phase 20 - Linux
## Context