#![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(&mut self, pixels: I) -> Result<(), Self::Error> where I: IntoIterator> { 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::().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"); } } }