5 Commits
memory ... main

Author SHA1 Message Date
9cbecc1689 GP Fault handler 2026-01-10 11:04:08 +01:00
12ab12f1b2 serial Kernel panic 2026-01-10 09:45:20 +01:00
0f72987bc1 use boot_ctx 2026-01-04 11:18:20 +01:00
d9dfd4c749 version splash 2026-01-04 11:00:30 +01:00
be1be41a64 Merge pull request 'memory' (#7) from memory into main
Reviewed-on: #7
2026-01-04 09:27:59 +01:00
8 changed files with 189 additions and 32 deletions

View File

@@ -4,6 +4,7 @@
#include "io/serial/serial.h" #include "io/serial/serial.h"
#include "io/kbd/ps2.h" #include "io/kbd/ps2.h"
#include <kernel.h> #include <kernel.h>
#include <stdbool.h>
struct interrupt_descriptor idt[256]; struct interrupt_descriptor idt[256];
struct idtr idt_reg; struct idtr idt_reg;
@@ -53,6 +54,64 @@ void idt_init()
DEBUG("IDT initialized"); DEBUG("IDT initialized");
} }
static inline uint64_t read_cr2(void)
{
uint64_t val;
asm volatile ("mov %%cr2, %0" : "=r"(val));
return val;
}
static void page_fault_handler(struct cpu_status_t* ctx)
{
// It could be used to remap pages etc. to fix the fault, but right now what I'm more
// interested in is getting more info out of those numbers cause i'm lost each time i have
// to read all this mess
uint64_t cr2 = read_cr2();
DEBUG("\x1b[38;5;231mPage Fault at rip=0x%p, err=%u (%s%s%s%s%s%s%s%s) when accessing addr=0x%p\x1b[0m", ctx->iret_rip, ctx->error_code,
CHECK_BIT(ctx->error_code, 0) ? "PAGE_PROTECTION_VIOLATION " : "PAGE_NOT_PRESENT ",
CHECK_BIT(ctx->error_code, 1) ? "ON_WRITE " : "ON_READ ",
CHECK_BIT(ctx->error_code, 2) ? "IN_USER_MODE" : "IN_KERNEL_MODE",
CHECK_BIT(ctx->error_code, 3) ? " WAS_RESERVED" : "",
CHECK_BIT(ctx->error_code, 4) ? " ON_INSTRUCTION_FETCH" : "",
CHECK_BIT(ctx->error_code, 5) ? " PK_VIOLATION" : "",
CHECK_BIT(ctx->error_code, 6) ? " ON_SHADOWSTACK_ACCESS" : "",
CHECK_BIT(ctx->error_code, 7) ? " SGX_VIOLATION" : "",
cr2);
/* if (CHECK_BIT(ctx->error_code, 0))
{
panic(ctx);
} */
panic(ctx);
}
static void gp_fault_handler(struct cpu_status_t* ctx)
{
DEBUG("\x1b[38;5;231mGeneral Protection Fault at rip=0x%p, err=%u (%s)\x1b[0m",
ctx->iret_rip,
ctx->error_code,
(ctx->error_code == 0) ? "NOT_SEGMENT_RELATED" : "SEGMENT_RELATED");
// Segment-related
if (ctx->error_code != 0)
{
bool is_external = CHECK_BIT(ctx->error_code, 0);
// is it IDT, GDT, LDT?
uint8_t table = ctx->error_code & 0x6; // 0b110 (isolate table)
uint16_t index = ctx->error_code & 0xFFF8; // 13*1 1111111111111 + 000 = 1111111111111000
char* table_names[4] = {"GDT", "IDT", "LDT", "IDT"};
DEBUG("\x1b[38;5;231m%s in %s index %u\x1b[0m",
is_external ? "EXTERNAL" : "INTERNAL",
table_names[table],
index);
}
panic(ctx);
}
struct cpu_status_t* interrupt_dispatch(struct cpu_status_t* context) struct cpu_status_t* interrupt_dispatch(struct cpu_status_t* context)
{ {
switch(context->vector_number) switch(context->vector_number)
@@ -97,10 +156,11 @@ struct cpu_status_t* interrupt_dispatch(struct cpu_status_t* context)
DEBUG("Stack-Segment Fault!"); DEBUG("Stack-Segment Fault!");
break; break;
case 13: case 13:
DEBUG("General Protection Fault!"); gp_fault_handler(context);
break; break;
case 14: case 14:
DEBUG("Page Fault!"); // Better debugging for page faults...
page_fault_handler(context);
break; break;
case 15: case 15:
DEBUG("Intel Reserved Interrupt! (Achievement unlocked: How Did We Get Here?)"); DEBUG("Intel Reserved Interrupt! (Achievement unlocked: How Did We Get Here?)");

View File

@@ -9,8 +9,9 @@ because this shitty implementation will be replaced one day by Flanterm
#include <stddef.h> #include <stddef.h>
#include <kernel.h> #include <kernel.h>
#include "term.h" #include "term.h"
#include "mem/misc/utils.h"
extern struct limine_framebuffer* framebuffer; extern struct boot_context boot_ctx;
// Importing the PSF object file // Importing the PSF object file
extern unsigned char _binary_zap_light16_psf_start[]; extern unsigned char _binary_zap_light16_psf_start[];
@@ -33,14 +34,19 @@ Cursor cursor = {0};
unsigned char* fb; unsigned char* fb;
struct limine_framebuffer* framebuffer;
uint8_t lines_length[MAX_LINES];
int term_init() int term_init()
{ {
// Get framebuffer address from Limine struct // Get framebuffer address from Limine struct
if (framebuffer) if (boot_ctx.fb)
{ {
fb = framebuffer->address; fb = boot_ctx.fb->address;
DEBUG("terminal initialized"); framebuffer = boot_ctx.fb;
DEBUG("terminal initialized, fb=0x%p (width=%u height=%u pitch=%u bpp=%u)", fb, framebuffer->width, framebuffer->height, framebuffer->pitch, framebuffer->bpp);
return 0; return 0;
} }
return -ENOMEM; return -ENOMEM;
@@ -84,10 +90,56 @@ static void erase_char(int px, int py)
} }
} }
static inline size_t term_max_lines(void)
{
return framebuffer->height / FONT_HEIGHT;
}
void term_scroll()
{
const size_t row_height = FONT_HEIGHT;
const size_t row_bytes = framebuffer->pitch;
const size_t screen_rows = framebuffer->height;
// Move framebuffer up by one text row
//memmove(fb, fb + row_height * row_bytes, (screen_rows - row_height) * row_bytes);
for (size_t i = 0; i < (screen_rows - row_height) * row_bytes; i++)
{
fb[i] = fb[i + row_height * row_bytes];
}
// Clear last text row
size_t clear_start = (screen_rows - row_height) * row_bytes;
memset(fb + clear_start, 0, row_height * row_bytes);
// Shift line lengths by 1 (for backspace handling)
size_t max_lines = term_max_lines();
for (size_t i = 1; i < max_lines; i++)
{
lines_length[i - 1] = lines_length[i];
}
lines_length[max_lines - 1] = 0;
if (cursor.y > 0)
{
cursor.y--;
}
}
void putchar(char c) void putchar(char c)
{ {
if ((c == '\n') && ((cursor.y+1)*FONT_HEIGHT >= framebuffer->height))
{
term_scroll();
return;
}
if (c == '\n') if (c == '\n')
{ {
lines_length[cursor.y] = cursor.x;
cursor.x = 0; cursor.x = 0;
cursor.y++; cursor.y++;
return; return;
@@ -107,7 +159,8 @@ void putchar(char c)
if (cursor.x == 0) if (cursor.x == 0)
{ {
cursor.y--; cursor.y--;
cursor.x = (framebuffer->width / FONT_WIDTH) -1; // here // cursor.x = (framebuffer->width / FONT_WIDTH) -1; // here
cursor.x = lines_length[cursor.y];
} }
else { else {
cursor.x--; cursor.x--;
@@ -125,6 +178,11 @@ void putchar(char c)
cursor.y++; cursor.y++;
} }
if ((cursor.y+1)*FONT_HEIGHT >= framebuffer->height)
{
term_scroll();
}
int px = cursor.x * FONT_WIDTH; int px = cursor.x * FONT_WIDTH;
int py = cursor.y * FONT_HEIGHT; int py = cursor.y * FONT_HEIGHT;
draw_char(c, px, py, WHITE, BLACK); draw_char(c, px, py, WHITE, BLACK);

View File

@@ -11,6 +11,8 @@ enum TermColors
WHITE = 0xffffff WHITE = 0xffffff
}; };
#define MAX_LINES 256
#define PSF1_FONT_MAGIC 0x0436 #define PSF1_FONT_MAGIC 0x0436
typedef struct typedef struct

View File

@@ -1,6 +1,10 @@
#ifndef KERNEL_H #ifndef KERNEL_H
#define KERNEL_H #define KERNEL_H
#define PEPPEROS_VERSION_MAJOR "0"
#define PEPPEROS_VERSION_MINOR "0"
#define PEPPEROS_VERSION_PATCH "1"
enum ErrorCodes enum ErrorCodes
{ {
ENOMEM, ENOMEM,
@@ -12,12 +16,24 @@ enum ErrorCodes
#include "io/serial/serial.h" #include "io/serial/serial.h"
#include "io/term/printf.h" #include "io/term/printf.h"
#include "idt/idt.h"
#define DEBUG(log, ...) fctprintf((void*)&skputc, 0, "debug: [%s]: " log "\r\n", __FILE__, ##__VA_ARGS__) #define DEBUG(log, ...) fctprintf((void*)&skputc, 0, "debug: [%s]: " log "\r\n", __FILE__, ##__VA_ARGS__)
#define CHECK_BIT(var,pos) ((var) & (1<<(pos)))
// printf("debug: [%s]: " log "\n", __FILE__, ##__VA_ARGS__); // printf("debug: [%s]: " log "\n", __FILE__, ##__VA_ARGS__);
void panic(struct cpu_status_t* ctx);
void hcf(); void hcf();
#define assert(check) do { if(!(check)) hcf(); } while(0) #define assert(check) do { if(!(check)) hcf(); } while(0)
struct boot_context
{
struct limine_framebuffer* fb;
struct limine_memmap_response* mmap;
struct limine_hhdm_response* hhdm;
struct limine_kernel_address_response* kaddr;
};
#endif #endif

View File

@@ -53,8 +53,6 @@ static volatile LIMINE_REQUESTS_START_MARKER;
__attribute__((used, section(".limine_requests_end"))) __attribute__((used, section(".limine_requests_end")))
static volatile LIMINE_REQUESTS_END_MARKER; static volatile LIMINE_REQUESTS_END_MARKER;
struct limine_framebuffer* framebuffer;
// Panic (should dump registers etc. in the future) // Panic (should dump registers etc. in the future)
void hcf() void hcf()
{ {
@@ -64,28 +62,36 @@ void hcf()
} }
} }
void panic(struct cpu_status_t* ctx)
{
DEBUG("\x1b[38;5;231m\x1b[48;5;196mKernel panic!!!\x1b[0m at rip=%p\nSomething went horribly wrong! vect=0x%.2x errcode=0x%x\nrax=%p rbx=%p rcx=%p rdx=%p\nrsi=%p rdi=%p r8=%p r9=%p\nr10=%p r11=%p r12=%p r13=%p\nr14=%p r15=%p\n\nflags=%p\nstack at rbp=%p\nHalting...",
ctx->iret_rip,
ctx->vector_number, ctx->error_code, ctx->rax, ctx->rbx, ctx->rcx, ctx->rdx, ctx->rsi, ctx->rdi,
ctx->r8, ctx->r9, ctx->r10, ctx->r11, ctx->r12, ctx->r13, ctx->r14, ctx->r15, ctx->iret_flags,
ctx->rbp);
hcf();
}
const char* splash = "pepperOS version "PEPPEROS_VERSION_MAJOR"."PEPPEROS_VERSION_MINOR"."PEPPEROS_VERSION_PATCH"\n";
struct boot_context boot_ctx;
// This is our entry point // This is our entry point
void kmain() void kmain()
{ {
if (!LIMINE_BASE_REVISION_SUPPORTED) hcf(); if (!LIMINE_BASE_REVISION_SUPPORTED) hcf();
if (framebuffer_request.response == NULL || framebuffer_request.response->framebuffer_count < 1) hcf();
// We should probably grab all the boot info in a boot context struct // Populate boot context
// that would be a bit cleaner than this mess boot_ctx.fb = framebuffer_request.response ? framebuffer_request.response->framebuffers[0] : NULL;
boot_ctx.mmap = memmap_request.response ? memmap_request.response : NULL;
// Get the first framebuffer from the response boot_ctx.hhdm = hhdm_request.response ? hhdm_request.response : NULL;
framebuffer = framebuffer_request.response->framebuffers[0]; boot_ctx.kaddr = kerneladdr_request.response ? kerneladdr_request.response : NULL;
serial_init(); serial_init();
if (memmap_request.response == NULL) hcf(); memmap_display(boot_ctx.mmap);
memmap_display(memmap_request.response); hhdm_display(boot_ctx.hhdm);
DEBUG("kernel: phys_base=0x%p virt_base=0x%p", boot_ctx.kaddr->physical_base, boot_ctx.kaddr->virtual_base);
if (hhdm_request.response == NULL) hcf();
hhdm_display(hhdm_request.response);
if (kerneladdr_request.response == NULL) hcf();
DEBUG("kernel: phys_base=0x%p virt_base=0x%p", kerneladdr_request.response->physical_base, kerneladdr_request.response->virtual_base);
CLEAR_INTERRUPTS; CLEAR_INTERRUPTS;
gdt_init(); gdt_init();
@@ -93,10 +99,10 @@ void kmain()
timer_init(); timer_init();
SET_INTERRUPTS; SET_INTERRUPTS;
pmm_init(memmap_request.response, hhdm_request.response); pmm_init(boot_ctx.mmap, boot_ctx.hhdm);
// Remap kernel , HHDM and framebuffer // Remap kernel , HHDM and framebuffer
paging_init(kerneladdr_request.response, framebuffer); paging_init(boot_ctx.kaddr, boot_ctx.fb);
kheap_init(); kheap_init();
@@ -110,10 +116,13 @@ void kmain()
keyboard_init(FR); keyboard_init(FR);
term_init(); term_init();
// Draw something kputs(splash);
printf("%s, %s!\n", "Hello", "world");
// Yoohoooooo! for (int i=0; i<50; i++)
//DEBUG("kernel initialized successfully! hanging... wow=%d", 42); {
printf("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non justo a magna bibendum auctor viverra rutrum diam. In hac habitasse platea dictumst. Vestibulum suscipit ipsum eget tortor maximus lobortis. Donec vel ipsum id lacus fringilla bibendum id eget risus. Fusce vestibulum diam sit amet nunc ultricies, nec rutrum nibh congue. Donec fringilla a dui sit amet ullamcorper. Donec pharetra quis tortor id congue. Aliquam erat volutpat. Duis suscipit nulla vel ligula iaculis, in gravida mauris pellentesque. Vestibulum nunc nisl, posuere eu eros et, dictum molestie dolor. Donec posuere laoreet hendrerit. Suspendisse potenti. Proin fringilla vehicula malesuada. Quisque a dui est. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Curabitur nec aliquam lacus, at lacinia enim. "); printf("testing, attention please %d\n", i);
timer_wait(1000);
}
hcf(); hcf();
} }

View File

@@ -49,7 +49,7 @@ void vmm_setup_pt_root()
DEBUG("VMM setup: vmm_pt_root=0x%p (phys=0x%p)", vmm_pt_root, phys); DEBUG("VMM setup: vmm_pt_root=0x%p (phys=0x%p)", vmm_pt_root, phys);
} }
void* vmm_alloc(size_t length, size_t flags) /* void* vmm_alloc(size_t length, size_t flags)
{ {
// We will try to allocate at least length bytes, which have to be rounded UP to // We will try to allocate at least length bytes, which have to be rounded UP to
// the next page so its coherent with the PMM // the next page so its coherent with the PMM
@@ -58,7 +58,7 @@ void* vmm_alloc(size_t length, size_t flags)
// Need to implement this (as linked list) // Need to implement this (as linked list)
// but for now kernel heap is sufficient // but for now kernel heap is sufficient
// The VMM will prob be more useful when we have userspace // The VMM will prob be more useful when we have userspace
} } */
void vmm_init() void vmm_init()
{ {

View File

@@ -65,6 +65,17 @@ void pit_init()
outb(0x40, (divisor >> 8) & 0xFF); outb(0x40, (divisor >> 8) & 0xFF);
} }
// Wait n ticks
// Given that there's a tick every 1ms, wait n milliseconds
void timer_wait(uint64_t wait_ticks)
{
uint64_t then = ticks + wait_ticks;
while (ticks < then)
{
asm("hlt");
};
}
void timer_init() void timer_init()
{ {
// Remapping the PIC, because at startup it conflicts with // Remapping the PIC, because at startup it conflicts with

View File

@@ -2,5 +2,6 @@
#define TIMER_H #define TIMER_H
void timer_init(); void timer_init();
void timer_wait(unsigned int wait_ticks);
#endif #endif