commit aa357b619841f07202b7b1754c6aa234908605be Author: Faynot Date: Fri Mar 27 14:06:30 2026 +0300 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3d17a41 --- /dev/null +++ b/.gitignore @@ -0,0 +1,18 @@ +/limine +/ovmf +*.iso +*.hdd +/target +**/*.rs.bk +**/*.rlib +**/Cargo.lock +/kernel/build.rs +/kernel/linker-*.ld +/kernel/*.o +/kernel/*.elf +/kernel/*.bin +*.swp +*.swo +*.DS_Store +*.idea/ +*.vscode/ diff --git a/GNUmakefile b/GNUmakefile new file mode 100644 index 0000000..5219b60 --- /dev/null +++ b/GNUmakefile @@ -0,0 +1,251 @@ +# Nuke built-in rules and variables. +MAKEFLAGS += -rR +.SUFFIXES: + +# Convenience macro to reliably declare user overridable variables. +override USER_VARIABLE = $(if $(filter $(origin $(1)),default undefined),$(eval override $(1) := $(2))) + +# Target architecture to build for. Default to x86_64. +$(call USER_VARIABLE,KARCH,x86_64) + +# Default user QEMU flags. These are appended to the QEMU command calls. +$(call USER_VARIABLE,QEMUFLAGS,-m 2G) + +override IMAGE_NAME := elyz-$(KARCH) + +.PHONY: all +all: $(IMAGE_NAME).iso + +.PHONY: all-hdd +all-hdd: $(IMAGE_NAME).hdd + +.PHONY: run +run: run-$(KARCH) + +.PHONY: run-hdd +run-hdd: run-hdd-$(KARCH) + +.PHONY: run-x86_64 +run-x86_64: ovmf/ovmf-code-$(KARCH).fd ovmf/ovmf-vars-$(KARCH).fd $(IMAGE_NAME).iso + qemu-system-$(KARCH) \ + -M q35 \ + -drive if=pflash,unit=0,format=raw,file=ovmf/ovmf-code-$(KARCH).fd,readonly=on \ + -drive if=pflash,unit=1,format=raw,file=ovmf/ovmf-vars-$(KARCH).fd \ + -cdrom $(IMAGE_NAME).iso \ + $(QEMUFLAGS) + +.PHONY: run-hdd-x86_64 +run-hdd-x86_64: ovmf/ovmf-code-$(KARCH).fd ovmf/ovmf-vars-$(KARCH).fd $(IMAGE_NAME).hdd + qemu-system-$(KARCH) \ + -M q35 \ + -drive if=pflash,unit=0,format=raw,file=ovmf/ovmf-code-$(KARCH).fd,readonly=on \ + -drive if=pflash,unit=1,format=raw,file=ovmf/ovmf-vars-$(KARCH).fd \ + -hda $(IMAGE_NAME).hdd \ + $(QEMUFLAGS) + +.PHONY: run-aarch64 +run-aarch64: ovmf/ovmf-code-$(KARCH).fd ovmf/ovmf-vars-$(KARCH).fd $(IMAGE_NAME).iso + qemu-system-$(KARCH) \ + -M virt \ + -cpu cortex-a72 \ + -device ramfb \ + -device qemu-xhci \ + -device usb-kbd \ + -device usb-mouse \ + -drive if=pflash,unit=0,format=raw,file=ovmf/ovmf-code-$(KARCH).fd,readonly=on \ + -drive if=pflash,unit=1,format=raw,file=ovmf/ovmf-vars-$(KARCH).fd \ + -cdrom $(IMAGE_NAME).iso \ + $(QEMUFLAGS) + +.PHONY: run-hdd-aarch64 +run-hdd-aarch64: ovmf/ovmf-code-$(KARCH).fd ovmf/ovmf-vars-$(KARCH).fd $(IMAGE_NAME).hdd + qemu-system-$(KARCH) \ + -M virt \ + -cpu cortex-a72 \ + -device ramfb \ + -device qemu-xhci \ + -device usb-kbd \ + -device usb-mouse \ + -drive if=pflash,unit=0,format=raw,file=ovmf/ovmf-code-$(KARCH).fd,readonly=on \ + -drive if=pflash,unit=1,format=raw,file=ovmf/ovmf-vars-$(KARCH).fd \ + -hda $(IMAGE_NAME).hdd \ + $(QEMUFLAGS) + +.PHONY: run-riscv64 +run-riscv64: ovmf/ovmf-code-$(KARCH).fd ovmf/ovmf-vars-$(KARCH).fd $(IMAGE_NAME).iso + qemu-system-$(KARCH) \ + -M virt \ + -cpu rv64 \ + -device ramfb \ + -device qemu-xhci \ + -device usb-kbd \ + -device usb-mouse \ + -drive if=pflash,unit=0,format=raw,file=ovmf/ovmf-code-$(KARCH).fd,readonly=on \ + -drive if=pflash,unit=1,format=raw,file=ovmf/ovmf-vars-$(KARCH).fd \ + -cdrom $(IMAGE_NAME).iso \ + $(QEMUFLAGS) + +.PHONY: run-hdd-riscv64 +run-hdd-riscv64: ovmf/ovmf-code-$(KARCH).fd ovmf/ovmf-vars-$(KARCH).fd $(IMAGE_NAME).hdd + qemu-system-$(KARCH) \ + -M virt \ + -cpu rv64 \ + -device ramfb \ + -device qemu-xhci \ + -device usb-kbd \ + -device usb-mouse \ + -drive if=pflash,unit=0,format=raw,file=ovmf/ovmf-code-$(KARCH).fd,readonly=on \ + -drive if=pflash,unit=1,format=raw,file=ovmf/ovmf-vars-$(KARCH).fd \ + -hda $(IMAGE_NAME).hdd \ + $(QEMUFLAGS) + +.PHONY: run-loongarch64 +run-loongarch64: ovmf/ovmf-code-$(KARCH).fd ovmf/ovmf-vars-$(KARCH).fd $(IMAGE_NAME).iso + qemu-system-$(KARCH) \ + -M virt \ + -cpu la464 \ + -device ramfb \ + -device qemu-xhci \ + -device usb-kbd \ + -device usb-mouse \ + -drive if=pflash,unit=0,format=raw,file=ovmf/ovmf-code-$(KARCH).fd,readonly=on \ + -drive if=pflash,unit=1,format=raw,file=ovmf/ovmf-vars-$(KARCH).fd \ + -cdrom $(IMAGE_NAME).iso \ + $(QEMUFLAGS) + +.PHONY: run-hdd-loongarch64 +run-hdd-loongarch64: ovmf/ovmf-code-$(KARCH).fd ovmf/ovmf-vars-$(KARCH).fd $(IMAGE_NAME).hdd + qemu-system-$(KARCH) \ + -M virt \ + -cpu la464 \ + -device ramfb \ + -device qemu-xhci \ + -device usb-kbd \ + -device usb-mouse \ + -drive if=pflash,unit=0,format=raw,file=ovmf/ovmf-code-$(KARCH).fd,readonly=on \ + -drive if=pflash,unit=1,format=raw,file=ovmf/ovmf-vars-$(KARCH).fd \ + -hda $(IMAGE_NAME).hdd \ + $(QEMUFLAGS) + + +.PHONY: run-bios +run-bios: $(IMAGE_NAME).iso + qemu-system-$(KARCH) \ + -M q35 \ + -cdrom $(IMAGE_NAME).iso \ + -boot d \ + $(QEMUFLAGS) + +.PHONY: run-hdd-bios +run-hdd-bios: $(IMAGE_NAME).hdd + qemu-system-$(KARCH) \ + -M q35 \ + -hda $(IMAGE_NAME).hdd \ + $(QEMUFLAGS) + +ovmf/ovmf-code-$(KARCH).fd: + mkdir -p ovmf + curl -Lo $@ https://github.com/osdev0/edk2-ovmf-nightly/releases/latest/download/ovmf-code-$(KARCH).fd + case "$(KARCH)" in \ + aarch64) dd if=/dev/zero of=$@ bs=1 count=0 seek=67108864 2>/dev/null;; \ + loongarch64) dd if=/dev/zero of=$@ bs=1 count=0 seek=5242880 2>/dev/null;; \ + riscv64) dd if=/dev/zero of=$@ bs=1 count=0 seek=33554432 2>/dev/null;; \ + esac + +ovmf/ovmf-vars-$(KARCH).fd: + mkdir -p ovmf + curl -Lo $@ https://github.com/osdev0/edk2-ovmf-nightly/releases/latest/download/ovmf-vars-$(KARCH).fd + case "$(KARCH)" in \ + aarch64) dd if=/dev/zero of=$@ bs=1 count=0 seek=67108864 2>/dev/null;; \ + loongarch64) dd if=/dev/zero of=$@ bs=1 count=0 seek=5242880 2>/dev/null;; \ + riscv64) dd if=/dev/zero of=$@ bs=1 count=0 seek=33554432 2>/dev/null;; \ + esac + +limine/limine: + rm -rf limine + git clone https://github.com/limine-bootloader/limine.git --branch=v9.x-binary --depth=1 + $(MAKE) -C limine + +.PHONY: kernel +kernel: + $(MAKE) -C kernel + +$(IMAGE_NAME).iso: limine/limine kernel + rm -rf iso_root + mkdir -p iso_root/boot + cp -v kernel/kernel iso_root/boot/ + mkdir -p iso_root/boot/limine + cp -v limine.conf iso_root/boot/limine/ + mkdir -p iso_root/EFI/BOOT +ifeq ($(KARCH),x86_64) + cp -v limine/limine-bios.sys limine/limine-bios-cd.bin limine/limine-uefi-cd.bin iso_root/boot/limine/ + cp -v limine/BOOTX64.EFI iso_root/EFI/BOOT/ + cp -v limine/BOOTIA32.EFI iso_root/EFI/BOOT/ + xorriso -as mkisofs -b boot/limine/limine-bios-cd.bin \ + -no-emul-boot -boot-load-size 4 -boot-info-table \ + --efi-boot boot/limine/limine-uefi-cd.bin \ + -efi-boot-part --efi-boot-image --protective-msdos-label \ + iso_root -o $(IMAGE_NAME).iso + ./limine/limine bios-install $(IMAGE_NAME).iso +endif +ifeq ($(KARCH),aarch64) + cp -v limine/limine-uefi-cd.bin iso_root/boot/limine/ + cp -v limine/BOOTAA64.EFI iso_root/EFI/BOOT/ + xorriso -as mkisofs \ + --efi-boot boot/limine/limine-uefi-cd.bin \ + -efi-boot-part --efi-boot-image --protective-msdos-label \ + iso_root -o $(IMAGE_NAME).iso +endif +ifeq ($(KARCH),riscv64) + cp -v limine/limine-uefi-cd.bin iso_root/boot/limine/ + cp -v limine/BOOTRISCV64.EFI iso_root/EFI/BOOT/ + xorriso -as mkisofs \ + --efi-boot boot/limine/limine-uefi-cd.bin \ + -efi-boot-part --efi-boot-image --protective-msdos-label \ + iso_root -o $(IMAGE_NAME).iso +endif +ifeq ($(KARCH),loongarch64) + cp -v limine/limine-uefi-cd.bin iso_root/boot/limine/ + cp -v limine/BOOTLOONGARCH64.EFI iso_root/EFI/BOOT/ + xorriso -as mkisofs \ + --efi-boot boot/limine/limine-uefi-cd.bin \ + -efi-boot-part --efi-boot-image --protective-msdos-label \ + iso_root -o $(IMAGE_NAME).iso +endif + rm -rf iso_root + +$(IMAGE_NAME).hdd: limine/limine kernel + rm -f $(IMAGE_NAME).hdd + dd if=/dev/zero bs=1M count=0 seek=64 of=$(IMAGE_NAME).hdd + sgdisk $(IMAGE_NAME).hdd -n 1:2048 -t 1:ef00 +ifeq ($(KARCH),x86_64) + ./limine/limine bios-install $(IMAGE_NAME).hdd +endif + mformat -i $(IMAGE_NAME).hdd@@1M + mmd -i $(IMAGE_NAME).hdd@@1M ::/EFI ::/EFI/BOOT ::/boot ::/boot/limine + mcopy -i $(IMAGE_NAME).hdd@@1M kernel/bin-$(KARCH)/kernel ::/boot + mcopy -i $(IMAGE_NAME).hdd@@1M limine.conf ::/boot/limine +ifeq ($(KARCH),x86_64) + mcopy -i $(IMAGE_NAME).hdd@@1M limine/limine-bios.sys ::/boot/limine + mcopy -i $(IMAGE_NAME).hdd@@1M limine/BOOTX64.EFI ::/EFI/BOOT + mcopy -i $(IMAGE_NAME).hdd@@1M limine/BOOTIA32.EFI ::/EFI/BOOT +endif +ifeq ($(KARCH),aarch64) + mcopy -i $(IMAGE_NAME).hdd@@1M limine/BOOTAA64.EFI ::/EFI/BOOT +endif +ifeq ($(KARCH),riscv64) + mcopy -i $(IMAGE_NAME).hdd@@1M limine/BOOTRISCV64.EFI ::/EFI/BOOT +endif +ifeq ($(KARCH),loongarch64) + mcopy -i $(IMAGE_NAME).hdd@@1M limine/BOOTLOONGARCH64.EFI ::/EFI/BOOT +endif + +.PHONY: clean +clean: + $(MAKE) -C kernel clean + rm -rf iso_root $(IMAGE_NAME).iso $(IMAGE_NAME).hdd + +.PHONY: distclean +distclean: clean + $(MAKE) -C kernel distclean + rm -rf limine ovmf diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..9914120 --- /dev/null +++ b/LICENSE @@ -0,0 +1,12 @@ +Copyright (C) 2023-2024 mintsuki and contributors. + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..4710fa0 --- /dev/null +++ b/README.md @@ -0,0 +1,98 @@ +# 🦀 Elyz + +--- + +## 📂 Структура проекта + +* `kernel/` — Исходный код ядра на. +* `limine/` — Файлы загрузчика Limine. +* `ovmf/` — Файлы прошивки для поддержки загрузки через UEFI. +* `limine.conf` — Конфигурация меню загрузки. +* `GNUmakefile` — Основной сценарий сборки и запуска. + +--- + +## 🛠 Требования + +Для работы со сборкой понадобятся следующие инструменты: + +| Инструмент | Описание | +| :--- | :--- | +| **GNU Make** | Утилита для сборки (`make`). | +| **Rust** | Nightly версия, включая `rust-src`. | +| **xorriso** | Необходим для создания загрузочных ISO-образов. | +| **sgdisk & mtools** | Необходимы для создания образов жесткого диска (HDD/USB). | +| **QEMU** | Эмулятор для тестирования ядра. | + +--- + +## Запуск и отладка + +* **Склонируйте репозиторий** + ```bash + git clone https://git.inotfail.com/INotFail/elyz.git + cd elyz + ``` + +* **Сборка ядра** + ```bash + cd kernel + make all + cd ../ + ``` + +* **Запуск (основные способы)** + ```bash + make run-bios + ``` + или + ```bash + make run + ``` + или + ```bash + make run-uefi + ``` + + +`make all` скомпилирует ядро (из kernel/), а затем сгенерирует загрузочный ISO-образ. + +`make run` соберет ядро и загрузочный ISO-образ (эквивалент команды make all), а затем запустит его с помощью команды qemu (если установлено). + +`make all-hdd` скомпилирует ядро, а затем сгенерирует исходный образ, подходящий для записи на USB-накопитель или жесткий диск/SSD. + +`make run-hdd` соберет ядро и необработанный образ жесткого диска (эквивалентно созданию образа для всех жестких дисков), а затем запустит его с помощью qemu (если установлено). + +`run-uefi` и `run-hdd-uefi` цели эквивалентны своим нецелевым `-uefi` аналогам, за исключением того, что они загружаются `qemu` с использованием прошивки, совместимой с UEFI. + + +## 🏗 Поддерживаемые архитектуры + +Переменная `KARCH` определяет целевую архитектуру. По умолчанию используется `x86_64`. + +Вы можете изменить архитектуру при вызове `make`: +```bash +make run KARCH=aarch64 +``` + +**Доступные варианты:** +* `x86_64` (Default) +* `aarch64` +* `riscv64` +* `loongarch64` + +> Для архитектур, отличных от x86, потребуется настройка соответствующих целевых платформ в `kernel/rust-toolchain.toml`. + +--- + +## 📝 Важное + +* **Очистка проекта:** Чтобы удалить все артефакты сборки и скомпилированные файлы, выполните: + ```bash + make clean + ``` +* **Логи:** Ядро выводит данные в консоль QEMU. + +--- + +**Boot основан на оригинальном шаблоне:** [jasondyoungberg/limine-rust-template](https://github.com/jasondyoungberg/limine-rust-template) diff --git a/kernel/.gitignore b/kernel/.gitignore new file mode 100644 index 0000000..6b51966 --- /dev/null +++ b/kernel/.gitignore @@ -0,0 +1,2 @@ +/kernel +/target diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml new file mode 100644 index 0000000..9c8642f --- /dev/null +++ b/kernel/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "RINA" +version = "0.1.0" +edition = "2024" + +[[bin]] +name = "kernel" +path = "src/main.rs" + +[dependencies] +limine = "0.5" +embedded-graphics = "0.8" + +[profile.dev] +panic = "abort" + +[profile.release] +panic = "abort" diff --git a/kernel/GNUmakefile b/kernel/GNUmakefile new file mode 100644 index 0000000..46e0f2b --- /dev/null +++ b/kernel/GNUmakefile @@ -0,0 +1,44 @@ +# Nuke built-in rules and variables. +MAKEFLAGS += -rR +.SUFFIXES: + +# This is the name that our final executable will have. +# Change as needed. +override OUTPUT := kernel + +# Convenience macro to reliably declare user overridable variables. +override USER_VARIABLE = $(if $(filter $(origin $(1)),default undefined),$(eval override $(1) := $(2))) + +# Target architecture to build for. Default to x86_64. +$(call USER_VARIABLE,KARCH,x86_64) + +ifeq ($(RUST_TARGET),) + override RUST_TARGET := $(KARCH)-unknown-none + ifeq ($(KARCH),riscv64) + override RUST_TARGET := riscv64gc-unknown-none-elf + endif +endif + +ifeq ($(RUST_PROFILE),) + override RUST_PROFILE := dev +endif + +override RUST_PROFILE_SUBDIR := $(RUST_PROFILE) +ifeq ($(RUST_PROFILE),dev) + override RUST_PROFILE_SUBDIR := debug +endif + +# Default target. +.PHONY: all +all: + RUSTFLAGS="-C relocation-model=static" cargo build --target $(RUST_TARGET) --profile $(RUST_PROFILE) + cp target/$(RUST_TARGET)/$(RUST_PROFILE_SUBDIR)/$$(cd target/$(RUST_TARGET)/$(RUST_PROFILE_SUBDIR) && find -maxdepth 1 -perm -111 -type f) kernel + +# Remove object files and the final executable. +.PHONY: clean +clean: + cargo clean + rm -rf kernel + +.PHONY: distclean +distclean: clean diff --git a/kernel/rust-toolchain.toml b/kernel/rust-toolchain.toml new file mode 100644 index 0000000..66a0077 --- /dev/null +++ b/kernel/rust-toolchain.toml @@ -0,0 +1,8 @@ +[toolchain] +channel = "nightly" +targets = [ + "x86_64-unknown-none", + # "aarch64-unknown-none", + # "riscv64gc-unknown-none-elf", + # "loongarch64-unknown-none", +] diff --git a/kernel/src/main.rs b/kernel/src/main.rs new file mode 100644 index 0000000..26781aa --- /dev/null +++ b/kernel/src/main.rs @@ -0,0 +1,193 @@ +#![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"); + } + } +} diff --git a/limine.conf b/limine.conf new file mode 100644 index 0000000..0978db7 --- /dev/null +++ b/limine.conf @@ -0,0 +1,10 @@ +# Timeout in seconds that Limine will use before automatically booting. +timeout: 3 + +# The entry name that will be displayed in the boot menu. +/Elyz (RINA KERNEL) + # We use the Limine boot protocol. + protocol: limine + + # Path to the kernel to boot. boot():/ represents the partition on which limine.conf is located. + kernel_path: boot():/boot/kernel