Files
Elyz/kernel/src/main.rs
Faynot aa357b6198 init
2026-03-27 14:06:30 +03:00

194 lines
6.3 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#![no_std]
#![no_main]
use core::arch::asm;
use core::fmt::{self, Write};
use limine::BaseRevision;
use limine::request::{FramebufferRequest, RequestsEndMarker, RequestsStartMarker};
use embedded_graphics::{
mono_font::{ascii::FONT_6X10, MonoTextStyle},
pixelcolor::Rgb888,
prelude::*,
text::Text,
Drawable,
};
// Отрисовка пикселей
struct FramebufferDisplay<'a> {
framebuffer: &'a limine::framebuffer::Framebuffer<'a>,
}
impl DrawTarget for FramebufferDisplay<'_> {
type Color = Rgb888;
type Error = core::convert::Infallible;
fn draw_iter<I>(&mut self, pixels: I) -> Result<(), Self::Error>
where I: IntoIterator<Item = Pixel<Self::Color>> {
for Pixel(coord, color) in pixels {
if coord.x >= 0 && coord.x < self.framebuffer.width() as i32 &&
coord.y >= 0 && coord.y < self.framebuffer.height() as i32 {
let offset = (coord.y as usize * self.framebuffer.pitch() as usize) + (coord.x as usize * 4);
unsafe {
self.framebuffer.addr().add(offset).cast::<u32>().write(color.into_storage());
}
}
}
Ok(())
}
}
impl OriginDimensions for FramebufferDisplay<'_> {
fn size(&self) -> Size {
Size::new(self.framebuffer.width() as u32, self.framebuffer.height() as u32)
}
}
// Терминальный вывод. Следит за положением курсора и умеет двигать текст
struct Console<'a> {
display: FramebufferDisplay<'a>,
x: i32,
y: i32,
}
impl<'a> Console<'a> {
pub fn new(display: FramebufferDisplay<'a>) -> Self {
Self { display, x: 10, y: 20 } // Начальный отступ
}
// Метод для очистки экрана
pub fn clear(&mut self) {
let size = self.display.size();
let fb = self.display.framebuffer;
unsafe {
// Быстрая очистка через заполнение памяти нулями
core::ptr::write_bytes(fb.addr(), 0, fb.pitch() as usize * fb.height() as usize);
}
self.x = 10;
self.y = 20;
}
// Логика скроллинга. копирует пиксели снизу вверх
fn scroll(&mut self) {
let fb = self.display.framebuffer;
let pitch = fb.pitch() as usize;
let height = fb.height() as usize;
let font_height = 10; // Высота FONT_6X10
let shift = font_height * pitch;
unsafe {
let addr = fb.addr();
// Копируем всё содержимое экрана на одну строку вверх
core::ptr::copy(
addr.add(shift),
addr,
pitch * (height - font_height)
);
// Очищаем последнюю строку
core::ptr::write_bytes(
addr.add(pitch * (height - font_height)),
0,
shift
);
}
self.y -= font_height as i32;
}
}
// Вывод текста. write!(console, "Hello {}", name)
impl fmt::Write for Console<'_> {
fn write_str(&mut self, s: &str) -> fmt::Result {
let style = MonoTextStyle::new(&FONT_6X10, Rgb888::WHITE);
for c in s.chars() {
if c == '\n' {
self.x = 10;
self.y += 10;
} else {
// Если текст выходит за границы экрана — перенос строки
if self.x + 6 > self.display.framebuffer.width() as i32 {
self.x = 10;
self.y += 10;
}
// Рисуем символ (превращаем char в временную строку &str)
let mut buf = [0u8; 4];
let s_char = c.encode_utf8(&mut buf);
let _ = Text::new(s_char, Point::new(self.x, self.y), style).draw(&mut self.display);
self.x += 6; // Ширина FONT_6X10
}
// Если достигли низа экрана, то скроллим
if self.y > self.display.framebuffer.height() as i32 - 10 {
self.scroll();
}
}
Ok(())
}
}
// boot
#[used]
#[unsafe(link_section = ".requests")]
static BASE_REVISION: BaseRevision = BaseRevision::new();
#[used]
#[unsafe(link_section = ".requests")]
static FRAMEBUFFER_REQUEST: FramebufferRequest = FramebufferRequest::new();
#[used]
#[unsafe(link_section = ".requests_start_marker")]
static _START_MARKER: RequestsStartMarker = RequestsStartMarker::new();
#[used]
#[unsafe(link_section = ".requests_end_marker")]
static _END_MARKER: RequestsEndMarker = RequestsEndMarker::new();
#[unsafe(no_mangle)]
unsafe extern "C" fn kmain() -> ! {
assert!(BASE_REVISION.is_supported());
if let Some(framebuffer_response) = FRAMEBUFFER_REQUEST.get_response() {
if let Some(fb) = framebuffer_response.framebuffers().next() {
// Инициализируем консоль
let mut console = Console::new(FramebufferDisplay { framebuffer: &fb });
console.clear();
let _ = writeln!(console, "RINA Kernel");
let _ = writeln!(console, "-----------------------");
let _ = writeln!(console, "Framebuffer: {}x{}", fb.width(), fb.height());
let _ = writeln!(console, "Memory mapping... OK");
let _ = writeln!(console, "Hello, Arina! Terminal mode active :3");
// Тест скроллинга: выведем много строк
for i in 0..5 {
let _ = writeln!(console, "System log entry #{}", i);
}
}
}
hcf();
}
#[panic_handler]
fn rust_panic(_info: &core::panic::PanicInfo) -> ! {
// В будущем тут будет выводиться текст ошибки
hcf();
}
fn hcf() -> ! {
loop {
unsafe {
#[cfg(target_arch = "x86_64")]
asm!("hlt");
#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
asm!("wfi");
#[cfg(target_arch = "loongarch64")]
asm!("idle 0");
}
}
}