diff options
| author | salmonik <salmonik@tuta.io> | 2026-07-31 02:18:30 +0200 |
|---|---|---|
| committer | salmonik <salmonik@tuta.io> | 2026-07-31 02:18:30 +0200 |
| commit | 76103215711d268b4b02f62e900f2be3032cf295 (patch) | |
| tree | dcd86b5b02ae99c99ca833668055f4f53211be6b /docs/adr | |
| download | rs-dos-76103215711d268b4b02f62e900f2be3032cf295.tar.gz rs-dos-76103215711d268b4b02f62e900f2be3032cf295.zip | |
Initial commit: raisernics toy kernel
- Bare-metal x86_64 UEFI kernel (PE32+, no libc)
- GOP framebuffer + 8x16 bitmap font
- PS/2 keyboard (polling, scancode set 1)
- UART 16550 serial driver (COM1, 115200 8N1)
- Bump allocator as #[global_allocator] (alloc::String, Vec, format!)
- UEFI memory map capture (static buffer, ADR 0001)
- Shell with 7 commands (help, echo, clear, hello, info, mem, halt)
- Dual output: GOP framebuffer + serial console
- Makefile: run, run-gui, debug, release, image targets
- tools/: qemu.sh, boot-image.sh, debug-kernel.py
Diffstat (limited to 'docs/adr')
| -rw-r--r-- | docs/adr/0001-static-buffer-for-memory-map.md | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/docs/adr/0001-static-buffer-for-memory-map.md b/docs/adr/0001-static-buffer-for-memory-map.md new file mode 100644 index 0000000..75a4059 --- /dev/null +++ b/docs/adr/0001-static-buffer-for-memory-map.md | |||
| @@ -0,0 +1,54 @@ | |||
| 1 | # ADR 0001 — Static .bss Buffer for UEFI Memory Map Capture | ||
| 2 | |||
| 3 | ## Status | ||
| 4 | |||
| 5 | Accepted. | ||
| 6 | |||
| 7 | ## Context | ||
| 8 | |||
| 9 | Before calling `ExitBootServices`, the kernel must obtain the UEFI memory map | ||
| 10 | to know which physical memory regions are available. The standard UEFI recipe | ||
| 11 | is: | ||
| 12 | |||
| 13 | 1. Call `GetMemoryMap` with a null buffer to get the required buffer size. | ||
| 14 | 2. Allocate a buffer (via `AllocatePool`). | ||
| 15 | 3. Call `GetMemoryMap` again to fill the buffer, receiving a `MapKey`. | ||
| 16 | 4. Call `ExitBootServices(image_handle, MapKey)`. | ||
| 17 | |||
| 18 | **Problem:** Steps 2 and 3 change the memory map themselves (the pool | ||
| 19 | allocation adds entries). After step 3 we have a valid `MapKey` for the | ||
| 20 | map *as it was during step 3*, but calling `FreePool` on the buffer | ||
| 21 | (before step 4) would change the map again and invalidate the key. | ||
| 22 | Not freeing the buffer leaks pool memory, but more importantly, the | ||
| 23 | default approach of `AllocatePool + GetMemoryMap + ExitBootServices` | ||
| 24 | between two `GetMemoryMap` calls makes the key fragile. | ||
| 25 | |||
| 26 | ## Decision | ||
| 27 | |||
| 28 | Use a **pre-allocated static buffer in `.bss`** (64 KB) instead of | ||
| 29 | dynamically allocating a pool buffer. Because the buffer already exists, | ||
| 30 | no `AllocatePool`/`FreePool` calls happen between `GetMemoryMap` and | ||
| 31 | `ExitBootServices`. | ||
| 32 | |||
| 33 | The sequence becomes: | ||
| 34 | |||
| 35 | 1. `GetMemoryMap(null)` → determine required size. | ||
| 36 | 2. `GetMemoryMap(static_buf)` → fill the map, receive `MapKey`. | ||
| 37 | 3. `ExitBootServices(image_handle, MapKey)` — no pool allocation | ||
| 38 | happened after step 2, so the key is guaranteed valid. | ||
| 39 | |||
| 40 | If the static buffer is too small (it shouldn't be — 64 KB holds ~1300 | ||
| 41 | descriptors, real firmware typically uses ~50–150), the caller falls | ||
| 42 | back to a pool-allocated buffer. | ||
| 43 | |||
| 44 | ## Consequences | ||
| 45 | |||
| 46 | - **Positive:** The `MapKey` is never invalidated between capture and | ||
| 47 | `ExitBootServices`. The boot sequence is simpler and more reliable. | ||
| 48 | - **Positive:** No pool memory leaks — the static buffer lives in `.bss` | ||
| 49 | and costs nothing to keep. | ||
| 50 | - **Negative:** 64 KB of `.bss` is permanently reserved (irrelevant on a | ||
| 51 | kernel that owns all memory). | ||
| 52 | - **Negative:** The buffer size is fixed at compile time; pathological | ||
| 53 | firmware with thousands of entries would require a fallback path | ||
| 54 | (implemented but never hit in practice). | ||
