153 lines
5.4 KiB
Markdown
153 lines
5.4 KiB
Markdown
# Процесс загрузки: концептуальная модель
|
||
|
||
## Цепочка загрузки
|
||
|
||
```
|
||
Питание включено
|
||
│
|
||
▼
|
||
CPU reset vector (0xFFFFFFF0)
|
||
│
|
||
▼
|
||
UEFI firmware / BIOS
|
||
│
|
||
▼
|
||
Limine bootloader ─────────────────────────────┐
|
||
│ │
|
||
│ 1. Переводит CPU в 64-bit long mode │
|
||
│ 2. Настраивает page tables (identity map) │
|
||
│ 3. Загружает ядро по физическому адресу │
|
||
│ 4. Настраивает HHDM │
|
||
│ 5. Заполняет Limine requests │
|
||
│ 6. Передаёт управление на kmain │
|
||
│ │
|
||
▼ │
|
||
kmain() (точка входа) │
|
||
│ │
|
||
... инициализация ... │
|
||
│ │
|
||
▼ │
|
||
HCF (останов CPU) ─────────────────────────────┘
|
||
```
|
||
|
||
## Limine Boot Protocol
|
||
|
||
Elyz использует [Limine](https://github.com/limine-bootloader/limine) —
|
||
современный bootloader с открытым исходным кодом.
|
||
|
||
Статические `Limine requests` сообщают bootloader'у, что нужно ядру:
|
||
|
||
| Request | Назначение |
|
||
|---------|------------|
|
||
| `FramebufferRequest` | Получить framebuffer для графического вывода |
|
||
| `MemoryMapRequest` | Получить карту физической памяти |
|
||
| `HhdmRequest` | Получить HHDM offset |
|
||
| `ExecutableAddressRequest` | Получить физический/виртуальный адрес ядра |
|
||
| `BaseRevision` | Проверить совместимость с Limine |
|
||
|
||
### Размещение в секциях
|
||
|
||
Requests размещаются между специальными маркерами в секции `.data`:
|
||
|
||
```rust
|
||
#[used]
|
||
#[unsafe(link_section = ".requests_start_marker")]
|
||
static _START_MARKER: RequestsStartMarker = RequestsStartMarker::new();
|
||
|
||
// ... все requests ...
|
||
|
||
#[used]
|
||
#[unsafe(link_section = ".requests_end_marker")]
|
||
static _END_MARKER: RequestsEndMarker = RequestsEndMarker::new();
|
||
```
|
||
|
||
Линкер скрипт сохраняет эти секции:
|
||
```ld
|
||
.data : {
|
||
*(.data .data.*)
|
||
KEEP(*(.requests_start_marker))
|
||
KEEP(*(.requests))
|
||
KEEP(*(.requests_end_marker))
|
||
} :data
|
||
```
|
||
|
||
## Точка входа — kmain
|
||
|
||
Линкер скрипт: `ENTRY(kmain)`.
|
||
|
||
```rust
|
||
#[unsafe(no_mangle)]
|
||
unsafe extern "C" fn kmain() -> ! { ... }
|
||
```
|
||
|
||
Атрибуты:
|
||
- `no_mangle` — сохраняет имя `kmain` (линкер ищет именно его).
|
||
- `extern "C"` — C ABI (Linux x86-64 calling convention: RDI, RSI, ...).
|
||
- `unsafe` — на этапе инициализации все операции потенциально опасны.
|
||
- `-> !` — kmain никогда не возвращается (HALT).
|
||
|
||
## Build system
|
||
|
||
### GNUmakefile
|
||
|
||
```makefile
|
||
KARCH ?= x86_64
|
||
RUST_TARGET ?= $(KARCH)-unknown-none
|
||
RUST_PROFILE ?= dev
|
||
|
||
all:
|
||
RUSTFLAGS="-C relocation-model=static" \
|
||
cargo build --target $(RUST_TARGET) --profile $(RUST_PROFILE)
|
||
cp target/$(RUST_TARGET)/$(RUST_PROFILE_SUBDIR)/kernel .
|
||
```
|
||
|
||
- `relocation-model=static`: ядро не использует динамическую перелокацию.
|
||
- `--target x86_64-unknown-none`: bare-metal target (без ОС).
|
||
- Результат копируется в `kernel/` (корень).
|
||
|
||
### build.rs — linker script
|
||
|
||
```rust
|
||
fn main() {
|
||
let arch = std::env::var("CARGO_CFG_TARGET_ARCH").unwrap();
|
||
println!("cargo:rustc-link-arg=-Tlinker-{arch}.ld");
|
||
println!("cargo:rerun-if-changed=linker-{arch}.ld");
|
||
}
|
||
```
|
||
|
||
Подставляет правильный linker script для архитектуры.
|
||
|
||
### rust-toolchain.toml
|
||
|
||
```toml
|
||
[toolchain]
|
||
channel = "nightly"
|
||
targets = ["x86_64-unknown-none"]
|
||
```
|
||
|
||
Требуется nightly Rust из-за:
|
||
- `#![no_std]`, `#![no_main]`.
|
||
- `core::arch::global_asm!`, `core::arch::asm!`.
|
||
- `const { ... }` в инициализации констант.
|
||
|
||
## Память: расположение после загрузки
|
||
|
||
```
|
||
Физическая память:
|
||
┌───────────────────────┐ 0x0
|
||
│ Reserved │
|
||
├───────────────────────┤
|
||
│ Usable (free) │ ← входит в mmap entries
|
||
├───────────────────────┤
|
||
│ Kernel image │ ← загружен Limine
|
||
├───────────────────────┤
|
||
│ PMM metadata │ ← bitmap + ref_counts + L1
|
||
├───────────────────────┤
|
||
│ ... (usable) │
|
||
└───────────────────────┘ max_addr
|
||
|
||
Виртуальная память (Higher Half):
|
||
0xFFFF_8000_0000_0000 ─── HHDM (вся физическая память 1:1)
|
||
0xFFFF_9000_0000_0000 ─── Kernel heap (8 MiB)
|
||
```
|