feat: docs & ARCH 2.2, 2.3, 2.4
This commit is contained in:
150
kernel/docs/tty.md
Normal file
150
kernel/docs/tty.md
Normal file
@@ -0,0 +1,150 @@
|
||||
# Framebuffer Console: `tty.rs`
|
||||
|
||||
## Назначение
|
||||
|
||||
Драйвер графического вывода текста на framebuffer. Использует
|
||||
PSF2 (PC Screen Font 2) шрифты для отрисовки символов.
|
||||
|
||||
Является основным визуальным каналом вывода ядра (через info! макрос).
|
||||
|
||||
## Структура Console
|
||||
|
||||
```rust
|
||||
pub struct Console<'a> {
|
||||
framebuffer: &'a Framebuffer<'a>, // ссылка на Limine framebuffer
|
||||
font: &'static [u8], // PSF2 шрифт
|
||||
pub x: usize, // текущая позиция X (колонка)
|
||||
pub y: usize, // текущая позиция Y (строка)
|
||||
pub fg_color: u32, // цвет текста (RGB)
|
||||
pub bg_color: u32, // цвет фона (RGB)
|
||||
}
|
||||
```
|
||||
|
||||
## PSF2 Header
|
||||
|
||||
```rust
|
||||
#[repr(C, packed)]
|
||||
struct Psf2Header {
|
||||
magic: u32, // 0x864AB572 (PSF2 magic)
|
||||
version: u32,
|
||||
header_size: u32, // размер заголовка
|
||||
flags: u32,
|
||||
num_glyphs: u32, // количество глифов
|
||||
bytes_per_glyph: u32, // байт на глиф
|
||||
height: u32, // высота глифа в пикселях
|
||||
width: u32, // ширина глифа в пикселях
|
||||
}
|
||||
```
|
||||
|
||||
Шрифт — `font.psf` (8×16, встроен через `include_bytes!`).
|
||||
|
||||
## Операции
|
||||
|
||||
### clear()
|
||||
|
||||
Заполняет весь framebuffer нулями. Сбрасывает позицию курсора в (0, 0).
|
||||
|
||||
```rust
|
||||
pub fn clear(&mut self) {
|
||||
unsafe {
|
||||
core::ptr::write_bytes(fb.addr(), 0, (fb.pitch() * fb.height()) as usize);
|
||||
}
|
||||
self.x = 0;
|
||||
self.y = 0;
|
||||
}
|
||||
```
|
||||
|
||||
### scroll()
|
||||
|
||||
Сдвигает содержимое framebuffer вверх на высоту шрифта.
|
||||
Новые строки заполняются нулями.
|
||||
|
||||
```rust
|
||||
fn scroll(&mut self) {
|
||||
let shift = font_height * pitch; // смещение на 1 строку
|
||||
let size = pitch * (height - font_height); // сколько копировать
|
||||
unsafe {
|
||||
ptr::copy(addr.add(shift), addr, size);
|
||||
ptr::write_bytes(addr.add(size), 0, shift);
|
||||
}
|
||||
self.y -= font_height;
|
||||
}
|
||||
```
|
||||
|
||||
### draw_glyph(glyph_index, x, y)
|
||||
|
||||
Рисует глиф (символ) в заданной позиции.
|
||||
|
||||
```rust
|
||||
fn draw_glyph(&mut self, glyph_index: u32, x: usize, y: usize) {
|
||||
let bytes_per_line = (width + 7) / 8; // пиксели → байты
|
||||
let glyph_offset = header_size + (glyph_index * bytes_per_glyph);
|
||||
|
||||
for cy in 0..height {
|
||||
let glyph_row = self.font[glyph_offset + cy * bytes_per_line];
|
||||
for cx in 0..width {
|
||||
if (glyph_row & (0x80 >> cx)) != 0 {
|
||||
// Пиксель включён — рисуем fg_color
|
||||
let offset = ((y + cy) * fb_pitch) + ((x + cx) * 4);
|
||||
unsafe {
|
||||
fb_addr.add(offset).cast::<u32>().write_volatile(self.fg_color);
|
||||
}
|
||||
}
|
||||
// Если пиксель выключен — фон остаётся (нет очистки)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- `width=8`, `bytes_per_line=1`: каждый ряд глифа = 1 байт.
|
||||
- `(0x80 >> cx)`: проверка бита слева направо (MSB first).
|
||||
- `write_volatile`: запрещает компилятору оптимизировать запись в MMIO.
|
||||
|
||||
### write_char(c)
|
||||
|
||||
Печатает символ:
|
||||
- `\n` → переход на новую строку.
|
||||
- Другие символы → draw_glyph. Если символ > num_glyphs → глиф 0.
|
||||
- Перенос строки по ширине экрана.
|
||||
- Скроллинг при достижении низа.
|
||||
|
||||
## fmt::Write реализация
|
||||
|
||||
```rust
|
||||
impl fmt::Write for Console<'_> {
|
||||
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||
for c in s.chars() {
|
||||
self.write_char(c);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Использование в kmain()
|
||||
|
||||
```rust
|
||||
let fb = fb_res.framebuffers().next().expect("No framebuffer");
|
||||
let mut console = tty::Console::new(&fb, KERNEL_FONT);
|
||||
console.clear();
|
||||
|
||||
info!(console, "BOOT", "LIS4 Kernel Starting...");
|
||||
// ... остальные логи
|
||||
|
||||
let _ = writeln!(console, "{}", logo); // ASCII art при загрузке
|
||||
```
|
||||
|
||||
## Детали реализации
|
||||
|
||||
- **Цвета**: write_volatile для 32-битного пикселя. Формат — RGBA?
|
||||
(зависит от режима framebuffer).
|
||||
- **Фон**: не перерисовывается. Только пиксели текста.
|
||||
Для полной очистки — clear().
|
||||
- **PSF2 magic**: `0x864AB572` — проверяется в заголовке.
|
||||
- **Производительность**: draw_glyph простая, без буферизации.
|
||||
Для скроллинга — memcpy всего framebuffer.
|
||||
|
||||
## Зависимости
|
||||
|
||||
- `KERNEL_FONT: &[u8]` — встроен в main.rs через `include_bytes!("font.psf")`.
|
||||
- `limine::framebuffer::Framebuffer` — через HHDM отображённый framebuffer.
|
||||
Reference in New Issue
Block a user