feat: initial x86_64 port

This commit is contained in:
Jordan ⌨️ 2025-09-24 22:48:39 +02:00
parent 0600245c83
commit 335e24a733
24 changed files with 1343 additions and 55 deletions

12
build
View file

@ -1,12 +0,0 @@
#!/usr/bin/env -S uv run -s
# /// script
# requires-python = ">=3.11"
# dependencies = [
# "cutekit @ git+https://github.com/cute-engineering/cutekit.git@stable",
# ]
# ///
import sys
import cutekit as ck
sys.exit(ck.main())

View file

@ -1,5 +1,4 @@
from . import (
headers,
cli,
enforce_c99
)

View file

@ -1,24 +1,71 @@
from cutekit import cli, model, shell, builder
from pathlib import Path
@cli.command("boot", "Boot the kernel inside of Qemu")
def _(args: model.RegistryArgs):
registry = model.Registry.use(args)
from cutekit import cli, model, shell
target = registry.lookup('kernel-riscv32', model.Target)
assert target is not None
from .image import Image
component = registry.lookup('core', model.Component)
assert component is not None
scope = builder.TargetScope(registry, target)
kernelProduct = builder.build(scope, component)[0]
def generateImg(img: Image, target: str) -> Path:
modules = []
img.mkdir("/efi/boot")
img.mkdir("/bin")
img.cp(img.build("core", f"kernel-{target}"), Path("/kernel.elf"))
shell.exec(*[
"qemu-system-riscv32",
"-machine", "virt",
"-bios", "default",
"-nographic",
"-serial", "mon:stdio",
"-kernel", str(kernelProduct.path),
"--no-reboot",
])
if target == "x86_64":
img.wget(
"https://codeberg.org/Limine/Limine/raw/branch/v10.x-binary/BOOTX64.EFI",
"efi/boot/bootx64.efi",
)
img.export_limine(Path("/efi/boot"), Path("/kernel.elf"), modules)
return img.path
@cli.command("image", "Generate the boot image")
def _(): ...
class StartArgs(model.RegistryArgs):
debug: bool = cli.arg(None, "debug", "Build the image in debug mode")
arch: str = cli.arg(None, "arch", "The architecture of the image", default="x86_64")
@cli.command("image/start", "Run the system inside the emulator")
def _(args: StartArgs):
if args.arch not in ["x86_64", "riscv32"]:
raise RuntimeError(f"Unsupported architecture: {args.arch}")
p = generateImg(Image(model.Registry.use(args), f"kernel-{args.arch}"), args.arch)
match args.arch:
case "x86_64":
shell.exec(
*[
"qemu-system-x86_64",
# "-enable-kvm",
"-no-reboot",
"-no-shutdown",
# "-display",
# "none",
"-smp",
"4",
"-serial",
"mon:stdio",
"-drive",
f"format=raw,file=fat:rw:{p},media=disk",
"-bios",
shell.wget("https://retrage.github.io/edk2-nightly/bin/RELEASEX64_OVMF.fd"),
]
)
case "riscv32":
shell.exec(
*[
"qemu-system-riscv32",
"-machine", "virt",
"-bios", "default",
"-nographic",
"-serial", "mon:stdio",
"-kernel", str(p / "kernel.elf"),
"--no-reboot",
]
)

View file

@ -1,12 +0,0 @@
from cutekit.rules import rules
rules['cc'].args.append('-pedantic')
rules['cc'].args.append('-Wpedantic')
rules['cc'].args.append('-Wno-dollar-in-identifier-extension')
rules['cc'].args.append('-Wno-gnu-statement-expression-from-macro-expansion')
for arg in rules['cc'].args:
if "-std=" in arg:
rules['cc'].args.remove(arg)
rules['cc'].args.append('-std=c99')
break

55
meta/plugins/image.py Normal file
View file

@ -0,0 +1,55 @@
import os
from hashlib import blake2b
from cutekit import model, builder, const, shell
from pathlib import Path
class Image:
def __init__(self, registry: model.Registry, name: str):
self.__registry: model.Registry = registry
self.__name = name
@property
def path(self) -> Path:
return Path(const.PROJECT_CK_DIR) / "images" / self.__name
def build(self, component_spec: str, target_spec: str) -> Path:
comp = self.__registry.lookup(component_spec, model.Component)
target = self.__registry.lookup(target_spec, model.Target)
assert comp is not None
assert target is not None
scope = builder.TargetScope(self.__registry, target)
return Path(builder.build(scope, comp)[0].path)
def cp(self, src: Path, dst: Path) -> list[Path]:
shell.cp(str(src), str(self.path / str(dst).removeprefix(os.path.sep)))
return [dst]
def mkdir(self, name: str):
(self.path / str(name).removeprefix("/")).mkdir(parents=True, exist_ok=True)
def wget(self, link: str, dst: str):
shell.wget(link, str(self.path / str(dst).removeprefix(os.path.sep)))
def get_hash(self, target: Path) -> str:
with (self.path / str(target).removeprefix(os.path.sep)).open("rb") as f:
return blake2b(f.read()).hexdigest()
def export_limine(self, target: Path, kernel: Path, modules: list[Path]):
rel_path = Path(self.path / str(target).removeprefix(os.path.sep))
with (rel_path / "limine.conf").open("w") as f:
f.writelines(
[
"randomize_memory: yes\n",
"timeout: 0\n\n",
f"/{self.__name}\n",
" protocol: limine\n",
f" kernel_path: boot():{kernel.as_posix()}#{self.get_hash(kernel)}\n",
]
+ [
f" module_path: boot():{module.as_posix()}#{self.get_hash(module)}\n"
for module in modules
]
)

View file

@ -30,15 +30,16 @@
]
},
"ld": {
"cmd": "{shell.latest('clang')}",
"cmd": "{shell.latest('ld.lld')}",
"args": [
"--target=riscv32",
"-nostdlib",
"-ffreestanding",
"-Wl,-Tmeta/targets/kernel-riscv32.ld"
"-m",
"elf32lriscv",
"-T{utils.relpath('kernel-riscv32.ld')}",
"-z",
"max-page-size=0x1000"
],
"files": [
"meta/targets/kernel-riscv32.ld"
"{utils.relpath('kernel-riscv32.ld')}"
]
},
"ar": {

View file

@ -0,0 +1,78 @@
{
"$schema": "https://schemas.cute.engineering/stable/cutekit.manifest.target.v1",
"id": "kernel-x86_64",
"type": "target",
"props": {
"toolchain": "clang",
"arch": "x86_64",
"sys": "kernel",
"abi": "sysv",
"bits": "64",
"freestanding": true,
"host": false,
"sys-encoding": "utf8",
"sys-line-ending": "lf",
"sys-path-separator": "slash",
"sys-terminal": "ansi"
},
"tools": {
"cc": {
"cmd": "{shell.latest('clang')}",
"args": [
"--target=x86_64-none-elf",
"-ffreestanding",
"-fno-stack-protector",
"-mno-80387",
"-mno-mmx",
"-mno-3dnow",
"-mno-sse",
"-mno-sse2",
"-mno-red-zone",
"-mcmodel=kernel"
]
},
"cxx": {
"cmd": "{shell.latest('clang++')}",
"args": [
"--target=x86_64-none-elf",
"-ffreestanding",
"-fno-stack-protector",
"-mno-80387",
"-mno-mmx",
"-mno-3dnow",
"-mno-sse",
"-mno-sse2",
"-mno-red-zone",
"-mcmodel=kernel",
"-fno-exceptions",
"-fno-rtti"
]
},
"ld": {
"cmd": "{shell.latest('ld.lld')}",
"args": [
"-m",
"elf_x86_64",
"-T{utils.relpath('kernel-x86_64.ld')}",
"-z",
"max-page-size=0x1000"
],
"files": [
"{utils.relpath('kernel-x86_64.ld')}"
]
},
"ar": {
"cmd": "{shell.latest('llvm-ar')}",
"args": [
"rcs"
]
},
"as": {
"cmd": "nasm",
"args": [
"-f",
"elf64"
]
}
}
}

View file

@ -0,0 +1,75 @@
/* Tell the linker that we want an x86_64 ELF64 output file */
OUTPUT_FORMAT(elf64-x86-64)
/* We want the symbol kmain to be our entry point */
ENTRY(x86_64_start)
/* Define the program headers we want so the bootloader gives us the right */
/* MMU permissions; this also allows us to exert more control over the linking */
/* process. */
PHDRS
{
limine_requests PT_LOAD;
text PT_LOAD;
rodata PT_LOAD;
data PT_LOAD;
}
SECTIONS
{
/* We want to be placed in the topmost 2GiB of the address space, for optimisations */
/* and because that is what the Limine spec mandates. */
/* Any address in this region will do, but often 0xffffffff80000000 is chosen as */
/* that is the beginning of the region. */
. = 0xffffffff80000000;
/* Define a section to contain the Limine requests and assign it to its own PHDR */
.limine_requests : {
KEEP(*(.limine_requests_start))
KEEP(*(.limine_requests))
KEEP(*(.limine_requests_end))
} :limine_requests
/* Move to the next memory page for .text */
. = ALIGN(CONSTANT(MAXPAGESIZE));
.text : {
*(.text .text.*)
} :text
/* Move to the next memory page for .rodata */
. = ALIGN(CONSTANT(MAXPAGESIZE));
.rodata : {
*(.rodata .rodata.*)
} :rodata
/* Add a .note.gnu.build-id output section in case a build ID flag is added to the */
/* linker command. */
.note.gnu.build-id : {
*(.note.gnu.build-id)
} :rodata
/* Move to the next memory page for .data */
. = ALIGN(CONSTANT(MAXPAGESIZE));
.data : {
*(.data .data.*)
} :data
/* NOTE: .bss needs to be the last thing mapped to :data, otherwise lots of */
/* unnecessary zeros will be written to the binary. */
/* If you need, for example, .init_array and .fini_array, those should be placed */
/* above this. */
.bss : {
*(.bss .bss.*)
*(COMMON)
} :data
/* Discard .note.* and .eh_frame* since they may cause issues on some hosts. */
/DISCARD/ : {
*(.eh_frame*)
*(.note .note.*)
}
}

View file

@ -12,7 +12,7 @@
#include "paging.h"
extern char __bss[], __bss_end[];
extern void kmain(void);
void kmain(void);
static uint8_t early_heap[kib$(32)];
static DTBNode* dtb_root = NULL;

View file

@ -0,0 +1,18 @@
#include <dtb>
#include <limine>
#include <logger>
__attribute__((used, section(".limine_requests"))) static volatile LIMINE_BASE_REVISION(3);
__attribute__((used, section(".limine_requests_start"))) static volatile LIMINE_REQUESTS_START_MARKER;
__attribute__((used, section(".limine_requests_end"))) static volatile LIMINE_REQUESTS_END_MARKER;
void kmain(void);
void x86_64_start(void) {
info$("Hello, x86_64 !");
// kmain();
}
DTBNode* hal_dtb_root(void) {
return NULL;
}

View file

@ -0,0 +1,44 @@
#include <hal>
#include <limine>
#include <logger>
#include "serial.h"
__attribute__((used, section(".limine_requests"))) static volatile struct limine_hhdm_request hhdm_req = {
.id = LIMINE_HHDM_REQUEST,
.revision = 0,
};
void hal_putc(int ch) {
static bool is_serial_init = false;
if (!is_serial_init) [[clang::unlikely]] {
serial_init(COM1, SERIAL_BAUD_RATE);
is_serial_init = true;
}
serial_putc(COM1, ch);
}
size_t page_size(void) {
return 4096;
}
void hal_brkpoint(void) {
__asm__ volatile("int $3");
}
void* hal_mmap_l2h(uintptr_t addr) {
if (hhdm_req.response == NULL) [[clang::unlikely]] {
panic$("Couldn't get limine's HHDM");
}
return (void*)(addr + hhdm_req.response->offset);
}
void* hal_mmap_h2l(uintptr_t addr) {
if (hhdm_req.response == NULL) [[clang::unlikely]] {
panic$("Couldn't get limine's HHDM");
}
return (void*)(addr - hhdm_req.response->offset);
}

View file

@ -0,0 +1,17 @@
#include "ioport.h"
uint8_t in8(uint16_t port) {
uint8_t ret;
__asm__ volatile("inb %w1, %b0"
: "=a"(ret)
: "Nd"(port)
: "memory");
return ret;
}
void out8(uint16_t port, uint8_t val) {
__asm__ volatile("outb %b0, %w1" :
: "a"(val),
"Nd"(port)
: "memory");
}

View file

@ -0,0 +1,6 @@
#pragma once
#include <stdint.h>
uint8_t in8(uint16_t port);
void out8(uint16_t port, uint8_t val);

View file

@ -0,0 +1,11 @@
{
"$schema": "https://schemas.cute.engineering/stable/cutekit.manifest.component.v1",
"type": "lib",
"id": "hal-x86_64",
"enableIf": {
"arch": ["x86_64"],
"sys": ["kernel"]
},
"provides": ["hal-impl"],
"requires": ["pmm", "kmalloc", "handover", "handover-limine"]
}

View file

@ -0,0 +1,39 @@
#include "serial.h"
#include "ioport.h"
static void write_register(uint16_t port, uint16_t offset, uint8_t value) {
out8(port + offset, value);
}
static uint8_t read_register(uint16_t port, uint16_t offset) {
return in8(port + offset);
}
void _serial_init(enum comPortNo port, uint32_t rate) {
if (SERIAL_BAUD_RATE % rate > 0) {
return;
}
uint16_t div = SERIAL_BAUD_RATE / rate;
write_register(port, SERIAL_INTERRUPT_REG, SERIAL_DISABLE_INTERRUPT);
write_register(port, SERIAL_LINE_CTRL_REG, SERIAL_LINE_CTRL_DLAB);
write_register(port, SERIAL_BAUD_LSB, div & 0xff);
write_register(port, SERIAL_BAUD_MSB, div >> 8);
write_register(port, SERIAL_LINE_CTRL_REG, SERIAL_LINE_CTRL_DATA8);
write_register(port, SERIAL_FIFO_CTRL_REG, SERIAL_FIFO_CTRL_FIFO | SERIAL_FIFO_CTRL_CLEAR_RX | SERIAL_FIFO_CTRL_CLEAR_TX | SERIAL_FIFO_CTRL_INT14);
write_register(port, SERIAL_MODEM_REG, SERIAL_MODEM_DTR | SERIAL_MODEM_RTS | SERIAL_MODEM_IRQ | SERIAL_MODEM_OUT2);
}
static void serial_wait_ready(enum comPortNo port) {
while ((read_register(port, SERIAL_LINE_STATUS_REG) & SERIAL_LINE_TRANSMITTER_EMPTY) == 0)
;
}
void serial_putc(enum comPortNo port, char c) {
serial_wait_ready(port);
write_register(port, SERIAL_TRANSMIT_BUFFER, c);
}

View file

@ -0,0 +1,64 @@
#pragma once
#include <stdint.h>
#define SERIAL_INTERRUPT_REG (1)
#define SERIAL_ENABLE_INTERRUPT (1)
#define SERIAL_DISABLE_INTERRUPT (0)
#define SERIAL_TRANSMIT_BUFFER (0)
#define SERIAL_FIFO_CTRL_REG (2)
#define SERIAL_FIFO_CTRL_FIFO (1 << 0)
#define SERIAL_FIFO_CTRL_CLEAR_RX (1 << 1)
#define SERIAL_FIFO_CTRL_CLEAR_TX (1 << 2)
#define SERIAL_FIFO_CTRL_DMA (1 << 3)
#define SERIAL_FIFO_CTRL_INT1 (0b00)
#define SERIAL_FIFO_CTRL_INT4 (0b01 << 6)
#define SERIAL_FIFO_CTRL_INT8 (0b10 << 6)
#define SERIAL_FIFO_CTRL_INT14 (0b11 << 6)
#define SERIAL_LINE_CTRL_REG (3)
#define SERIAL_LINE_CTRL_DATA5 (0b00)
#define SERIAL_LINE_CTRL_DATA6 (0b01)
#define SERIAL_LINE_CTRL_DATA7 (0b10)
#define SERIAL_LINE_CTRL_DATA8 (0b11)
#define SERIAL_LINE_CTRL_STOP (1 << 2)
#define SERIAL_LINE_CTRL_PARITY (0b111 << 3)
#define SERIAL_LINE_CTRL_BRK (1 << 6)
#define SERIAL_LINE_CTRL_DLAB (1 << 7)
#define SERIAL_MODEM_REG (4)
#define SERIAL_MODEM_DTR (1 << 0)
#define SERIAL_MODEM_RTS (1 << 1)
#define SERIAL_MODEM_OUT2 (1 << 2)
#define SERIAL_MODEM_IRQ (1 << 3)
#define SERIAL_MODEM_LOOP (1 << 4)
#define SERIAL_LINE_STATUS_REG (5)
#define SERIAL_LINE_DATA_READY (1 << 0)
#define SERIAL_LINE_TRANSMITTER_EMPTY (1 << 5)
// IF DLAB = 1
#define SERIAL_BAUD_LSB (0)
#define SERIAL_BAUD_MSB (1)
#define SERIAL_BAUD_RATE (115200)
enum comPortNo {
COM1 = 0x3f8,
COM2 = 0x2f8,
COM3 = 0x3e8,
COM4 = 0x2e8,
COM5 = 0x5f8,
COM6 = 0x4f8,
COM7 = 0x5e8,
COM8 = 0x4e8,
};
#define serial_init(PORT, RATE) \
_Static_assert(SERIAL_BAUD_RATE % RATE == 0, "Invalid baud rate"); \
_serial_init(PORT, RATE);
void _serial_init(enum comPortNo port, uint32_t rate);
void serial_putc(enum comPortNo port, char c);

View file

@ -0,0 +1,5 @@
{
"$schema": "https://schemas.cute.engineering/stable/cutekit.manifest.component.v1",
"type": "lib",
"id": "limine"
}

View file

@ -0,0 +1,833 @@
/* BSD Zero Clause License */
/* Copyright (C) 2022-2025 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.
*/
#ifndef LIMINE_H
# define LIMINE_H 1
# ifdef __cplusplus
extern "C" {
# endif
# include <stdint.h>
/* Misc */
# ifdef LIMINE_NO_POINTERS
# define LIMINE_PTR(TYPE) uint64_t
# else
# define LIMINE_PTR(TYPE) TYPE
# endif
# ifndef LIMINE_API_REVISION
# define LIMINE_API_REVISION 0
# endif
# if LIMINE_API_REVISION > 3
# error "limine.h API revision unsupported"
# endif
# ifdef __GNUC__
# define LIMINE_DEPRECATED __attribute__((__deprecated__))
# define LIMINE_DEPRECATED_IGNORE_START \
_Pragma("GCC diagnostic push") \
_Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
# define LIMINE_DEPRECATED_IGNORE_END \
_Pragma("GCC diagnostic pop")
# else
# define LIMINE_DEPRECATED
# define LIMINE_DEPRECATED_IGNORE_START
# define LIMINE_DEPRECATED_IGNORE_END
# endif
# define LIMINE_REQUESTS_START_MARKER \
uint64_t limine_requests_start_marker[4] = {0xf6b8f4b39de7d1ae, 0xfab91a6940fcb9cf, 0x785c6ed015d3e316, 0x181e920a7852b9d9};
# define LIMINE_REQUESTS_END_MARKER \
uint64_t limine_requests_end_marker[2] = {0xadc0e0531bb10d03, 0x9572709f31764c62};
# define LIMINE_REQUESTS_DELIMITER LIMINE_REQUESTS_END_MARKER
# define LIMINE_BASE_REVISION(N) \
uint64_t limine_base_revision[3] = {0xf9562b2d5c95a6c8, 0x6a7b384944536bdc, (N)};
# define LIMINE_BASE_REVISION_SUPPORTED (limine_base_revision[2] == 0)
# define LIMINE_LOADED_BASE_REV_VALID (limine_base_revision[1] != 0x6a7b384944536bdc)
# define LIMINE_LOADED_BASE_REVISION (limine_base_revision[1])
# define LIMINE_COMMON_MAGIC 0xc7b1dd30df4c8b88, 0x0a82e883a194f07b
struct limine_uuid {
uint32_t a;
uint16_t b;
uint16_t c;
uint8_t d[8];
};
# define LIMINE_MEDIA_TYPE_GENERIC 0
# define LIMINE_MEDIA_TYPE_OPTICAL 1
# define LIMINE_MEDIA_TYPE_TFTP 2
struct limine_file {
uint64_t revision;
LIMINE_PTR(void*)
address;
uint64_t size;
LIMINE_PTR(char*)
path;
# if LIMINE_API_REVISION >= 3
LIMINE_PTR(char*)
string;
# else
LIMINE_PTR(char*)
cmdline;
# endif
uint32_t media_type;
uint32_t unused;
uint32_t tftp_ip;
uint32_t tftp_port;
uint32_t partition_index;
uint32_t mbr_disk_id;
struct limine_uuid gpt_disk_uuid;
struct limine_uuid gpt_part_uuid;
struct limine_uuid part_uuid;
};
/* Boot info */
# define LIMINE_BOOTLOADER_INFO_REQUEST {LIMINE_COMMON_MAGIC, 0xf55038d8e2a1202f, 0x279426fcf5f59740}
struct limine_bootloader_info_response {
uint64_t revision;
LIMINE_PTR(char*)
name;
LIMINE_PTR(char*)
version;
};
struct limine_bootloader_info_request {
uint64_t id[4];
uint64_t revision;
LIMINE_PTR(struct limine_bootloader_info_response*)
response;
};
/* Executable command line */
# define LIMINE_EXECUTABLE_CMDLINE_REQUEST {LIMINE_COMMON_MAGIC, 0x4b161536e598651e, 0xb390ad4a2f1f303a}
struct limine_executable_cmdline_response {
uint64_t revision;
LIMINE_PTR(char*)
cmdline;
};
struct limine_executable_cmdline_request {
uint64_t id[4];
uint64_t revision;
LIMINE_PTR(struct limine_executable_cmdline_response*)
response;
};
/* Firmware type */
# define LIMINE_FIRMWARE_TYPE_REQUEST {LIMINE_COMMON_MAGIC, 0x8c2f75d90bef28a8, 0x7045a4688eac00c3}
# define LIMINE_FIRMWARE_TYPE_X86BIOS 0
# define LIMINE_FIRMWARE_TYPE_UEFI32 1
# define LIMINE_FIRMWARE_TYPE_UEFI64 2
# define LIMINE_FIRMWARE_TYPE_SBI 3
struct limine_firmware_type_response {
uint64_t revision;
uint64_t firmware_type;
};
struct limine_firmware_type_request {
uint64_t id[4];
uint64_t revision;
LIMINE_PTR(struct limine_firmware_type_response*)
response;
};
/* Stack size */
# define LIMINE_STACK_SIZE_REQUEST {LIMINE_COMMON_MAGIC, 0x224ef0460a8e8926, 0xe1cb0fc25f46ea3d}
struct limine_stack_size_response {
uint64_t revision;
};
struct limine_stack_size_request {
uint64_t id[4];
uint64_t revision;
LIMINE_PTR(struct limine_stack_size_response*)
response;
uint64_t stack_size;
};
/* HHDM */
# define LIMINE_HHDM_REQUEST {LIMINE_COMMON_MAGIC, 0x48dcf1cb8ad2b852, 0x63984e959a98244b}
struct limine_hhdm_response {
uint64_t revision;
uint64_t offset;
};
struct limine_hhdm_request {
uint64_t id[4];
uint64_t revision;
LIMINE_PTR(struct limine_hhdm_response*)
response;
};
/* Framebuffer */
# define LIMINE_FRAMEBUFFER_REQUEST {LIMINE_COMMON_MAGIC, 0x9d5827dcd881dd75, 0xa3148604f6fab11b}
# define LIMINE_FRAMEBUFFER_RGB 1
struct limine_video_mode {
uint64_t pitch;
uint64_t width;
uint64_t height;
uint16_t bpp;
uint8_t memory_model;
uint8_t red_mask_size;
uint8_t red_mask_shift;
uint8_t green_mask_size;
uint8_t green_mask_shift;
uint8_t blue_mask_size;
uint8_t blue_mask_shift;
};
struct limine_framebuffer {
LIMINE_PTR(void*)
address;
uint64_t width;
uint64_t height;
uint64_t pitch;
uint16_t bpp;
uint8_t memory_model;
uint8_t red_mask_size;
uint8_t red_mask_shift;
uint8_t green_mask_size;
uint8_t green_mask_shift;
uint8_t blue_mask_size;
uint8_t blue_mask_shift;
uint8_t unused[7];
uint64_t edid_size;
LIMINE_PTR(void*)
edid;
/* Response revision 1 */
uint64_t mode_count;
LIMINE_PTR(struct limine_video_mode**)
modes;
};
struct limine_framebuffer_response {
uint64_t revision;
uint64_t framebuffer_count;
LIMINE_PTR(struct limine_framebuffer**)
framebuffers;
};
struct limine_framebuffer_request {
uint64_t id[4];
uint64_t revision;
LIMINE_PTR(struct limine_framebuffer_response*)
response;
};
/* Terminal */
# define LIMINE_TERMINAL_REQUEST {LIMINE_COMMON_MAGIC, 0xc8ac59310c2b0844, 0xa68d0c7265d38878}
# define LIMINE_TERMINAL_CB_DEC 10
# define LIMINE_TERMINAL_CB_BELL 20
# define LIMINE_TERMINAL_CB_PRIVATE_ID 30
# define LIMINE_TERMINAL_CB_STATUS_REPORT 40
# define LIMINE_TERMINAL_CB_POS_REPORT 50
# define LIMINE_TERMINAL_CB_KBD_LEDS 60
# define LIMINE_TERMINAL_CB_MODE 70
# define LIMINE_TERMINAL_CB_LINUX 80
# define LIMINE_TERMINAL_CTX_SIZE ((uint64_t)(-1))
# define LIMINE_TERMINAL_CTX_SAVE ((uint64_t)(-2))
# define LIMINE_TERMINAL_CTX_RESTORE ((uint64_t)(-3))
# define LIMINE_TERMINAL_FULL_REFRESH ((uint64_t)(-4))
/* Response revision 1 */
# define LIMINE_TERMINAL_OOB_OUTPUT_GET ((uint64_t)(-10))
# define LIMINE_TERMINAL_OOB_OUTPUT_SET ((uint64_t)(-11))
# define LIMINE_TERMINAL_OOB_OUTPUT_OCRNL (1 << 0)
# define LIMINE_TERMINAL_OOB_OUTPUT_OFDEL (1 << 1)
# define LIMINE_TERMINAL_OOB_OUTPUT_OFILL (1 << 2)
# define LIMINE_TERMINAL_OOB_OUTPUT_OLCUC (1 << 3)
# define LIMINE_TERMINAL_OOB_OUTPUT_ONLCR (1 << 4)
# define LIMINE_TERMINAL_OOB_OUTPUT_ONLRET (1 << 5)
# define LIMINE_TERMINAL_OOB_OUTPUT_ONOCR (1 << 6)
# define LIMINE_TERMINAL_OOB_OUTPUT_OPOST (1 << 7)
LIMINE_DEPRECATED_IGNORE_START
struct LIMINE_DEPRECATED limine_terminal;
typedef void (*limine_terminal_write)(struct limine_terminal*, char const*, uint64_t);
typedef void (*limine_terminal_callback)(struct limine_terminal*, uint64_t, uint64_t, uint64_t, uint64_t);
struct LIMINE_DEPRECATED limine_terminal {
uint64_t columns;
uint64_t rows;
LIMINE_PTR(struct limine_framebuffer*)
framebuffer;
};
struct LIMINE_DEPRECATED limine_terminal_response {
uint64_t revision;
uint64_t terminal_count;
LIMINE_PTR(struct limine_terminal**)
terminals;
LIMINE_PTR(limine_terminal_write)
write;
};
struct LIMINE_DEPRECATED limine_terminal_request {
uint64_t id[4];
uint64_t revision;
LIMINE_PTR(struct limine_terminal_response*)
response;
LIMINE_PTR(limine_terminal_callback)
callback;
};
LIMINE_DEPRECATED_IGNORE_END
/* Paging mode */
# define LIMINE_PAGING_MODE_REQUEST {LIMINE_COMMON_MAGIC, 0x95c1a0edab0944cb, 0xa4e5cb3842f7488a}
# if defined(__x86_64__) || defined(__i386__)
# define LIMINE_PAGING_MODE_X86_64_4LVL 0
# define LIMINE_PAGING_MODE_X86_64_5LVL 1
# define LIMINE_PAGING_MODE_MIN LIMINE_PAGING_MODE_X86_64_4LVL
# define LIMINE_PAGING_MODE_DEFAULT LIMINE_PAGING_MODE_X86_64_4LVL
# elif defined(__aarch64__)
# define LIMINE_PAGING_MODE_AARCH64_4LVL 0
# define LIMINE_PAGING_MODE_AARCH64_5LVL 1
# define LIMINE_PAGING_MODE_MIN LIMINE_PAGING_MODE_AARCH64_4LVL
# define LIMINE_PAGING_MODE_DEFAULT LIMINE_PAGING_MODE_AARCH64_4LVL
# elif defined(__riscv) && (__riscv_xlen == 64)
# define LIMINE_PAGING_MODE_RISCV_SV39 0
# define LIMINE_PAGING_MODE_RISCV_SV48 1
# define LIMINE_PAGING_MODE_RISCV_SV57 2
# define LIMINE_PAGING_MODE_MIN LIMINE_PAGING_MODE_RISCV_SV39
# define LIMINE_PAGING_MODE_DEFAULT LIMINE_PAGING_MODE_RISCV_SV48
# elif defined(__loongarch__) && (__loongarch_grlen == 64)
# define LIMINE_PAGING_MODE_LOONGARCH64_4LVL 0
# define LIMINE_PAGING_MODE_MIN LIMINE_PAGING_MODE_LOONGARCH64_4LVL
# define LIMINE_PAGING_MODE_DEFAULT LIMINE_PAGING_MODE_LOONGARCH64_4LVL
# else
# error Unknown architecture
# endif
struct limine_paging_mode_response {
uint64_t revision;
uint64_t mode;
};
struct limine_paging_mode_request {
uint64_t id[4];
uint64_t revision;
LIMINE_PTR(struct limine_paging_mode_response*)
response;
uint64_t mode;
uint64_t max_mode;
uint64_t min_mode;
};
/* 5-level paging */
# define LIMINE_5_LEVEL_PAGING_REQUEST {LIMINE_COMMON_MAGIC, 0x94469551da9b3192, 0xebe5e86db7382888}
LIMINE_DEPRECATED_IGNORE_START
struct LIMINE_DEPRECATED limine_5_level_paging_response {
uint64_t revision;
};
struct LIMINE_DEPRECATED limine_5_level_paging_request {
uint64_t id[4];
uint64_t revision;
LIMINE_PTR(struct limine_5_level_paging_response*)
response;
};
LIMINE_DEPRECATED_IGNORE_END
/* MP */
# if LIMINE_API_REVISION >= 1
# define LIMINE_MP_REQUEST {LIMINE_COMMON_MAGIC, 0x95a67b819a1b857e, 0xa0b61b723b6a73e0}
# define LIMINE_MP(TEXT) limine_mp_##TEXT
# else
# define LIMINE_SMP_REQUEST {LIMINE_COMMON_MAGIC, 0x95a67b819a1b857e, 0xa0b61b723b6a73e0}
# define LIMINE_MP(TEXT) limine_smp_##TEXT
# endif
struct LIMINE_MP(info);
typedef void (*limine_goto_address)(struct LIMINE_MP(info) *);
# if defined(__x86_64__) || defined(__i386__)
# if LIMINE_API_REVISION >= 1
# define LIMINE_MP_X2APIC (1 << 0)
# else
# define LIMINE_SMP_X2APIC (1 << 0)
# endif
struct LIMINE_MP(info) {
uint32_t processor_id;
uint32_t lapic_id;
uint64_t reserved;
LIMINE_PTR(limine_goto_address)
goto_address;
uint64_t extra_argument;
};
struct LIMINE_MP(response) {
uint64_t revision;
uint32_t flags;
uint32_t bsp_lapic_id;
uint64_t cpu_count;
LIMINE_PTR(struct LIMINE_MP(info) **)
cpus;
};
# elif defined(__aarch64__)
struct LIMINE_MP(info) {
uint32_t processor_id;
uint32_t reserved1;
uint64_t mpidr;
uint64_t reserved;
LIMINE_PTR(limine_goto_address)
goto_address;
uint64_t extra_argument;
};
struct LIMINE_MP(response) {
uint64_t revision;
uint64_t flags;
uint64_t bsp_mpidr;
uint64_t cpu_count;
LIMINE_PTR(struct LIMINE_MP(info) **)
cpus;
};
# elif defined(__riscv) && (__riscv_xlen == 64)
struct LIMINE_MP(info) {
uint64_t processor_id;
uint64_t hartid;
uint64_t reserved;
LIMINE_PTR(limine_goto_address)
goto_address;
uint64_t extra_argument;
};
struct LIMINE_MP(response) {
uint64_t revision;
uint64_t flags;
uint64_t bsp_hartid;
uint64_t cpu_count;
LIMINE_PTR(struct LIMINE_MP(info) **)
cpus;
};
# elif defined(__loongarch__) && (__loongarch_grlen == 64)
struct LIMINE_MP(info) {
uint64_t reserved;
};
struct LIMINE_MP(response) {
uint64_t cpu_count;
LIMINE_PTR(struct LIMINE_MP(info) **)
cpus;
};
# else
# error Unknown architecture
# endif
struct LIMINE_MP(request) {
uint64_t id[4];
uint64_t revision;
LIMINE_PTR(struct LIMINE_MP(response) *)
response;
uint64_t flags;
};
/* Memory map */
# define LIMINE_MEMMAP_REQUEST {LIMINE_COMMON_MAGIC, 0x67cf3d9d378a806f, 0xe304acdfc50c3c62}
# define LIMINE_MEMMAP_USABLE 0
# define LIMINE_MEMMAP_RESERVED 1
# define LIMINE_MEMMAP_ACPI_RECLAIMABLE 2
# define LIMINE_MEMMAP_ACPI_NVS 3
# define LIMINE_MEMMAP_BAD_MEMORY 4
# define LIMINE_MEMMAP_BOOTLOADER_RECLAIMABLE 5
# if LIMINE_API_REVISION >= 2
# define LIMINE_MEMMAP_EXECUTABLE_AND_MODULES 6
# else
# define LIMINE_MEMMAP_KERNEL_AND_MODULES 6
# endif
# define LIMINE_MEMMAP_FRAMEBUFFER 7
struct limine_memmap_entry {
uint64_t base;
uint64_t length;
uint64_t type;
};
struct limine_memmap_response {
uint64_t revision;
uint64_t entry_count;
LIMINE_PTR(struct limine_memmap_entry**)
entries;
};
struct limine_memmap_request {
uint64_t id[4];
uint64_t revision;
LIMINE_PTR(struct limine_memmap_response*)
response;
};
/* Entry point */
# define LIMINE_ENTRY_POINT_REQUEST {LIMINE_COMMON_MAGIC, 0x13d86c035a1cd3e1, 0x2b0caa89d8f3026a}
typedef void (*limine_entry_point)(void);
struct limine_entry_point_response {
uint64_t revision;
};
struct limine_entry_point_request {
uint64_t id[4];
uint64_t revision;
LIMINE_PTR(struct limine_entry_point_response*)
response;
LIMINE_PTR(limine_entry_point)
entry;
};
/* Executable File */
# if LIMINE_API_REVISION >= 2
# define LIMINE_EXECUTABLE_FILE_REQUEST {LIMINE_COMMON_MAGIC, 0xad97e90e83f1ed67, 0x31eb5d1c5ff23b69}
# else
# define LIMINE_KERNEL_FILE_REQUEST {LIMINE_COMMON_MAGIC, 0xad97e90e83f1ed67, 0x31eb5d1c5ff23b69}
# endif
# if LIMINE_API_REVISION >= 2
struct limine_executable_file_response {
# else
struct limine_kernel_file_response {
# endif
uint64_t revision;
# if LIMINE_API_REVISION >= 2
LIMINE_PTR(struct limine_file*)
executable_file;
# else
LIMINE_PTR(struct limine_file*)
kernel_file;
# endif
};
# if LIMINE_API_REVISION >= 2
struct limine_executable_file_request {
# else
struct limine_kernel_file_request {
# endif
uint64_t id[4];
uint64_t revision;
# if LIMINE_API_REVISION >= 2
LIMINE_PTR(struct limine_executable_file_response*)
response;
# else
LIMINE_PTR(struct limine_kernel_file_response*)
response;
# endif
};
/* Module */
# define LIMINE_MODULE_REQUEST {LIMINE_COMMON_MAGIC, 0x3e7e279702be32af, 0xca1c4f3bd1280cee}
# define LIMINE_INTERNAL_MODULE_REQUIRED (1 << 0)
# define LIMINE_INTERNAL_MODULE_COMPRESSED (1 << 1)
struct limine_internal_module {
LIMINE_PTR(char const*)
path;
# if LIMINE_API_REVISION >= 3
LIMINE_PTR(const char*)
string;
# else
LIMINE_PTR(const char*)
cmdline;
# endif
uint64_t flags;
};
struct limine_module_response {
uint64_t revision;
uint64_t module_count;
LIMINE_PTR(struct limine_file**)
modules;
};
struct limine_module_request {
uint64_t id[4];
uint64_t revision;
LIMINE_PTR(struct limine_module_response*)
response;
/* Request revision 1 */
uint64_t internal_module_count;
LIMINE_PTR(struct limine_internal_module**)
internal_modules;
};
/* RSDP */
# define LIMINE_RSDP_REQUEST {LIMINE_COMMON_MAGIC, 0xc5e77b6b397e7b43, 0x27637845accdcf3c}
struct limine_rsdp_response {
uint64_t revision;
# if LIMINE_API_REVISION >= 1
uint64_t address;
# else
LIMINE_PTR(void*)
address;
# endif
};
struct limine_rsdp_request {
uint64_t id[4];
uint64_t revision;
LIMINE_PTR(struct limine_rsdp_response*)
response;
};
/* SMBIOS */
# define LIMINE_SMBIOS_REQUEST {LIMINE_COMMON_MAGIC, 0x9e9046f11e095391, 0xaa4a520fefbde5ee}
struct limine_smbios_response {
uint64_t revision;
# if LIMINE_API_REVISION >= 1
uint64_t entry_32;
uint64_t entry_64;
# else
LIMINE_PTR(void*)
entry_32;
LIMINE_PTR(void*)
entry_64;
# endif
};
struct limine_smbios_request {
uint64_t id[4];
uint64_t revision;
LIMINE_PTR(struct limine_smbios_response*)
response;
};
/* EFI system table */
# define LIMINE_EFI_SYSTEM_TABLE_REQUEST {LIMINE_COMMON_MAGIC, 0x5ceba5163eaaf6d6, 0x0a6981610cf65fcc}
struct limine_efi_system_table_response {
uint64_t revision;
# if LIMINE_API_REVISION >= 1
uint64_t address;
# else
LIMINE_PTR(void*)
address;
# endif
};
struct limine_efi_system_table_request {
uint64_t id[4];
uint64_t revision;
LIMINE_PTR(struct limine_efi_system_table_response*)
response;
};
/* EFI memory map */
# define LIMINE_EFI_MEMMAP_REQUEST {LIMINE_COMMON_MAGIC, 0x7df62a431d6872d5, 0xa4fcdfb3e57306c8}
struct limine_efi_memmap_response {
uint64_t revision;
LIMINE_PTR(void*)
memmap;
uint64_t memmap_size;
uint64_t desc_size;
uint64_t desc_version;
};
struct limine_efi_memmap_request {
uint64_t id[4];
uint64_t revision;
LIMINE_PTR(struct limine_efi_memmap_response*)
response;
};
/* Date at boot */
# if LIMINE_API_REVISION >= 3
# define LIMINE_DATE_AT_BOOT_REQUEST {LIMINE_COMMON_MAGIC, 0x502746e184c088aa, 0xfbc5ec83e6327893}
# else
# define LIMINE_BOOT_TIME_REQUEST {LIMINE_COMMON_MAGIC, 0x502746e184c088aa, 0xfbc5ec83e6327893}
# endif
# if LIMINE_API_REVISION >= 3
struct limine_date_at_boot_response {
# else
struct limine_boot_time_response {
# endif
uint64_t revision;
# if LIMINE_API_REVISION >= 3
int64_t timestamp;
# else
int64_t boot_time;
# endif
};
# if LIMINE_API_REVISION >= 3
struct limine_date_at_boot_request {
# else
struct limine_boot_time_request {
# endif
uint64_t id[4];
uint64_t revision;
# if LIMINE_API_REVISION >= 3
LIMINE_PTR(struct limine_date_at_boot_response*)
response;
# else
LIMINE_PTR(struct limine_boot_time_response*)
response;
# endif
};
/* Executable address */
# if LIMINE_API_REVISION >= 2
# define LIMINE_EXECUTABLE_ADDRESS_REQUEST {LIMINE_COMMON_MAGIC, 0x71ba76863cc55f63, 0xb2644a48c516a487}
# else
# define LIMINE_KERNEL_ADDRESS_REQUEST {LIMINE_COMMON_MAGIC, 0x71ba76863cc55f63, 0xb2644a48c516a487}
# endif
# if LIMINE_API_REVISION >= 2
struct limine_executable_address_response {
# else
struct limine_kernel_address_response {
# endif
uint64_t revision;
uint64_t physical_base;
uint64_t virtual_base;
};
# if LIMINE_API_REVISION >= 2
struct limine_executable_address_request {
# else
struct limine_kernel_address_request {
# endif
uint64_t id[4];
uint64_t revision;
# if LIMINE_API_REVISION >= 2
LIMINE_PTR(struct limine_executable_address_response*)
response;
# else
LIMINE_PTR(struct limine_kernel_address_response*)
response;
# endif
};
/* Device Tree Blob */
# define LIMINE_DTB_REQUEST {LIMINE_COMMON_MAGIC, 0xb40ddb48fb54bac7, 0x545081493f81ffb7}
struct limine_dtb_response {
uint64_t revision;
LIMINE_PTR(void*)
dtb_ptr;
};
struct limine_dtb_request {
uint64_t id[4];
uint64_t revision;
LIMINE_PTR(struct limine_dtb_response*)
response;
};
/* RISC-V Boot Hart ID */
# define LIMINE_RISCV_BSP_HARTID_REQUEST {LIMINE_COMMON_MAGIC, 0x1369359f025525f9, 0x2ff2a56178391bb6}
struct limine_riscv_bsp_hartid_response {
uint64_t revision;
uint64_t bsp_hartid;
};
struct limine_riscv_bsp_hartid_request {
uint64_t id[4];
uint64_t revision;
LIMINE_PTR(struct limine_riscv_bsp_hartid_response*)
response;
};
/* Bootloader Performance */
# define LIMINE_BOOTLOADER_PERFORMANCE_REQUEST {LIMINE_COMMON_MAGIC, 0x6b50ad9bf36d13ad, 0xdc4c7e88fc759e17}
struct limine_bootloader_performance_response {
uint64_t revision;
uint64_t reset_usec;
uint64_t init_usec;
uint64_t exec_usec;
};
struct limine_bootloader_performance_request {
uint64_t id[4];
uint64_t revision;
LIMINE_PTR(struct limine_bootloader_performance_response*)
response;
};
# ifdef __cplusplus
}
# endif
#endif

View file

@ -1,5 +1,6 @@
#pragma once
#include <hal>
#include <helpers/loc.h>
typedef enum {
@ -19,6 +20,10 @@ typedef enum {
#define error$(...) _log(LOG_ERROR, loc$(), __VA_ARGS__)
#define print$(...) _log(LOG_NONE, (Loc){0}, __VA_ARGS__)
#define panic$(...) \
_log(LOG_ERROR, loc$(), __VA_ARGS__); \
hal_brkpoint();
static char const* level_names[LOG_EVENT_LENGTH] = {
[LOG_NONE] = "",
[LOG_DEBUG] = "DEBUG",

View file

@ -5,6 +5,7 @@
#include "mod.h"
TaskError task_new(char const* name, HalPage* page_table, uintptr_t ip, Allocator* alloc) {
(void)ip;
Task* task = alloc->alloc(alloc, sizeof(Task));
if (task == NULL) {

View file

@ -1,9 +1,9 @@
{
"$schema": "https://schemas.cute.engineering/stable/cutekit.manifest.component.v1",
"id": "kmalloc",
"type": "lib",
"id": "handover-limine",
"requires": [
"allocators",
"traits"
"limine",
"handover"
]
}

View file

@ -0,0 +1,8 @@
#include "mod.h"
#include <limine>
static HandoverPayload* payload = NULL;
HandoverPayload* handover(void) {
return payload;
}

View file

@ -0,0 +1,7 @@
#pragma once
#include <handover>
void handover_init(void);
HandoverPayload* handover(void);