feat/kernel: Added IDT
This commit is contained in:
parent
248879c099
commit
af7599a266
15 changed files with 412 additions and 19 deletions
9
.vscode/settings.json
vendored
9
.vscode/settings.json
vendored
|
@ -1,10 +1,7 @@
|
||||||
{
|
{
|
||||||
"files.associations": {
|
"files.associations": {
|
||||||
"stdnoreturn.h": "c",
|
"cstdio": "c",
|
||||||
"serial.h": "c",
|
"stdarg.h": "c",
|
||||||
"io.h": "c",
|
"idt.h": "c"
|
||||||
"kprintf.h": "c",
|
|
||||||
"log.h": "c",
|
|
||||||
"cpu.h": "c"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -2,7 +2,7 @@
|
||||||
MAKEFLAGS += -rR
|
MAKEFLAGS += -rR
|
||||||
.SUFFIXES:
|
.SUFFIXES:
|
||||||
|
|
||||||
QEMUFLAGS := -m 2G -serial stdio
|
QEMUFLAGS := -m 2G -serial stdio -display none
|
||||||
IMAGE_NAME := release/emk
|
IMAGE_NAME := release/emk
|
||||||
|
|
||||||
HOST_CC := cc
|
HOST_CC := cc
|
||||||
|
|
|
@ -12,15 +12,30 @@ CC := gcc
|
||||||
AS := gcc
|
AS := gcc
|
||||||
NASM := nasm
|
NASM := nasm
|
||||||
|
|
||||||
CFLAGS := -g -O2 -pipe -Wall -Wextra -Werror -std=gnu11 -ffreestanding \
|
# Build mode configuration
|
||||||
|
BUILD_MODE ?= dev
|
||||||
|
ifeq ($(BUILD_MODE),release)
|
||||||
|
CFLAGS := -Os -pipe -Wall -Wextra -Werror -std=gnu11 -ffreestanding \
|
||||||
|
-fno-stack-protector -fno-stack-check -fno-PIC \
|
||||||
|
-ffunction-sections -fdata-sections -m64 -march=x86-64 \
|
||||||
|
-mno-80387 -mno-mmx -mno-sse -mno-sse2 -mno-red-zone \
|
||||||
|
-mcmodel=kernel -fno-unwind-tables -fno-asynchronous-unwind-tables \
|
||||||
|
-s -Wno-unused-variable
|
||||||
|
NASMFLAGS :=
|
||||||
|
LDFLAGS := -nostdlib -static -z max-page-size=0x1000 -Wl,--gc-sections \
|
||||||
|
-T linker.ld -Wl,-m,elf_x86_64 -Wl,--strip-all
|
||||||
|
else
|
||||||
|
CFLAGS := -g -O2 -pipe -Wall -Wextra -Werror -std=gnu11 -ffreestanding \
|
||||||
-fno-stack-protector -fno-stack-check -fno-PIC \
|
-fno-stack-protector -fno-stack-check -fno-PIC \
|
||||||
-ffunction-sections -fdata-sections -m64 -march=x86-64 \
|
-ffunction-sections -fdata-sections -m64 -march=x86-64 \
|
||||||
-mno-80387 -mno-mmx -mno-sse -mno-sse2 -mno-red-zone \
|
-mno-80387 -mno-mmx -mno-sse -mno-sse2 -mno-red-zone \
|
||||||
-mcmodel=kernel -Wno-unused-variable
|
-mcmodel=kernel -Wno-unused-variable
|
||||||
CPPFLAGS := -I../external -I$(SRCDIR) -MMD -MP -DLIMINE_API_REVISION=3
|
NASMFLAGS := -F dwarf -g
|
||||||
NASMFLAGS := -F dwarf -g
|
LDFLAGS := -nostdlib -static -z max-page-size=0x1000 -Wl,--gc-sections \
|
||||||
LDFLAGS := -nostdlib -static -z max-page-size=0x1000 -Wl,--gc-sections \
|
|
||||||
-T linker.ld -Wl,-m,elf_x86_64
|
-T linker.ld -Wl,-m,elf_x86_64
|
||||||
|
endif
|
||||||
|
|
||||||
|
CPPFLAGS := -I../external -I$(SRCDIR) -MMD -MP -DLIMINE_API_REVISION=3
|
||||||
|
|
||||||
SRCS := $(shell find $(SRCDIR) -type f \( -name '*.c' -o -name '*.S' -o -name '*.asm' \))
|
SRCS := $(shell find $(SRCDIR) -type f \( -name '*.c' -o -name '*.S' -o -name '*.asm' \))
|
||||||
OBJS := $(patsubst %.c,$(OBJDIR)/%.o,$(filter %.c,$(SRCS))) \
|
OBJS := $(patsubst %.c,$(OBJDIR)/%.o,$(filter %.c,$(SRCS))) \
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* EMK 1.0 Copyright (c) 2025 Piraterna */
|
||||||
#include <arch/gdt.h>
|
#include <arch/gdt.h>
|
||||||
|
|
||||||
gdt_entry_t gdt[5];
|
gdt_entry_t gdt[5];
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* EMK 1.0 Copyright (c) 2025 Piraterna */
|
||||||
#ifndef GDT_H
|
#ifndef GDT_H
|
||||||
#define GDT_H
|
#define GDT_H
|
||||||
|
|
||||||
|
|
94
kernel/src/arch/idt-stub.S
Normal file
94
kernel/src/arch/idt-stub.S
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
.globl real_handlers
|
||||||
|
.extern real_handlers
|
||||||
|
|
||||||
|
isr_handler_stub:
|
||||||
|
pushq %rax
|
||||||
|
pushq %rbx
|
||||||
|
pushq %rcx
|
||||||
|
pushq %rdx
|
||||||
|
pushq %rbp
|
||||||
|
pushq %rdi
|
||||||
|
pushq %rsi
|
||||||
|
pushq %r8
|
||||||
|
pushq %r9
|
||||||
|
pushq %r10
|
||||||
|
pushq %r11
|
||||||
|
pushq %r12
|
||||||
|
pushq %r13
|
||||||
|
pushq %r14
|
||||||
|
pushq %r15
|
||||||
|
|
||||||
|
movq %cr0, %rax
|
||||||
|
pushq %rax
|
||||||
|
movq %cr2, %rax
|
||||||
|
pushq %rax
|
||||||
|
movq %cr3, %rax
|
||||||
|
pushq %rax
|
||||||
|
movq %cr4, %rax
|
||||||
|
pushq %rax
|
||||||
|
|
||||||
|
movq %ds, %rax
|
||||||
|
pushq %rax
|
||||||
|
movq %es, %rax
|
||||||
|
pushq %rax
|
||||||
|
|
||||||
|
cld
|
||||||
|
|
||||||
|
movq %rsp, %rdi
|
||||||
|
movq 168(%rsp), %rbx
|
||||||
|
shlq $3, %rbx
|
||||||
|
leaq real_handlers(%rip), %rax
|
||||||
|
addq %rbx, %rax
|
||||||
|
callq *(%rax)
|
||||||
|
|
||||||
|
addq $48, %rsp
|
||||||
|
popq %r15
|
||||||
|
popq %r14
|
||||||
|
popq %r13
|
||||||
|
popq %r12
|
||||||
|
popq %r11
|
||||||
|
popq %r10
|
||||||
|
popq %r9
|
||||||
|
popq %r8
|
||||||
|
popq %rsi
|
||||||
|
popq %rdi
|
||||||
|
popq %rbp
|
||||||
|
popq %rdx
|
||||||
|
popq %rcx
|
||||||
|
popq %rbx
|
||||||
|
popq %rax
|
||||||
|
addq $16, %rsp
|
||||||
|
|
||||||
|
iretq
|
||||||
|
|
||||||
|
.macro ISR index
|
||||||
|
.global _isr\index
|
||||||
|
.type _isr\index, @function
|
||||||
|
_isr\index:
|
||||||
|
.if 0x\index != 8 && 0x\index != 10 && 0x\index != 11 && 0x\index != 12 && 0x\index != 13 && 0x\index != 14 && 0x\index != 17 && 0x\index != 30
|
||||||
|
pushq $0
|
||||||
|
.endif
|
||||||
|
pushq $0x\index
|
||||||
|
jmp isr_handler_stub
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro ISRADDR index
|
||||||
|
.quad _isr\index
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.irpc i, 0123456789abcdef
|
||||||
|
.irpc j, 0123456789abcdef
|
||||||
|
ISR \i\j
|
||||||
|
.endr
|
||||||
|
.endr
|
||||||
|
|
||||||
|
.section .data
|
||||||
|
|
||||||
|
.global stubs
|
||||||
|
.align 8
|
||||||
|
stubs:
|
||||||
|
.irpc i, 0123456789abcdef
|
||||||
|
.irpc j, 0123456789abcdef
|
||||||
|
ISRADDR \i\j
|
||||||
|
.endr
|
||||||
|
.endr
|
63
kernel/src/arch/idt.c
Normal file
63
kernel/src/arch/idt.c
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
#include <arch/idt.h>
|
||||||
|
#include <lib/string.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <arch/cpu.h>
|
||||||
|
#include <util/log.h>
|
||||||
|
#include <sys/kpanic.h>
|
||||||
|
|
||||||
|
struct idt_entry __attribute__((aligned(16))) idt_descriptor[256] = {0};
|
||||||
|
idt_intr_handler real_handlers[256] = {0};
|
||||||
|
extern uint64_t stubs[];
|
||||||
|
|
||||||
|
struct __attribute__((packed)) idt_ptr
|
||||||
|
{
|
||||||
|
uint16_t limit;
|
||||||
|
uint64_t base;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct idt_ptr idt_ptr = {sizeof(idt_descriptor) - 1, (uint64_t)&idt_descriptor};
|
||||||
|
|
||||||
|
void idt_default_interrupt_handler(struct register_ctx *ctx)
|
||||||
|
{
|
||||||
|
kpanic(ctx, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SET_GATE(interrupt, base, flags) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
idt_descriptor[(interrupt)].off_low = (base) & 0xFFFF; \
|
||||||
|
idt_descriptor[(interrupt)].sel = 0x8; \
|
||||||
|
idt_descriptor[(interrupt)].ist = 0; \
|
||||||
|
idt_descriptor[(interrupt)].attr = (flags); \
|
||||||
|
idt_descriptor[(interrupt)].off_mid = ((base) >> 16) & 0xFFFF; \
|
||||||
|
idt_descriptor[(interrupt)].off_high = ((base) >> 32) & 0xFFFFFFFF; \
|
||||||
|
idt_descriptor[(interrupt)].zero = 0; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
void idt_init()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 32; i++)
|
||||||
|
{
|
||||||
|
SET_GATE(i, stubs[i], IDT_TRAP_GATE);
|
||||||
|
real_handlers[i] = idt_default_interrupt_handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 32; i < 256; i++)
|
||||||
|
{
|
||||||
|
SET_GATE(i, stubs[i], IDT_INTERRUPT_GATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
__asm__ volatile(
|
||||||
|
"lidt %0"
|
||||||
|
: : "m"(idt_ptr) : "memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
int idt_register_handler(size_t vector, idt_intr_handler handler)
|
||||||
|
{
|
||||||
|
if (real_handlers[vector] != idt_default_interrupt_handler)
|
||||||
|
{
|
||||||
|
real_handlers[vector] = handler;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
37
kernel/src/arch/idt.h
Normal file
37
kernel/src/arch/idt.h
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
/* EMK 1.0 Copyright (c) 2025 Piraterna */
|
||||||
|
#ifndef IDT_H
|
||||||
|
#define IDT_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
struct __attribute__((packed)) register_ctx
|
||||||
|
{
|
||||||
|
uint64_t es, ds;
|
||||||
|
uint64_t cr4, cr3, cr2, cr0;
|
||||||
|
uint64_t r15, r14, r13, r12, r11, r10, r9, r8, rsi, rdi, rbp, rdx, rcx, rbx, rax;
|
||||||
|
uint64_t vector, err;
|
||||||
|
uint64_t rip, cs, rflags, rsp, ss;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct __attribute__((packed)) idt_entry
|
||||||
|
{
|
||||||
|
uint16_t off_low;
|
||||||
|
uint16_t sel;
|
||||||
|
uint8_t ist;
|
||||||
|
uint8_t attr;
|
||||||
|
uint16_t off_mid;
|
||||||
|
uint32_t off_high;
|
||||||
|
uint32_t zero;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef void (*idt_intr_handler)(struct register_ctx *ctx);
|
||||||
|
#define IDT_INTERRUPT_GATE (0x8E)
|
||||||
|
#define IDT_TRAP_GATE (0x8F)
|
||||||
|
#define IDT_IRQ_BASE (0x20)
|
||||||
|
|
||||||
|
void idt_init();
|
||||||
|
int idt_register_handler(size_t vector, idt_intr_handler handler);
|
||||||
|
void idt_default_interrupt_handler(struct register_ctx *ctx);
|
||||||
|
|
||||||
|
#endif // IDT_H
|
|
@ -6,6 +6,7 @@
|
||||||
#include <util/kprintf.h>
|
#include <util/kprintf.h>
|
||||||
#include <util/log.h>
|
#include <util/log.h>
|
||||||
#include <arch/gdt.h>
|
#include <arch/gdt.h>
|
||||||
|
#include <arch/idt.h>
|
||||||
|
|
||||||
__attribute__((used, section(".limine_requests"))) static volatile LIMINE_BASE_REVISION(3);
|
__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_start"))) static volatile LIMINE_REQUESTS_START_MARKER;
|
||||||
|
@ -21,11 +22,15 @@ void emk_entry(void)
|
||||||
|
|
||||||
if (!LIMINE_BASE_REVISION_SUPPORTED)
|
if (!LIMINE_BASE_REVISION_SUPPORTED)
|
||||||
{
|
{
|
||||||
early("ERROR: Limine base revision is not supported\n");
|
log_early("ERROR: Limine base revision is not supported\n");
|
||||||
hcf();
|
hcf();
|
||||||
}
|
}
|
||||||
|
|
||||||
gdt_init();
|
gdt_init();
|
||||||
early("Initialized GDT");
|
log_early("Initialized GDT");
|
||||||
|
idt_init();
|
||||||
|
log_early("Initialized IDT");
|
||||||
|
__asm__ volatile("int $0x01");
|
||||||
|
|
||||||
hlt();
|
hlt();
|
||||||
}
|
}
|
140
kernel/src/sys/kpanic.c
Normal file
140
kernel/src/sys/kpanic.c
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
#include <sys/kpanic.h>
|
||||||
|
#include <util/log.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <util/kprintf.h>
|
||||||
|
#include <lib/string.h>
|
||||||
|
#include <arch/cpu.h>
|
||||||
|
|
||||||
|
static const char *strings[32] = {
|
||||||
|
"Division by Zero",
|
||||||
|
"Debug",
|
||||||
|
"Non-Maskable-Interrupt",
|
||||||
|
"Breakpoint",
|
||||||
|
"Overflow",
|
||||||
|
"Bound Range Exceeded",
|
||||||
|
"Invalid opcode",
|
||||||
|
"Device (FPU) not available",
|
||||||
|
"Double Fault",
|
||||||
|
"RESERVED VECTOR",
|
||||||
|
"Invalid TSS",
|
||||||
|
"Segment not present",
|
||||||
|
"Stack Segment Fault",
|
||||||
|
"General Protection Fault",
|
||||||
|
"Page Fault",
|
||||||
|
"RESERVED VECTOR",
|
||||||
|
"x87 FP Exception",
|
||||||
|
"Alignment Check",
|
||||||
|
"Machine Check (Internal Error)",
|
||||||
|
"SIMD FP Exception",
|
||||||
|
"Virtualization Exception",
|
||||||
|
"Control Protection Exception",
|
||||||
|
"RESERVED VECTOR",
|
||||||
|
"RESERVED VECTOR",
|
||||||
|
"RESERVED VECTOR",
|
||||||
|
"RESERVED VECTOR",
|
||||||
|
"RESERVED VECTOR",
|
||||||
|
"RESERVED VECTOR",
|
||||||
|
"Hypervisor Injection Exception",
|
||||||
|
"VMM Communication Exception",
|
||||||
|
"Security Exception",
|
||||||
|
"RESERVED VECTOR"};
|
||||||
|
|
||||||
|
static void capture_regs(struct register_ctx *context)
|
||||||
|
{
|
||||||
|
__asm__ volatile(
|
||||||
|
"movq %%rax, %0\n\t"
|
||||||
|
"movq %%rbx, %1\n\t"
|
||||||
|
"movq %%rcx, %2\n\t"
|
||||||
|
"movq %%rdx, %3\n\t"
|
||||||
|
"movq %%rsi, %4\n\t"
|
||||||
|
"movq %%rdi, %5\n\t"
|
||||||
|
"movq %%rbp, %6\n\t"
|
||||||
|
"movq %%r8, %7\n\t"
|
||||||
|
"movq %%r9, %8\n\t"
|
||||||
|
"movq %%r10, %9\n\t"
|
||||||
|
"movq %%r11, %10\n\t"
|
||||||
|
"movq %%r12, %11\n\t"
|
||||||
|
"movq %%r13, %12\n\t"
|
||||||
|
"movq %%r14, %13\n\t"
|
||||||
|
"movq %%r15, %14\n\t"
|
||||||
|
: "=m"(context->rax), "=m"(context->rbx), "=m"(context->rcx), "=m"(context->rdx),
|
||||||
|
"=m"(context->rsi), "=m"(context->rdi), "=m"(context->rbp), "=m"(context->r9),
|
||||||
|
"=m"(context->r9), "=m"(context->r10), "=m"(context->r11), "=m"(context->r12),
|
||||||
|
"=m"(context->r13), "=m"(context->r14), "=m"(context->r15)
|
||||||
|
:
|
||||||
|
: "memory");
|
||||||
|
|
||||||
|
__asm__ volatile(
|
||||||
|
"movq %%cs, %0\n\t"
|
||||||
|
"movq %%ss, %1\n\t"
|
||||||
|
"movq %%es, %2\n\t"
|
||||||
|
"movq %%ds, %3\n\t"
|
||||||
|
"movq %%cr0, %4\n\t"
|
||||||
|
"movq %%cr2, %5\n\t"
|
||||||
|
"movq %%cr3, %6\n\t"
|
||||||
|
"movq %%cr4, %7\n\t"
|
||||||
|
: "=r"(context->cs), "=r"(context->ss), "=r"(context->es), "=r"(context->ds),
|
||||||
|
"=r"(context->cr0), "=r"(context->cr2), "=r"(context->cr3), "=r"(context->cr4)
|
||||||
|
:
|
||||||
|
: "memory");
|
||||||
|
|
||||||
|
__asm__ volatile(
|
||||||
|
"movq %%rsp, %0\n\t"
|
||||||
|
"pushfq\n\t"
|
||||||
|
"popq %1\n\t"
|
||||||
|
: "=r"(context->rsp), "=r"(context->rflags)
|
||||||
|
:
|
||||||
|
: "memory");
|
||||||
|
|
||||||
|
context->rip = (uint64_t)__builtin_return_address(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void kpanic(struct register_ctx *ctx, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
struct register_ctx regs;
|
||||||
|
|
||||||
|
if (ctx == NULL)
|
||||||
|
{
|
||||||
|
capture_regs(®s);
|
||||||
|
regs.err = 0xDEADBEEF;
|
||||||
|
regs.vector = 0x0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memcpy(®s, ctx, sizeof(struct register_ctx));
|
||||||
|
}
|
||||||
|
|
||||||
|
char buf[1024];
|
||||||
|
|
||||||
|
if (fmt)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
vsnprintf(buf, sizeof(buf), fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (regs.vector >= sizeof(strings) / sizeof(strings[0]))
|
||||||
|
{
|
||||||
|
snprintf(buf, sizeof(buf), "Unknown panic vector: %d", regs.vector);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
snprintf(buf, sizeof(buf), "%s", strings[regs.vector]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log_panic("=== Kernel panic: '%s' @ 0x%.16llx ===", buf, regs.rip);
|
||||||
|
log_panic("Registers:");
|
||||||
|
log_panic(" rax: 0x%.16llx rbx: 0x%.16llx rcx: 0x%.16llx rdx: 0x%.16llx", regs.rax, regs.rbx, regs.rcx, regs.rdx);
|
||||||
|
log_panic(" rsi: 0x%.16llx rdi: 0x%.16llx rbp: 0x%.16llx rsp: 0x%.16llx", regs.rsi, regs.rdi, regs.rbp, regs.rsp);
|
||||||
|
log_panic(" r8 : 0x%.16llx r9 : 0x%.16llx r10: 0x%.16llx r11: 0x%.16llx", regs.r8, regs.r9, regs.r10, regs.r11);
|
||||||
|
log_panic(" r12: 0x%.16llx r13: 0x%.16llx r14: 0x%.16llx r15: 0x%.16llx", regs.r12, regs.r13, regs.r14, regs.r15);
|
||||||
|
log_panic(" rip: 0x%.16llx rflags: 0x%.16llx", regs.rip, regs.rflags);
|
||||||
|
log_panic(" cs : 0x%.16llx ss: 0x%.16llx ds: 0x%.16llx es: 0x%.16llx", regs.cs, regs.ss, regs.ds, regs.es);
|
||||||
|
log_panic(" cr0: 0x%.16llx cr2: 0x%.16llx cr3: 0x%.16llx cr4: 0x%.16llx", regs.cr0, regs.cr2, regs.cr3, regs.cr4);
|
||||||
|
log_panic(" err: 0x%.16llx vector: 0x%.16llx", regs.err, regs.vector);
|
||||||
|
|
||||||
|
hcf();
|
||||||
|
}
|
8
kernel/src/sys/kpanic.h
Normal file
8
kernel/src/sys/kpanic.h
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#ifndef KPANIC_H
|
||||||
|
#define KPANIC_H
|
||||||
|
|
||||||
|
#include <arch/idt.h>
|
||||||
|
|
||||||
|
void kpanic(struct register_ctx *ctx, const char *fmt, ...);
|
||||||
|
|
||||||
|
#endif // KPANIC_H
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* EMK 1.0 Copyright (c) 2025 Piraterna */
|
||||||
#include <dev/serial.h>
|
#include <dev/serial.h>
|
||||||
#include <util/kprintf.h>
|
#include <util/kprintf.h>
|
||||||
|
|
||||||
|
@ -26,3 +27,24 @@ int kprintf(const char *fmt, ...)
|
||||||
va_end(args);
|
va_end(args);
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int snprintf(char *buf, size_t size, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
int length = vsnprintf(buf, size, fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
|
||||||
|
{
|
||||||
|
int length = npf_vsnprintf(buf, size, fmt, args);
|
||||||
|
|
||||||
|
if (length >= (int)size)
|
||||||
|
{
|
||||||
|
buf[size - 1] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
return length;
|
||||||
|
}
|
|
@ -1,7 +1,15 @@
|
||||||
|
/* EMK 1.0 Copyright (c) 2025 Piraterna */
|
||||||
#ifndef KPRINTF_H
|
#ifndef KPRINTF_H
|
||||||
#define KPRINTF_H
|
#define KPRINTF_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
/* Minimal kprintf using nanoprintf, see external/nanoprintf.h */
|
/* Minimal kprintf using nanoprintf, see external/nanoprintf.h */
|
||||||
int kprintf(const char *fmt, ...);
|
int kprintf(const char *fmt, ...);
|
||||||
|
|
||||||
|
/* Careful with these */
|
||||||
|
int snprintf(char *buf, size_t size, const char *fmt, ...);
|
||||||
|
int vsnprintf(char *buf, size_t size, const char *fmt, va_list args);
|
||||||
|
|
||||||
#endif // KPRINTF_H
|
#endif // KPRINTF_H
|
|
@ -1,8 +1,10 @@
|
||||||
|
/* EMK 1.0 Copyright (c) 2025 Piraterna */
|
||||||
#ifndef LOG_H
|
#ifndef LOG_H
|
||||||
#define LOG_H
|
#define LOG_H
|
||||||
|
|
||||||
#include <util/kprintf.h>
|
#include <util/kprintf.h>
|
||||||
|
|
||||||
#define early(fmt, ...) kprintf("early: " fmt "\n", ##__VA_ARGS__)
|
#define log_early(fmt, ...) kprintf("early: " fmt "\n", ##__VA_ARGS__)
|
||||||
|
#define log_panic(fmt, ...) kprintf("panic: " fmt "\n", ##__VA_ARGS__)
|
||||||
|
|
||||||
#endif // LOG_H
|
#endif // LOG_H
|
|
@ -1,4 +1,4 @@
|
||||||
timeout: 3
|
timeout: 0
|
||||||
|
|
||||||
/EMK
|
/EMK
|
||||||
protocol: limine
|
protocol: limine
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue