This commit is contained in:
Faynot
2026-03-27 14:06:30 +03:00
commit aa357b6198
10 changed files with 654 additions and 0 deletions

18
.gitignore vendored Normal file
View File

@@ -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/

251
GNUmakefile Normal file
View File

@@ -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

12
LICENSE Normal file
View File

@@ -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.

98
README.md Normal file
View File

@@ -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)

2
kernel/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
/kernel
/target

18
kernel/Cargo.toml Normal file
View File

@@ -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"

44
kernel/GNUmakefile Normal file
View File

@@ -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

View File

@@ -0,0 +1,8 @@
[toolchain]
channel = "nightly"
targets = [
"x86_64-unknown-none",
# "aarch64-unknown-none",
# "riscv64gc-unknown-none-elf",
# "loongarch64-unknown-none",
]

193
kernel/src/main.rs Normal file
View File

@@ -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<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");
}
}
}

10
limine.conf Normal file
View File

@@ -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