9 Commits

29 changed files with 271 additions and 351 deletions
+1
View File
@@ -10,3 +10,4 @@ iso_root
.gdb_history .gdb_history
symbols.map symbols.map
symbols.S symbols.S
*.log
+2 -4
View File
@@ -1,13 +1,11 @@
SOURCES = src/io/term/flanterm_backends/fb.c src/io/term/flanterm.c src/debug/panic.c src/debug/stacktrace.c src/boot/boot.c src/sched/scheduler.c src/sched/process.c src/mem/heap/kheap.c src/mem/paging/vmm.c src/mem/paging/paging.c src/mem/paging/pmm.c src/string/string.c src/io/kbd/ps2.c src/io/serial/serial.c src/io/term/printf.c src/io/term/term.c src/idt/idt.c src/mem/gdt/gdt.c src/mem/misc/utils.c src/time/timer.c src/kmain.c SOURCES = src/debug/misc.c src/io/term/flanterm_backends/fb.c src/io/term/flanterm.c src/debug/panic.c src/debug/stacktrace.c src/boot/boot.c src/sched/scheduler.c src/sched/process.c src/mem/heap/kheap.c src/mem/paging/vmm.c src/mem/paging/paging.c src/mem/paging/pmm.c src/string/string.c src/io/kbd/ps2.c src/io/serial/serial.c src/io/term/printf.c src/io/term/term.c src/idt/idt.c src/mem/gdt/gdt.c src/mem/misc/utils.c src/time/timer.c src/kmain.c
PROBLEMATIC_FLAGS=-Wno-unused-parameter -Wno-unused-variable PROBLEMATIC_FLAGS=-Wno-unused-parameter -Wno-unused-variable
build: build:
rm -f *.o rm -f *.o
x86_64-elf-gcc -g -c -Isrc $(SOURCES) $(PROBLEMATIC_FLAGS) -Wall -Wextra -std=gnu99 -nostdlib -ffreestanding -fno-stack-protector -fno-omit-frame-pointer -fno-stack-check -fno-PIC -ffunction-sections -fdata-sections -mcmodel=kernel x86_64-elf-gcc -g -c -Isrc $(SOURCES) $(PROBLEMATIC_FLAGS) -Wall -Wextra -std=gnu99 -nostdlib -ffreestanding -fno-stack-protector -fno-omit-frame-pointer -fno-stack-check -fno-PIC -ffunction-sections -fdata-sections -mcmodel=kernel
objcopy -O elf64-x86-64 -B i386 -I binary zap-light16.psf zap-light16.o
nasm -f elf64 src/idt/idt.S -o idt_stub.o nasm -f elf64 src/idt/idt.S -o idt_stub.o
nasm -f elf64 src/entry.S -o entry.o
x86_64-elf-ld -o pepperk -T linker.ld *.o x86_64-elf-ld -o pepperk -T linker.ld *.o
nm -n pepperk | awk '$$2 ~ /[TtDdBbRr]/ {print $$1, $$3}' > symbols.map nm -n pepperk | awk '$$2 ~ /[TtDdBbRr]/ {print $$1, $$3}' > symbols.map
python3 symbols.py python3 symbols.py
@@ -37,7 +35,7 @@ build-iso: limine/limine build
./limine/limine bios-install pepper.iso ./limine/limine bios-install pepper.iso
debug: debug:
/usr/bin/qemu-system-x86_64 -drive file=pepper.iso -s -S -d int -no-reboot -no-shutdown & /usr/bin/qemu-system-x86_64 -drive file=pepper.iso -s -S -d int -D qemu.log -no-reboot -no-shutdown &
gdb pepperk --command=debug.gdb gdb pepperk --command=debug.gdb
debug2: debug2:
+3 -1
View File
@@ -41,8 +41,10 @@ PepperOS wouldn't be possible without the following freely-licensed software:
- the [Limine](https://codeberg.org/Limine/Limine) portable bootloader - the [Limine](https://codeberg.org/Limine/Limine) portable bootloader
- Marco Paland's freestanding [printf implementation](https://github.com/mpaland) - Marco Paland's freestanding [printf implementation](https://github.com/mpaland)
- the [ZAP](https://www.zap.org.au/projects/console-fonts-zap/) PSF console fonts - Mintuski's [Flanterm](https://codeberg.org/Mintsuki/Flanterm) terminal emulator
...and without these amazing resources: ...and without these amazing resources:
- the [OSDev](https://osdev.org) wiki & forums - the [OSDev](https://osdev.org) wiki & forums
- Intel 64 and IA-32 Architectures Software Developer's Manual
- Documentation for the [GNU Compiler Collection](https://gcc.gnu.org/onlinedocs/gcc/)
+4
View File
@@ -1,3 +1,7 @@
target remote localhost:1234 target remote localhost:1234
set disassembly-flavor intel set disassembly-flavor intel
display/4i $rip display/4i $rip
# Trying to debug that flanterm page fault
# b plot_char_unscaled_uncanvas if $rdi == 0 || $rsi == 0 || $rdx == 0 || $r10 == 0
+1 -1
View File
@@ -1,6 +1,6 @@
OUTPUT_FORMAT(elf64-x86-64) OUTPUT_FORMAT(elf64-x86-64)
ENTRY(_start) ENTRY(kmain)
PHDRS PHDRS
{ {
+2 -2
View File
@@ -11,7 +11,7 @@
#define PEPPEROS_VERSION_MAJOR "0" #define PEPPEROS_VERSION_MAJOR "0"
#define PEPPEROS_VERSION_MINOR "0" #define PEPPEROS_VERSION_MINOR "0"
#define PEPPEROS_VERSION_PATCH "58" #define PEPPEROS_VERSION_PATCH "58"
#define PEPPEROS_SPLASH "pepperOS version "PEPPEROS_VERSION_MAJOR"."PEPPEROS_VERSION_MINOR"."PEPPEROS_VERSION_PATCH"\n" #define PEPPEROS_SPLASH "\x1b[38;5;196mPepperOS\x1b[0m version "PEPPEROS_VERSION_MAJOR"."PEPPEROS_VERSION_MINOR"."PEPPEROS_VERSION_PATCH"\n"
/* process */ /* process */
#define PROCESS_NAME_MAX 64 #define PROCESS_NAME_MAX 64
@@ -30,7 +30,7 @@
#define KERNEL_STACK_SIZE 65536 #define KERNEL_STACK_SIZE 65536
/* heap */ /* heap */
#define KHEAP_SIZE (16*1024*1024) #define KHEAP_SIZE (32*1024*1024)
/* term */ /* term */
#define TERM_HISTORY_MAX_LINES 256 #define TERM_HISTORY_MAX_LINES 256
+61
View File
@@ -0,0 +1,61 @@
#include <kernel.h>
#include "limine.h"
#include "string/string.h"
extern struct boot_context boot_ctx;
// Display the memmap so we see how the memory is laid out at handoff
void memmap_display(struct limine_memmap_response* response)
{
DEBUG("Got memory map from Limine: revision %u, %u entries", response->revision, response->entry_count);
for (size_t i=0; i<response->entry_count; i++)
{
struct limine_memmap_entry* entry = response->entries[i];
char type[32] = {0};
switch(entry->type)
{
case LIMINE_MEMMAP_USABLE:
strcpy(type, "USABLE");
break;
case LIMINE_MEMMAP_RESERVED:
strcpy(type, "RESERVED");
break;
case LIMINE_MEMMAP_ACPI_RECLAIMABLE:
strcpy(type, "ACPI_RECLAIMABLE");
break;
case LIMINE_MEMMAP_ACPI_NVS:
strcpy(type, "ACPI_NVS");
break;
case LIMINE_MEMMAP_BAD_MEMORY:
strcpy(type, "BAD_MEMORY");
break;
case LIMINE_MEMMAP_BOOTLOADER_RECLAIMABLE:
strcpy(type, "BOOTLOADER_RECLAIMABLE");
break;
case LIMINE_MEMMAP_KERNEL_AND_MODULES:
strcpy(type, "KERNEL_AND_MODULES");
break;
case LIMINE_MEMMAP_FRAMEBUFFER:
strcpy(type, "FRAMEBUFFER");
break;
default:
strcpy(type, "UNKNOWN");
break;
}
DEBUG("entry %02u: [0x%016x | %016u bytes] - %s", i, entry->base, entry->length, type);
}
}
// Display the HHDM
void hhdm_display(struct limine_hhdm_response* hhdm)
{
DEBUG("Got HHDM revision=%u offset=0x%p", hhdm->revision, hhdm->offset);
}
void boot_mem_display()
{
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);
}
+2
View File
@@ -9,7 +9,9 @@ void panic(struct cpu_status_t* ctx, const char* str)
if (ctx == NULL) if (ctx == NULL)
{ {
DEBUG("\x1b[38;5;231m\x1b[48;5;196mKernel panic!!!\x1b[0m Something went horribly wrong! (no cpu ctx)"); DEBUG("\x1b[38;5;231m\x1b[48;5;196mKernel panic!!!\x1b[0m Something went horribly wrong! (no cpu ctx)");
fctprintf((void*)&skputc, 0, "\x1b[38;5;231m\x1b[48;5;27m");
DIE_DEBUG(str); DIE_DEBUG(str);
fctprintf((void*)&skputc, 0, "\x1b[0m");
skputc('\r'); skputc('\r');
skputc('\n'); skputc('\n');
DEBUG("\x1b[38;5;231m\x1b[48;5;196mend Kernel panic - halting...\x1b[0m"); DEBUG("\x1b[38;5;231m\x1b[48;5;196mend Kernel panic - halting...\x1b[0m");
-23
View File
@@ -1,23 +0,0 @@
bits 64
global _start
extern kmain
extern kernel_stack
KERNEL_STACK_SIZE equ 65536
section .text
_start:
cli
; load kernel stack
lea rsp, [kernel_stack+KERNEL_STACK_SIZE]
; rbp=0 so last frame in stack trace
xor rbp, rbp
; 16 byte align
and rsp, -16
call kmain
+2 -1
View File
@@ -151,12 +151,13 @@ vector_7_handler:
align 16 align 16
vector_8_handler: vector_8_handler:
; No error code, we only push vector number ; No error code, we only push vector number
push qword 1 push qword 8
jmp interrupt_stub jmp interrupt_stub
; Coprocessor Segment Overrun ; Coprocessor Segment Overrun
align 16 align 16
vector_9_handler: vector_9_handler:
push qword 0
push qword 9 push qword 9
jmp interrupt_stub jmp interrupt_stub
+4 -7
View File
@@ -22,7 +22,7 @@ struct idtr idt_reg;
extern char vector_0_handler[]; extern char vector_0_handler[];
// Timer ticks // Timer ticks
extern uint64_t ticks; extern volatile uint64_t ticks;
void idt_set_entry(uint8_t vector, void* handler, uint8_t dpl) void idt_set_entry(uint8_t vector, void* handler, uint8_t dpl)
{ {
@@ -52,9 +52,8 @@ void idt_load(void* idt_addr)
void idt_init() void idt_init()
{ {
// We set 256 entries, but we have only the first few stubs. // Hardcoded...
// Undefined behavior? for (size_t i=0; i<=33; i++)
for (size_t i=0; i<256; i++)
{ {
// Each vector handler is 16-byte aligned, so <vector_no>*16 = address of that handler // Each vector handler is 16-byte aligned, so <vector_no>*16 = address of that handler
idt_set_entry(i, vector_0_handler + (i*16), 0); idt_set_entry(i, vector_0_handler + (i*16), 0);
@@ -203,9 +202,6 @@ struct cpu_status_t* interrupt_dispatch(struct cpu_status_t* context)
if (ticks % SCHEDULER_QUANTUM == 0) if (ticks % SCHEDULER_QUANTUM == 0)
{ {
return scheduler_schedule(context); return scheduler_schedule(context);
//struct cpu_status_t* current_ctx = scheduler_schedule(context);
//process_switch(current_ctx->iret_rsp, current_ctx->iret_rip);
//SET_INTERRUPTS;
} }
break; break;
@@ -213,6 +209,7 @@ struct cpu_status_t* interrupt_dispatch(struct cpu_status_t* context)
case 33: case 33:
DEBUG("Keyboard Interrupt"); DEBUG("Keyboard Interrupt");
keyboard_handler(); keyboard_handler();
outb(0x20, 0x20);
break; break;
default: default:
+24 -13
View File
@@ -17,6 +17,8 @@ uint8_t key_status = 0b00000000;
unsigned char* keymap; unsigned char* keymap;
unsigned char* keymap_shifted; unsigned char* keymap_shifted;
extern struct init_status init;
unsigned char kbdus[128] = unsigned char kbdus[128] =
{ {
0, 27, '1', '2', '3', '4', '5', '6', '7', '8', /* 9 */ 0, 27, '1', '2', '3', '4', '5', '6', '7', '8', /* 9 */
@@ -176,9 +178,6 @@ void keyboard_handler()
key_status &= ~ALT_PRESSED_BIT; key_status &= ~ALT_PRESSED_BIT;
break; break;
} }
// Send EOI
outb(0x20, 0x20);
return; return;
} }
else else
@@ -200,20 +199,25 @@ void keyboard_handler()
default: default:
{ {
// Should we get a SHIFTED char or a regular one? // Avoiding buffer overflow from extended keys lol
unsigned char c = (key_status & SHIFT_PRESSED_BIT) ? keymap_shifted[scancode] : keymap[scancode]; if (scancode < 128)
if (c)
{ {
// Should probably have a keyboard buffer here... instead of this // Should we get a SHIFTED char or a regular one?
_putchar(c); unsigned char c = (key_status & SHIFT_PRESSED_BIT) ? keymap_shifted[scancode] : keymap[scancode];
if (c)
{
if (c == '\n')
{
_putchar('\r');
}
// Should probably have a keyboard buffer here... instead of this
_putchar(c);
}
} }
} }
} }
} }
// End of Interrupt (to master PIC)
outb(0x20, 0x20);
} }
void keyboard_init(unsigned char layout) void keyboard_init(unsigned char layout)
@@ -233,14 +237,21 @@ void keyboard_init(unsigned char layout)
break; break;
default: default:
skputs("Unsupported layout."); panic(NULL, "Unsupported keyboard layout");
return; return;
} }
// Flush keyboard buffer
while (inb(0x64) & 1)
{
inb(0x60);
}
// Unmask IRQ1 // Unmask IRQ1
uint8_t mask = inb(0x21); uint8_t mask = inb(0x21);
mask &= ~(1 << 1); mask &= ~(1 << 1);
outb(0x21, mask); outb(0x21, mask);
DEBUG("PS/2 Keyboard initialized"); DEBUG("PS/2 Keyboard initialized");
init.keyboard = true;
} }
+5 -1
View File
@@ -7,6 +7,8 @@
#include <kernel.h> #include <kernel.h>
#include "serial.h" #include "serial.h"
extern struct init_status init;
void outb(int port, unsigned char data) void outb(int port, unsigned char data)
{ {
__asm__ __volatile__("outb %%al, %%dx" :: "a" (data),"d" (port)); __asm__ __volatile__("outb %%al, %%dx" :: "a" (data),"d" (port));
@@ -42,7 +44,8 @@ int serial_init()
// Set normal operation mode // Set normal operation mode
outb(PORT + 4, 0x0F); outb(PORT + 4, 0x0F);
DEBUG("serial initialized"); DEBUG("*** Welcome to PepperOS! ***");
init.serial = true;
return 0; return 0;
} }
@@ -54,6 +57,7 @@ static int is_transmit_empty()
// Serial kernel putchar // Serial kernel putchar
void skputc(char c) void skputc(char c)
{ {
// TODO: Spinlock here (serial access)
while (!is_transmit_empty()); // wait for free spot while (!is_transmit_empty()); // wait for free spot
outb(PORT, c); outb(PORT, c);
} }
+19
View File
@@ -25,6 +25,8 @@
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <kernel.h>
#ifdef __cplusplus #ifdef __cplusplus
#error "Please do not compile Flanterm as C++ code! Flanterm should be compiled as C99 or newer." #error "Please do not compile Flanterm as C++ code! Flanterm should be compiled as C99 or newer."
#endif #endif
@@ -662,6 +664,17 @@ static void plot_char_unscaled_canvas(struct flanterm_context *_ctx, struct flan
} }
static void plot_char_unscaled_uncanvas(struct flanterm_context *_ctx, struct flanterm_fb_char *c, size_t x, size_t y) { static void plot_char_unscaled_uncanvas(struct flanterm_context *_ctx, struct flanterm_fb_char *c, size_t x, size_t y) {
if (_ctx == NULL)
{
panic(NULL, "plot_char_unscaled_uncanvas: _ctx is NULL");
}
if (c == NULL)
{
panic(NULL, "plot_char_unscaled_uncanvas: c is NULL");
}
struct flanterm_fb_context *ctx = (void *)_ctx; struct flanterm_fb_context *ctx = (void *)_ctx;
if (x >= _ctx->cols || y >= _ctx->rows) { if (x >= _ctx->cols || y >= _ctx->rows) {
@@ -953,6 +966,12 @@ static void draw_cursor(struct flanterm_context *_ctx) {
} }
static void flanterm_fb_double_buffer_flush(struct flanterm_context *_ctx) { static void flanterm_fb_double_buffer_flush(struct flanterm_context *_ctx) {
if (_ctx == NULL)
{
panic(NULL, "flanterm_fb_double_buffer_flush: _ctx is NULL");
}
struct flanterm_fb_context *ctx = (void *)_ctx; struct flanterm_fb_context *ctx = (void *)_ctx;
if (_ctx->cursor_enabled) { if (_ctx->cursor_enabled) {
+37 -90
View File
@@ -11,107 +11,22 @@ because this shitty implementation will be replaced one day by Flanterm
(once memory management is okay: paging & kernel malloc) (once memory management is okay: paging & kernel malloc)
*/ */
#include <limine.h>
#include <stddef.h> #include <stddef.h>
#include <kernel.h> #include <kernel.h>
#include "term.h" #include "term.h"
#include "mem/misc/utils.h"
#include "config.h" #include "config.h"
#include "flanterm.h" #include "flanterm.h"
#include "flanterm_backends/fb.h"
extern struct boot_context boot_ctx; #include "mem/heap/kheap.h"
#include "limine.h"
// Importing the PSF object file
extern unsigned char _binary_zap_light16_psf_start[];
extern unsigned char _binary_zap_light16_psf_end[];
PSF1_Header* font = (PSF1_Header*)_binary_zap_light16_psf_start;
uint8_t* glyphs = _binary_zap_light16_psf_start + sizeof(PSF1_Header);
#define FONT_WIDTH 8
#define FONT_HEIGHT font->characterSize
extern struct flanterm_context* ft_ctx; extern struct flanterm_context* ft_ctx;
extern struct init_status init;
// Character cursor
typedef struct
{
size_t x;
size_t y;
} Cursor;
static Cursor cursor = {0, 0};
static uint8_t* fb;
static struct limine_framebuffer* framebuffer;
uint8_t lines_length[TERM_HISTORY_MAX_LINES];
static inline size_t term_max_cols(void)
{
return framebuffer->width / FONT_WIDTH;
}
static inline size_t term_max_lines(void)
{
return framebuffer->height / FONT_HEIGHT;
}
int term_init()
{
// Get framebuffer address from Limine struct
if (!boot_ctx.fb)
{
return -ENOMEM;
}
framebuffer = boot_ctx.fb;
fb = (uint8_t*)framebuffer->address;
memset(lines_length, 0, sizeof(lines_length));
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;
}
// These are marked "static" because we don't wanna expose them all around
// AKA they should just be seen here (kind of like private functions in cpp)
static inline void putpixel(size_t x, size_t y, uint32_t color)
{
// Guard so we don't write past fb boundaries
if (x >= framebuffer->width || y >= framebuffer->height) return;
// Depth isn't part of limine_framebuffer attributes so it will be 4
size_t pos = x*4 + y*framebuffer->pitch;
fb[pos] = color & 255; // blue channel
fb[pos+1] = (color >> 8) & 255; // green
fb[pos+2] = (color >> 16) & 255; // blue
}
void term_scroll()
{
// Erase first text line
memset(fb, 255, FONT_HEIGHT*framebuffer->pitch);
// Move whole framebuffer up by one text line
memmove(fb, fb+(FONT_HEIGHT*framebuffer->pitch), (framebuffer->height-FONT_HEIGHT)*framebuffer->pitch);
// Clear last text line
size_t clear_start = (framebuffer->height - FONT_HEIGHT) * framebuffer->pitch;
memset(fb + clear_start, 255, FONT_HEIGHT * framebuffer->pitch);
// 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;
}
// Overhead that could be avoided, right? (for printf) // Overhead that could be avoided, right? (for printf)
void _putchar(char character) void _putchar(char character)
{ {
// TODO: Spinlock here (terminal access)
flanterm_write(ft_ctx, &character, 1); flanterm_write(ft_ctx, &character, 1);
} }
@@ -124,4 +39,36 @@ void kputs(const char* str)
_putchar(str[i]); _putchar(str[i]);
i++; i++;
} }
_putchar('\r');
}
extern struct flanterm_context* ft_ctx;
extern struct boot_context boot_ctx;
void flanterm_free_wrapper(void* ptr, size_t size)
{
(void)size;
kfree(ptr);
}
void term_init()
{
uint32_t bgColor = 0x252525;
ft_ctx = flanterm_fb_init(
kmalloc,
flanterm_free_wrapper,
boot_ctx.fb->address, boot_ctx.fb->width, boot_ctx.fb->height, boot_ctx.fb->pitch,
boot_ctx.fb->red_mask_size, boot_ctx.fb->red_mask_shift,
boot_ctx.fb->green_mask_size, boot_ctx.fb->green_mask_shift,
boot_ctx.fb->blue_mask_size, boot_ctx.fb->blue_mask_shift,
NULL,
NULL, NULL,
&bgColor, NULL,
NULL, NULL,
NULL, 0, 0, 1,
0, 0,
0,
0
);
init.terminal = true;
} }
+1 -19
View File
@@ -7,26 +7,8 @@
#ifndef TERM_H #ifndef TERM_H
#define TERM_H #define TERM_H
int term_init();
void kputs(const char* str); void kputs(const char* str);
void _putchar(char character); void _putchar(char character);
void term_init();
enum TermColors
{
BLACK = 0x000000,
WHITE = 0xffffff
};
#define PSF1_FONT_MAGIC 0x0436
typedef struct
{
uint16_t magic;
uint8_t fontMode;
uint8_t characterSize; // height
} PSF1_Header;
// debug
void term_scroll();
#endif #endif
+14 -1
View File
@@ -19,9 +19,11 @@ 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" #include "idt/idt.h"
#include <stdbool.h>
#define DEBUG(log, ...) fctprintf((void*)&skputc, 0, "debug: [%s]: " log "\r\n", __FILE__, ##__VA_ARGS__) extern volatile uint64_t ticks;
#define DEBUG(log, ...) fctprintf((void*)&skputc, 0, "[%8u] debug: <%s>: " log "\r\n", ticks, __func__, ##__VA_ARGS__)
/* #define DEBUG(log, ...) \ /* #define DEBUG(log, ...) \
printf("debug: [%s]: " log "\r\n", __FILE__, ##__VA_ARGS__); \ printf("debug: [%s]: " log "\r\n", __FILE__, ##__VA_ARGS__); \
@@ -38,8 +40,10 @@ void panic(struct cpu_status_t* ctx, const char* str);
void hcf(); void hcf();
void idle(); void idle();
/* debug */
void debug_stack_trace(unsigned int max_frames); void debug_stack_trace(unsigned int max_frames);
const char* debug_find_symbol(uintptr_t rip, uintptr_t* offset); const char* debug_find_symbol(uintptr_t rip, uintptr_t* offset);
void boot_mem_display();
#define assert(check) do { if(!(check)) hcf(); } while(0) #define assert(check) do { if(!(check)) hcf(); } while(0)
@@ -51,4 +55,13 @@ struct boot_context
struct limine_kernel_address_response* kaddr; struct limine_kernel_address_response* kaddr;
}; };
// Are these modules initialized yet?
struct init_status
{
bool terminal;
bool serial;
bool keyboard;
bool timer;
};
#endif #endif
+29 -58
View File
@@ -30,8 +30,6 @@
__attribute__((used, section(".limine_requests"))) __attribute__((used, section(".limine_requests")))
volatile LIMINE_BASE_REVISION(3); volatile LIMINE_BASE_REVISION(3);
struct flanterm_context *ft_ctx;
// Halt and catch fire (makes machine stall) // Halt and catch fire (makes machine stall)
void hcf() void hcf()
{ {
@@ -41,9 +39,9 @@ void hcf()
// Doing nothing (can be interrupted) // Doing nothing (can be interrupted)
void idle() {SET_INTERRUPTS; for(;;)asm("hlt");} void idle() {SET_INTERRUPTS; for(;;)asm("hlt");}
uint8_t kernel_stack[KERNEL_STACK_SIZE] __attribute__((aligned(16))); struct flanterm_context *ft_ctx;
struct boot_context boot_ctx; struct boot_context boot_ctx;
struct init_status init = {0};
extern volatile struct limine_framebuffer_request framebuffer_request; extern volatile struct limine_framebuffer_request framebuffer_request;
extern volatile struct limine_memmap_request memmap_request; extern volatile struct limine_memmap_request memmap_request;
@@ -52,92 +50,65 @@ extern volatile struct limine_kernel_address_request kerneladdr_request;
extern struct process_t* processes_list; extern struct process_t* processes_list;
extern struct process_t* current_process; extern struct process_t* current_process;
struct process_t* idle_proc;
bool iran = false;
// Never gets executed although pedicel is scheduled?
void pedicel_main(void* arg) void pedicel_main(void* arg)
{ {
//printf("Hello, world from a KERNEL PROCESS!"); bool iran = true;
} // FROM THE NEXT LINE ONWARDS, CANNOT WRITE TO FRAMEBUFFER WITHOUT PAGE FAULT!
//printf("\n\nWelcome to PepperOS! Pedicel speaking.\nNothing left to do, halting the system!");
void two_main(void* arg)
{
//printf("...process 2 speaking!!!");
} }
void idle_main(void* arg) void idle_main(void* arg)
{ {
for(;;)asm("hlt"); for (;;)
{
asm("hlt");
}
} }
extern uintptr_t kheap_start;
// This is our entry point // This is our entry point
void kmain() void kmain()
{ {
CLEAR_INTERRUPTS;
if (!LIMINE_BASE_REVISION_SUPPORTED) hcf(); if (!LIMINE_BASE_REVISION_SUPPORTED) hcf();
serial_init();
timer_init();
// Populate boot context // Populate boot context
boot_ctx.fb = framebuffer_request.response ? framebuffer_request.response->framebuffers[0] : NULL; boot_ctx.fb = framebuffer_request.response ? framebuffer_request.response->framebuffers[0] : NULL;
boot_ctx.mmap = memmap_request.response ? memmap_request.response : NULL; boot_ctx.mmap = memmap_request.response ? memmap_request.response : NULL;
boot_ctx.hhdm = hhdm_request.response ? hhdm_request.response : NULL; boot_ctx.hhdm = hhdm_request.response ? hhdm_request.response : NULL;
boot_ctx.kaddr = kerneladdr_request.response ? kerneladdr_request.response : NULL; boot_ctx.kaddr = kerneladdr_request.response ? kerneladdr_request.response : NULL;
boot_mem_display();
pmm_init(boot_ctx.mmap, boot_ctx.hhdm); pmm_init(boot_ctx.mmap, boot_ctx.hhdm);
// Remap kernel , HHDM and framebuffer // Remap kernel , HHDM and framebuffer
paging_init(boot_ctx.kaddr, boot_ctx.fb); paging_init(boot_ctx.kaddr, boot_ctx.fb);
uint32_t bgColor = 0x252525;
ft_ctx = flanterm_fb_init(
NULL,
NULL,
boot_ctx.fb->address, boot_ctx.fb->width, boot_ctx.fb->height, boot_ctx.fb->pitch,
boot_ctx.fb->red_mask_size, boot_ctx.fb->red_mask_shift,
boot_ctx.fb->green_mask_size, boot_ctx.fb->green_mask_shift,
boot_ctx.fb->blue_mask_size, boot_ctx.fb->blue_mask_shift,
NULL,
NULL, NULL,
&bgColor, NULL, // &bgColor
NULL, NULL,
NULL, 0, 0, 1,
0, 0,
0,
0
);
serial_init();
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();
idt_init();
timer_init();
kheap_init(); kheap_init();
vmm_init(); keyboard_init(FR);
struct process_t* idle_proc = process_create("idle", (void*)idle_main, 0); term_init();
gdt_init();
idt_init();
process_init();
idle_proc = process_create("idle", (void*)idle_main, 0);
struct process_t* pedicel = process_create("pedicel", (void*)pedicel_main, 0); struct process_t* pedicel = process_create("pedicel", (void*)pedicel_main, 0);
struct process_t* two = process_create("two", (void*)two_main, 0);
process_display_list(processes_list); process_display_list(processes_list);
scheduler_init(); scheduler_init();
current_process = idle_proc; kputs(PEPPEROS_SPLASH);
current_process->status = RUNNING;
SET_INTERRUPTS;
keyboard_init(FR);
//term_init();
//printf(PEPPEROS_SPLASH);
//printf("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur eu diam id sem tincidunt vestibulum. Etiam sed congue nisl, vitae aliquet orci. Donec magna turpis, semper sed ipsum eget, semper blandit dolor. Morbi faucibus posuere sapien. Vestibulum aliquet mi vel orci finibus, vestibulum rhoncus tellus sagittis. Vivamus a arcu suscipit sem iaculis volutpat vel nec est. Nulla malesuada, urna vel pretium pretium, enim tortor pulvinar velit, porttitor dictum lectus turpis id tortor. Quisque egestas ultricies lorem, egestas ultrices tellus elementum porta. Fusce consequat nisi in diam placerat fermentum. Suspendisse tempus turpis nec turpis condimentum fringilla. Maecenas nec orci pharetra, feugiat enim vel, viverra neque. Vivamus placerat purus in tincidunt ultricies. Pellentesque vel mi molestie, congue nibh nec, cursus nisl. Cras dapibus lectus mauris, sed interdum risus tristique non. ");
flanterm_write(ft_ctx, "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur eu diam id sem tincidunt vestibulum. Etiam sed congue nisl, vitae aliquet orci. Donec magna turpis, semper sed ipsum eget, semper blandit dolor. Morbi faucibus posuere sapien. Vestibulum aliquet mi vel orci finibus, vestibulum rhoncus tellus sagittis. Vivamus a arcu suscipit sem iaculis volutpat vel nec est. Nulla malesuada, urna vel pretium pretium, enim tortor pulvinar velit, porttitor dictum lectus turpis id tortor. Quisque egestas ultricies lorem, egestas ultrices tellus elementum porta. Fusce consequat nisi in diam placerat fermentum. Suspendisse tempus turpis nec turpis condimentum fringilla. Maecenas nec orci pharetra, feugiat enim vel, viverra neque. Vivamus placerat purus in tincidunt ultricies. Pellentesque vel mi molestie, congue nibh nec, cursus nisl. Cras dapibus lectus mauris, sed interdum risus tristique non.", sizeof("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur eu diam id sem tincidunt vestibulum. Etiam sed congue nisl, vitae aliquet orci. Donec magna turpis, semper sed ipsum eget, semper blandit dolor. Morbi faucibus posuere sapien. Vestibulum aliquet mi vel orci finibus, vestibulum rhoncus tellus sagittis. Vivamus a arcu suscipit sem iaculis volutpat vel nec est. Nulla malesuada, urna vel pretium pretium, enim tortor pulvinar velit, porttitor dictum lectus turpis id tortor. Quisque egestas ultricies lorem, egestas ultrices tellus elementum porta. Fusce consequat nisi in diam placerat fermentum. Suspendisse tempus turpis nec turpis condimentum fringilla. Maecenas nec orci pharetra, feugiat enim vel, viverra neque. Vivamus placerat purus in tincidunt ultricies. Pellentesque vel mi molestie, congue nibh nec, cursus nisl. Cras dapibus lectus mauris, sed interdum risus tristique non. "));
idle(); idle();
} }
+30 -47
View File
@@ -23,40 +23,36 @@ static uintptr_t end;
// Kernel root table (level 4) // Kernel root table (level 4)
extern uint64_t *kernel_pml4; extern uint64_t *kernel_pml4;
static void kheap_grow(size_t size)
{
size_t pages = ALIGN_UP(size + sizeof(struct heap_block_t), PAGE_SIZE) / PAGE_SIZE;
if (pages == 0) pages = 1;
for (size_t i = 0; i < pages; i++)
{
kheap_map_page();
}
}
void kheap_map_page()
{
uintptr_t phys = pmm_alloc();
paging_map_page(kernel_pml4, end, phys, PTE_PRESENT | PTE_WRITABLE | PTE_NOEXEC);
end += PAGE_SIZE;
//DEBUG("Mapped first kheap page");
}
void kheap_init() void kheap_init()
{ {
kheap_start = ALIGN_UP(kernel_virt_base + KERNEL_SIZE, PAGE_SIZE); kheap_start = ALIGN_UP(kernel_virt_base + KERNEL_SIZE, PAGE_SIZE);
end = kheap_start;
// At least 1 page must be mapped for it to work size_t heap_pages = ALIGN_UP(KHEAP_SIZE, PAGE_SIZE) / PAGE_SIZE;
kheap_map_page(); DEBUG("Mapping %d kernel heap pages at 0x%p", heap_pages, kheap_start);
uintptr_t current_addr = kheap_start;
// Map/alloc enough pages for heap (KHEAP_SIZE)
for (size_t i=0; i<heap_pages; i++)
{
uintptr_t phys = pmm_alloc();
if (phys == 0)
{
panic(NULL, "Not enough memory available to initialize kernel heap.");
}
paging_map_page(kernel_pml4, current_addr, phys, PTE_PRESENT | PTE_WRITABLE);
current_addr += PAGE_SIZE;
}
end = current_addr;
// Give linked list head its properties // Give linked list head its properties
head = (struct heap_block_t*)kheap_start; head = (struct heap_block_t*)kheap_start;
head->size = PAGE_SIZE - sizeof(struct heap_block_t); head->size = (end-kheap_start) - sizeof(struct heap_block_t);
head->free = true; head->free = true;
head->next = NULL; head->next = NULL;
DEBUG("kheap initialized, head=0x%p, size=%u", head, head->size); DEBUG("Kernel heap initialized, head=0x%p, size=%u bytes", head, head->size);
} }
void* kmalloc(size_t size) void* kmalloc(size_t size)
@@ -73,12 +69,12 @@ void* kmalloc(size_t size)
if (curr->free && curr->size >= size) if (curr->free && curr->size >= size)
{ {
// We split the block if it is big enough // We split the block if it is big enough
if (curr->size >= size + BLOCK_MIN_SIZE) if (curr->size >= size + sizeof(struct heap_block_t) + 16)
{ {
//struct heap_block_t* new_block = (struct heap_block_t*)((uintptr_t)curr + sizeof(struct heap_block_t) + size); //struct heap_block_t* new_block = (struct heap_block_t*)((uintptr_t)curr + sizeof(struct heap_block_t) + size);
struct heap_block_t* split = (struct heap_block_t*)((uintptr_t)curr + sizeof(*curr) + size); struct heap_block_t* split = (struct heap_block_t*)((uintptr_t)curr + sizeof(struct heap_block_t) + size);
split->size = curr->size - size - sizeof(*curr); split->size = curr->size - size - sizeof(struct heap_block_t);
split->free = true; split->free = true;
split->next = curr->next; split->next = curr->next;
@@ -94,25 +90,12 @@ void* kmalloc(size_t size)
curr = curr->next; curr = curr->next;
} }
// If we're here it means we didn't have enough memory // No growing. If we're here it means the initial pool
// for the block allocation. So we will allocate more.. // wasn't sufficient. Too bad.
uintptr_t old_end = end; DEBUG("Kernel heap is OUT OF MEMORY!");
kheap_grow(size + sizeof(struct heap_block_t)); // if we were terrorists maybe we should panic
// or just wait for others to free stuff?
struct heap_block_t* block = (struct heap_block_t*)old_end; return NULL;
block->size = ALIGN_UP(end - old_end - sizeof(struct heap_block_t), 16);
block->free = true;
block->next = NULL;
// Put the block at the end of the list
curr = head;
while (curr->next)
{
curr = curr->next;
}
curr->next = block;
return kmalloc(size);
} }
void kfree(void* ptr) void kfree(void* ptr)
+4 -2
View File
@@ -14,13 +14,15 @@
#include <stdbool.h> #include <stdbool.h>
#include <stddef.h> #include <stddef.h>
#include <stdint.h>
struct heap_block_t struct heap_block_t
{ {
size_t size; size_t size;
bool free; bool free; // 1byte
uint8_t reserved[7]; // (7+1 = 8 bytes)
struct heap_block_t* next; struct heap_block_t* next;
}; } __attribute__((aligned(16)));
void kheap_init(); void kheap_init();
void* kmalloc(size_t size); void* kmalloc(size_t size);
-49
View File
@@ -77,52 +77,3 @@ int memcmp(const void* s1, const void* s2, size_t n)
return 0; return 0;
} }
// Display the memmap so we see how the memory is laid out at handoff
void memmap_display(struct limine_memmap_response* response)
{
DEBUG("Got memory map from Limine: revision %u, %u entries", response->revision, response->entry_count);
for (size_t i=0; i<response->entry_count; i++)
{
struct limine_memmap_entry* entry = response->entries[i];
char type[32] = {0};
switch(entry->type)
{
case LIMINE_MEMMAP_USABLE:
strcpy(type, "USABLE");
break;
case LIMINE_MEMMAP_RESERVED:
strcpy(type, "RESERVED");
break;
case LIMINE_MEMMAP_ACPI_RECLAIMABLE:
strcpy(type, "ACPI_RECLAIMABLE");
break;
case LIMINE_MEMMAP_ACPI_NVS:
strcpy(type, "ACPI_NVS");
break;
case LIMINE_MEMMAP_BAD_MEMORY:
strcpy(type, "BAD_MEMORY");
break;
case LIMINE_MEMMAP_BOOTLOADER_RECLAIMABLE:
strcpy(type, "BOOTLOADER_RECLAIMABLE");
break;
case LIMINE_MEMMAP_KERNEL_AND_MODULES:
strcpy(type, "KERNEL_AND_MODULES");
break;
case LIMINE_MEMMAP_FRAMEBUFFER:
strcpy(type, "FRAMEBUFFER");
break;
default:
strcpy(type, "UNKNOWN");
break;
}
DEBUG("entry %02u: [0x%016x | %016u bytes] - %s", i, entry->base, entry->length, type);
}
}
// Display the HHDM
void hhdm_display(struct limine_hhdm_response* hhdm)
{
DEBUG("Got HHDM revision=%u offset=0x%p", hhdm->revision, hhdm->offset);
}
+2 -1
View File
@@ -68,5 +68,6 @@ void vmm_setup_pt_root()
void vmm_init() void vmm_init()
{ {
vmm_setup_pt_root(); // NO U
//vmm_setup_pt_root();
} }
+4 -18
View File
@@ -13,6 +13,9 @@
#include "config.h" #include "config.h"
#include "io/serial/serial.h" #include "io/serial/serial.h"
#include "io/term/flanterm.h"
extern struct flanterm_context* ft_ctx;
struct process_t* processes_list; struct process_t* processes_list;
struct process_t* current_process; struct process_t* current_process;
@@ -139,23 +142,6 @@ struct process_t* process_get_next(struct process_t* process)
return process->next; return process->next;
} }
// (from gdt) This will switch tasks ONLY in ring 0
// KERNEL CS = 0x08
// KERNEL SS = 0x10
__attribute__((naked, noreturn))
void process_switch(uint64_t stack_addr, uint64_t code_addr)
{
asm volatile(" \
push $0x10 \n\
push %0 \n\
push $0x202 \n\
push $0x08 \n\
push %1 \n\
iretq \n\
" :: "r"(stack_addr), "r"(code_addr));
}
// Will be used to clean up resources (if any, when we implement it) // Will be used to clean up resources (if any, when we implement it)
// Just mark as DEAD then idle. Scheduler will delete process at next timer interrupt % quantum. // Just mark as DEAD then idle. Scheduler will delete process at next timer interrupt % quantum.
void process_exit() void process_exit()
@@ -168,7 +154,7 @@ void process_exit()
} }
SET_INTERRUPTS; SET_INTERRUPTS;
outb(0x20, 0x20); //outb(0x20, 0x20);
for (;;) for (;;)
{ {
asm("hlt"); asm("hlt");
-1
View File
@@ -34,7 +34,6 @@ struct process_t* process_create(char* name, void(*function)(void*), void* arg);
void process_add(struct process_t** processes_list, struct process_t* process); void process_add(struct process_t** processes_list, struct process_t* process);
void process_delete(struct process_t** processes_list, struct process_t* process); void process_delete(struct process_t** processes_list, struct process_t* process);
struct process_t* process_get_next(struct process_t* process); struct process_t* process_get_next(struct process_t* process);
void process_switch(uint64_t stack_addr, uint64_t code_addr);
void process_exit(); void process_exit();
void process_display_list(struct process_t* processes_list); void process_display_list(struct process_t* processes_list);
+14 -2
View File
@@ -12,6 +12,7 @@
extern struct process_t* processes_list; extern struct process_t* processes_list;
extern struct process_t* current_process; extern struct process_t* current_process;
extern struct process_t* idle_proc;
void scheduler_init() void scheduler_init()
{ {
@@ -21,6 +22,17 @@ void scheduler_init()
struct cpu_status_t* scheduler_schedule(struct cpu_status_t* context) struct cpu_status_t* scheduler_schedule(struct cpu_status_t* context)
{ {
if (context == NULL)
{
panic(NULL, "Scheduler called with NULL context");
}
if (current_process == NULL)
{
// If no more processes, then set IDLE as the current process, that's it.
current_process = idle_proc;
}
current_process->context = context; current_process->context = context;
//current_process->status = READY; //current_process->status = READY;
@@ -37,6 +49,8 @@ struct cpu_status_t* scheduler_schedule(struct cpu_status_t* context)
if (current_process != NULL && current_process->status == DEAD) if (current_process != NULL && current_process->status == DEAD)
{ {
process_delete(&prev_process, current_process); process_delete(&prev_process, current_process);
current_process = NULL;
return idle_proc->context;
} else } else
{ {
current_process->status = RUNNING; current_process->status = RUNNING;
@@ -44,8 +58,6 @@ struct cpu_status_t* scheduler_schedule(struct cpu_status_t* context)
} }
} }
// Current_process gets wrong context?? (iret_rip points to other stuff than process function; like putpixel() for example)
DEBUG("current_process={pid=%u, name='%s', root_page_table[virt]=%p}", current_process->pid, current_process->name, current_process->root_page_table); DEBUG("current_process={pid=%u, name='%s', root_page_table[virt]=%p}", current_process->pid, current_process->name, current_process->root_page_table);
load_cr3(VIRT_TO_PHYS((uint64_t)current_process->root_page_table)); load_cr3(VIRT_TO_PHYS((uint64_t)current_process->root_page_table));
-7
View File
@@ -1,7 +0,0 @@
; Task (process) switching
bits 64
global switch_to_task
switch_to_task:
+3
View File
@@ -18,6 +18,8 @@ interested in multi-core functionnality like SMP)
volatile uint64_t ticks = 0; volatile uint64_t ticks = 0;
extern struct init_status init;
void pic_remap() void pic_remap()
{ {
uint8_t master_mask = inb(0x21); uint8_t master_mask = inb(0x21);
@@ -91,4 +93,5 @@ void timer_init()
pic_enable(); pic_enable();
pit_init(); pit_init();
DEBUG("PIT initialized"); DEBUG("PIT initialized");
init.timer = true;
} }
BIN
View File
Binary file not shown.