Compare commits
4 Commits
be1be41a64
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
9cbecc1689
|
|||
|
12ab12f1b2
|
|||
|
0f72987bc1
|
|||
|
d9dfd4c749
|
@@ -4,6 +4,7 @@
|
||||
#include "io/serial/serial.h"
|
||||
#include "io/kbd/ps2.h"
|
||||
#include <kernel.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
struct interrupt_descriptor idt[256];
|
||||
struct idtr idt_reg;
|
||||
@@ -53,6 +54,64 @@ void idt_init()
|
||||
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)
|
||||
{
|
||||
switch(context->vector_number)
|
||||
@@ -97,10 +156,11 @@ struct cpu_status_t* interrupt_dispatch(struct cpu_status_t* context)
|
||||
DEBUG("Stack-Segment Fault!");
|
||||
break;
|
||||
case 13:
|
||||
DEBUG("General Protection Fault!");
|
||||
gp_fault_handler(context);
|
||||
break;
|
||||
case 14:
|
||||
DEBUG("Page Fault!");
|
||||
// Better debugging for page faults...
|
||||
page_fault_handler(context);
|
||||
break;
|
||||
case 15:
|
||||
DEBUG("Intel Reserved Interrupt! (Achievement unlocked: How Did We Get Here?)");
|
||||
|
||||
@@ -9,8 +9,9 @@ because this shitty implementation will be replaced one day by Flanterm
|
||||
#include <stddef.h>
|
||||
#include <kernel.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
|
||||
extern unsigned char _binary_zap_light16_psf_start[];
|
||||
@@ -33,14 +34,19 @@ Cursor cursor = {0};
|
||||
|
||||
unsigned char* fb;
|
||||
|
||||
struct limine_framebuffer* framebuffer;
|
||||
|
||||
uint8_t lines_length[MAX_LINES];
|
||||
|
||||
int term_init()
|
||||
{
|
||||
// Get framebuffer address from Limine struct
|
||||
|
||||
if (framebuffer)
|
||||
if (boot_ctx.fb)
|
||||
{
|
||||
fb = framebuffer->address;
|
||||
DEBUG("terminal initialized");
|
||||
fb = boot_ctx.fb->address;
|
||||
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 -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)
|
||||
{
|
||||
if ((c == '\n') && ((cursor.y+1)*FONT_HEIGHT >= framebuffer->height))
|
||||
{
|
||||
term_scroll();
|
||||
return;
|
||||
}
|
||||
|
||||
if (c == '\n')
|
||||
{
|
||||
lines_length[cursor.y] = cursor.x;
|
||||
cursor.x = 0;
|
||||
cursor.y++;
|
||||
return;
|
||||
@@ -107,7 +159,8 @@ void putchar(char c)
|
||||
if (cursor.x == 0)
|
||||
{
|
||||
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 {
|
||||
cursor.x--;
|
||||
@@ -125,6 +178,11 @@ void putchar(char c)
|
||||
cursor.y++;
|
||||
}
|
||||
|
||||
if ((cursor.y+1)*FONT_HEIGHT >= framebuffer->height)
|
||||
{
|
||||
term_scroll();
|
||||
}
|
||||
|
||||
int px = cursor.x * FONT_WIDTH;
|
||||
int py = cursor.y * FONT_HEIGHT;
|
||||
draw_char(c, px, py, WHITE, BLACK);
|
||||
|
||||
@@ -11,6 +11,8 @@ enum TermColors
|
||||
WHITE = 0xffffff
|
||||
};
|
||||
|
||||
#define MAX_LINES 256
|
||||
|
||||
#define PSF1_FONT_MAGIC 0x0436
|
||||
|
||||
typedef struct
|
||||
|
||||
16
src/kernel.h
16
src/kernel.h
@@ -1,6 +1,10 @@
|
||||
#ifndef KERNEL_H
|
||||
#define KERNEL_H
|
||||
|
||||
#define PEPPEROS_VERSION_MAJOR "0"
|
||||
#define PEPPEROS_VERSION_MINOR "0"
|
||||
#define PEPPEROS_VERSION_PATCH "1"
|
||||
|
||||
enum ErrorCodes
|
||||
{
|
||||
ENOMEM,
|
||||
@@ -12,12 +16,24 @@ enum ErrorCodes
|
||||
|
||||
#include "io/serial/serial.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 CHECK_BIT(var,pos) ((var) & (1<<(pos)))
|
||||
|
||||
// printf("debug: [%s]: " log "\n", __FILE__, ##__VA_ARGS__);
|
||||
|
||||
void panic(struct cpu_status_t* ctx);
|
||||
void hcf();
|
||||
#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
|
||||
|
||||
55
src/kmain.c
55
src/kmain.c
@@ -53,8 +53,6 @@ static volatile LIMINE_REQUESTS_START_MARKER;
|
||||
__attribute__((used, section(".limine_requests_end")))
|
||||
static volatile LIMINE_REQUESTS_END_MARKER;
|
||||
|
||||
struct limine_framebuffer* framebuffer;
|
||||
|
||||
// Panic (should dump registers etc. in the future)
|
||||
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
|
||||
void kmain()
|
||||
{
|
||||
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
|
||||
// that would be a bit cleaner than this mess
|
||||
|
||||
// Get the first framebuffer from the response
|
||||
framebuffer = framebuffer_request.response->framebuffers[0];
|
||||
// Populate boot context
|
||||
boot_ctx.fb = framebuffer_request.response ? framebuffer_request.response->framebuffers[0] : NULL;
|
||||
boot_ctx.mmap = memmap_request.response ? memmap_request.response : NULL;
|
||||
boot_ctx.hhdm = hhdm_request.response ? hhdm_request.response : NULL;
|
||||
boot_ctx.kaddr = kerneladdr_request.response ? kerneladdr_request.response : NULL;
|
||||
|
||||
serial_init();
|
||||
|
||||
if (memmap_request.response == NULL) hcf();
|
||||
memmap_display(memmap_request.response);
|
||||
|
||||
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);
|
||||
memmap_display(boot_ctx.mmap);
|
||||
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);
|
||||
|
||||
CLEAR_INTERRUPTS;
|
||||
gdt_init();
|
||||
@@ -93,10 +99,10 @@ void kmain()
|
||||
timer_init();
|
||||
SET_INTERRUPTS;
|
||||
|
||||
pmm_init(memmap_request.response, hhdm_request.response);
|
||||
pmm_init(boot_ctx.mmap, boot_ctx.hhdm);
|
||||
|
||||
// Remap kernel , HHDM and framebuffer
|
||||
paging_init(kerneladdr_request.response, framebuffer);
|
||||
paging_init(boot_ctx.kaddr, boot_ctx.fb);
|
||||
|
||||
kheap_init();
|
||||
|
||||
@@ -110,10 +116,13 @@ void kmain()
|
||||
keyboard_init(FR);
|
||||
|
||||
term_init();
|
||||
// Draw something
|
||||
printf("%s, %s!\n", "Hello", "world");
|
||||
// Yoohoooooo!
|
||||
//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. ");
|
||||
kputs(splash);
|
||||
|
||||
for (int i=0; i<50; i++)
|
||||
{
|
||||
printf("testing, attention please %d\n", i);
|
||||
timer_wait(1000);
|
||||
}
|
||||
|
||||
hcf();
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ void vmm_setup_pt_root()
|
||||
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
|
||||
// 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)
|
||||
// but for now kernel heap is sufficient
|
||||
// The VMM will prob be more useful when we have userspace
|
||||
}
|
||||
} */
|
||||
|
||||
void vmm_init()
|
||||
{
|
||||
|
||||
@@ -65,6 +65,17 @@ void pit_init()
|
||||
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()
|
||||
{
|
||||
// Remapping the PIC, because at startup it conflicts with
|
||||
|
||||
@@ -2,5 +2,6 @@
|
||||
#define TIMER_H
|
||||
|
||||
void timer_init();
|
||||
void timer_wait(unsigned int wait_ticks);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user