summaryrefslogtreecommitdiffstats
path: root/CONTEXT.md
blob: 66ab320c67cce96fb685402bd8aab6c8d84cb398 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# CONTEXT.md — raisernics Kernel Glossary

## raisernics

Custom x86_64 kernel for the RNG ecosystem.  Toy project — self-contained,
no strict userspace separation, TempleOS-inspired design philosophy.
Built in Rust, compiled for the `x86_64-unknown-uefi` target (nightly).

## Boot interface

The kernel is a **PE32+ EFI application** loaded via UEFI `LoadImage`/`StartImage`.
The existing bootloader (rsbl) loads us from `\bzImage` and passes the UEFI
system table.  No bootloader changes needed.

## Output strategy

Two-phase console model:

- **Phase 1 (boot services alive):** UEFI `con_out->OutputString()` — works
  with whatever UEFI firmware routes (serial + framebuffer).
- **Phase 2 (native):** Raw serial UART 16550 driver on COM1 (I/O port
  `0x3F8`).  Activated after `ExitBootServices` when we own the hardware.

## Dependency philosophy

Aligns with RNG philosophy: minimal dependencies.  Freestanding Rust,
no libc, no external crates at the kernel/core level.  UEFI protocol
structs are hand-defined (not from `uefi-rs` crate) to stay lightweight.

## Paging strategy

Long mode mandates paging (`CR0.PG = 1`), so we accept that tax but keep it
simple.  Identity-mapped 4-level tables, no higher-half, no demand paging,
no guard pages.  `paging.rs` provides identity map/unmap/query helpers.  At
boot the kernel runs on UEFI's tables; `adopt_tables()` rebuilds that map
into the kernel's own tables and switches CR3 — needed because UEFI maps its
page-table pages read-only, so the firmware tree can't be modified in place.
Firmware large pages (2 MB / 1 GB) are split into 4 KB tables on demand;
page-table pages come from the physical page allocator.

## Physical memory

Before `ExitBootServices`, the kernel reads the UEFI memory map to know
which physical regions are free.  The heap is a first-fit **free-list
allocator** with splitting and coalescing: blocks carry a 16-byte header
(size + free flag), free blocks are linked in address order, and an 8-byte
back-pointer before each payload lets `free` find its block even when
alignment left a gap.  When the free list is exhausted, the heap **grows**
by taking pages from the page allocator (proportional to the request),
keeping the two allocators cooperating.  A **bitmap page allocator** manages
physical pages: one bit per 4 KB page spanning the conventional regions, so
MMIO holes and firmware-reserved gaps are never handed out, and the heap
region itself is reserved to keep the allocators from double-allocating the
same RAM.  Contiguous runs with power-of-two alignment are supported
(`alloc_pages_aligned`).

## Input strategy

**PS/2 keyboard polling.** Port I/O to `0x60`/`0x64`.  Scancode set 1
(US QWERTY layout in the initial build).  No interrupts — polling loop
inside the shell.

## Display strategy

Two-phase model matching output:

- **Phase 1:** UEFI `con_out->OutputString()` (framebuffer + serial handled
  by firmware).
- **Phase 2:** GOP (Graphics Output Protocol) framebuffer obtained before
  `ExitBootServices`, driven by a built-in 8×16 bitmap font.  Text rendered
  by drawing glyphs directly into the framebuffer.

The framebuffer address stays valid after `ExitBootServices` — the GPU's
linear frame buffer is system memory that we own once boot services are gone.

## Keyboard layout

Scancode set 1, US QWERTY layout.  Hardcoded scancode→ASCII table.
Other layouts can be added later by swapping the translation table.

## Development loop

Standalone project — no integration with the RNG initramfs build system.
Testing via QEMU with OVMF.  The kernel PE binary is placed on a FAT
image as `\bzImage` (matching rsbl's expected path).

## Project layout

Single Rust crate (`x86_64-unknown-uefi` target).  Module breakdown:

- `main.rs` — entry point, panic handler, top-level init
- `uefi.rs` — UEFI protocol type definitions
- `serial.rs` — UART 16550 driver
- `paging.rs` — identity page table helpers
- `memory.rs` — UEFI memory map, free-list heap allocator (grows from page
  allocator), bitmap page allocator
- `paging.rs` — identity page-table helpers (map/unmap/query, large-page split)
- `power.rs` — `ResetSystem`-based shutdown, hlt loop fallback
- `rtc.rs` — CMOS/RTC clock (ports 0x70/0x71), BCD/12h normalization
- `pci.rs` — legacy PCI config space (0xCF8/0xCFC), full enumeration
- `fs.rs` — VFS: dirs, ramfs files, char devices (`/dev/mem`, `rtc`, `pci`,
  `version`, `meminfo`, `null`, `zero`, `console`, `serial`; `/tmp` ramfs;
  `/etc/motd`)
- `gop.rs` — framebuffer access and text rendering
- `font.rs` — 8×16 bitmap font data
- `ps2.rs` — PS/2 keyboard driver (polling)
- `shell.rs` — command loop and built-in commands

## Milestone status (v0.1)

✅ **Booting** — kernel loads via rsbl, prints banner via UEFI console (verified on real hardware)
✅ **ExitBootServices** — memory map captured via static `.bss` buffer
  (see `docs/adr/0001-static-buffer-for-memory-map.md`)
✅ **Serial** — UART 16550 at COM1, 115200 8N1
✅ **Framebuffer** — GOP located, 8×16 bitmap font renders text
✅ **Keyboard** — PS/2 polling, scancode set 1, US QWERTY
✅ **Shell** — commands: `help`, `echo`, `clear`, `hello`, `info`, `mem`, `halt`, `poweroff`
✅ **Heap allocator** — first-fit free-list with splitting + coalescing, `alloc`/`free`
  (boot-time self-test verifies alignment, reuse, and full coalescing)
✅ **Physical pages** — bitmap allocator over conventional regions, contiguous
  runs, heap reservation, page-0 trap guard (boot-time self-test included)
✅ **Paging helpers** — identity map/unmap/query, 2 MB/1 GB large-page split,
  own tables adopted at boot (boot-time self-test included)
✅ **Heap growth** — heap expands into the page allocator when exhausted
✅ **Shell** — `mmap` dumps the UEFI map, `stress` exercises alloc/free + growth
✅ **Poweroff** — `poweroff`/`exit` shut down via UEFI `ResetSystem`
  (ACPI S5; `halt` keeps the plain hlt loop)
✅ **RTC** — CMOS clock read at boot and via `date` (BCD/12h handled)
✅ **PCI** — port-based config access, full bus enumeration via `pci`
✅ **VFS** — “everything is a file”: dirs, ramfs, char devices
  (`ls`/`cat`/`hexdump`/`mkdir`/`touch`/`rm`, `echo >`/`>>`; devices
  regenerate on read, `/dev/mem` is raw physical RAM)
✅ **^C / ^D** — Ctrl+C cancels the line or aborts a running stream
  (`cat`/`hexdump` check between chunks), Ctrl+D on an empty line
  powers off (EOF)

## Target audience

Learning exercise and toy.  Not a Linux replacement.  Not POSIX-compatible.