Merge pull request 'kbd_fix' (#12) from kbd_fix into main
Reviewed-on: #12
This commit was merged in pull request #12.
This commit is contained in:
@@ -41,8 +41,10 @@ PepperOS wouldn't be possible without the following freely-licensed software:
|
||||
|
||||
- the [Limine](https://codeberg.org/Limine/Limine) portable bootloader
|
||||
- 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:
|
||||
|
||||
- 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/)
|
||||
@@ -151,12 +151,13 @@ vector_7_handler:
|
||||
align 16
|
||||
vector_8_handler:
|
||||
; No error code, we only push vector number
|
||||
push qword 1
|
||||
push qword 8
|
||||
jmp interrupt_stub
|
||||
|
||||
; Coprocessor Segment Overrun
|
||||
align 16
|
||||
vector_9_handler:
|
||||
push qword 0
|
||||
push qword 9
|
||||
jmp interrupt_stub
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ struct idtr idt_reg;
|
||||
extern char vector_0_handler[];
|
||||
|
||||
// Timer ticks
|
||||
extern uint64_t ticks;
|
||||
extern volatile uint64_t ticks;
|
||||
|
||||
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()
|
||||
{
|
||||
// We set 256 entries, but we have only the first few stubs.
|
||||
// Undefined behavior?
|
||||
for (size_t i=0; i<256; i++)
|
||||
// Hardcoded...
|
||||
for (size_t i=0; i<=33; i++)
|
||||
{
|
||||
// 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);
|
||||
@@ -210,6 +209,7 @@ struct cpu_status_t* interrupt_dispatch(struct cpu_status_t* context)
|
||||
case 33:
|
||||
DEBUG("Keyboard Interrupt");
|
||||
keyboard_handler();
|
||||
outb(0x20, 0x20);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
@@ -17,6 +17,8 @@ uint8_t key_status = 0b00000000;
|
||||
unsigned char* keymap;
|
||||
unsigned char* keymap_shifted;
|
||||
|
||||
extern struct init_status init;
|
||||
|
||||
unsigned char kbdus[128] =
|
||||
{
|
||||
0, 27, '1', '2', '3', '4', '5', '6', '7', '8', /* 9 */
|
||||
@@ -176,9 +178,6 @@ void keyboard_handler()
|
||||
key_status &= ~ALT_PRESSED_BIT;
|
||||
break;
|
||||
}
|
||||
|
||||
// Send EOI
|
||||
outb(0x20, 0x20);
|
||||
return;
|
||||
}
|
||||
else
|
||||
@@ -199,21 +198,26 @@ void keyboard_handler()
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
// Avoiding buffer overflow from extended keys lol
|
||||
if (scancode < 128)
|
||||
{
|
||||
// Should we get a SHIFTED char or a regular one?
|
||||
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)
|
||||
@@ -233,14 +237,21 @@ void keyboard_init(unsigned char layout)
|
||||
break;
|
||||
|
||||
default:
|
||||
skputs("Unsupported layout.");
|
||||
panic(NULL, "Unsupported keyboard layout");
|
||||
return;
|
||||
}
|
||||
|
||||
// Flush keyboard buffer
|
||||
while (inb(0x64) & 1)
|
||||
{
|
||||
inb(0x60);
|
||||
}
|
||||
|
||||
// Unmask IRQ1
|
||||
uint8_t mask = inb(0x21);
|
||||
mask &= ~(1 << 1);
|
||||
outb(0x21, mask);
|
||||
|
||||
DEBUG("PS/2 Keyboard initialized");
|
||||
init.keyboard = true;
|
||||
}
|
||||
@@ -7,6 +7,8 @@
|
||||
#include <kernel.h>
|
||||
#include "serial.h"
|
||||
|
||||
extern struct init_status init;
|
||||
|
||||
void outb(int port, unsigned char data)
|
||||
{
|
||||
__asm__ __volatile__("outb %%al, %%dx" :: "a" (data),"d" (port));
|
||||
@@ -43,6 +45,7 @@ int serial_init()
|
||||
outb(PORT + 4, 0x0F);
|
||||
|
||||
DEBUG("*** Welcome to PepperOS! ***");
|
||||
init.serial = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -54,6 +57,7 @@ static int is_transmit_empty()
|
||||
// Serial kernel putchar
|
||||
void skputc(char c)
|
||||
{
|
||||
// TODO: Spinlock here (serial access)
|
||||
while (!is_transmit_empty()); // wait for free spot
|
||||
outb(PORT, c);
|
||||
}
|
||||
|
||||
@@ -16,12 +16,17 @@ because this shitty implementation will be replaced one day by Flanterm
|
||||
#include "term.h"
|
||||
#include "config.h"
|
||||
#include "flanterm.h"
|
||||
#include "flanterm_backends/fb.h"
|
||||
#include "mem/heap/kheap.h"
|
||||
#include "limine.h"
|
||||
|
||||
extern struct flanterm_context* ft_ctx;
|
||||
extern struct init_status init;
|
||||
|
||||
// Overhead that could be avoided, right? (for printf)
|
||||
void _putchar(char character)
|
||||
{
|
||||
// TODO: Spinlock here (terminal access)
|
||||
flanterm_write(ft_ctx, &character, 1);
|
||||
}
|
||||
|
||||
@@ -36,3 +41,34 @@ void kputs(const char* str)
|
||||
}
|
||||
_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;
|
||||
}
|
||||
@@ -9,5 +9,6 @@
|
||||
|
||||
void kputs(const char* str);
|
||||
void _putchar(char character);
|
||||
void term_init();
|
||||
|
||||
#endif
|
||||
|
||||
14
src/kernel.h
14
src/kernel.h
@@ -19,9 +19,11 @@ enum ErrorCodes
|
||||
#include "io/serial/serial.h"
|
||||
#include "io/term/printf.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, ...) \
|
||||
printf("debug: [%s]: " log "\r\n", __FILE__, ##__VA_ARGS__); \
|
||||
@@ -38,6 +40,7 @@ void panic(struct cpu_status_t* ctx, const char* str);
|
||||
void hcf();
|
||||
void idle();
|
||||
|
||||
/* debug */
|
||||
void debug_stack_trace(unsigned int max_frames);
|
||||
const char* debug_find_symbol(uintptr_t rip, uintptr_t* offset);
|
||||
void boot_mem_display();
|
||||
@@ -52,4 +55,13 @@ struct boot_context
|
||||
struct limine_kernel_address_response* kaddr;
|
||||
};
|
||||
|
||||
// Are these modules initialized yet?
|
||||
struct init_status
|
||||
{
|
||||
bool terminal;
|
||||
bool serial;
|
||||
bool keyboard;
|
||||
bool timer;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
47
src/kmain.c
47
src/kmain.c
@@ -30,8 +30,6 @@
|
||||
__attribute__((used, section(".limine_requests")))
|
||||
volatile LIMINE_BASE_REVISION(3);
|
||||
|
||||
struct flanterm_context *ft_ctx;
|
||||
|
||||
// Halt and catch fire (makes machine stall)
|
||||
void hcf()
|
||||
{
|
||||
@@ -41,9 +39,9 @@ void hcf()
|
||||
// Doing nothing (can be interrupted)
|
||||
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 init_status init = {0};
|
||||
|
||||
extern volatile struct limine_framebuffer_request framebuffer_request;
|
||||
extern volatile struct limine_memmap_request memmap_request;
|
||||
@@ -52,22 +50,24 @@ extern volatile struct limine_kernel_address_request kerneladdr_request;
|
||||
|
||||
extern struct process_t* processes_list;
|
||||
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)
|
||||
{
|
||||
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 idle_main(void* arg)
|
||||
{
|
||||
for(;;)asm("hlt");
|
||||
}
|
||||
|
||||
void flanterm_free_wrapper(void* ptr, size_t size)
|
||||
for (;;)
|
||||
{
|
||||
(void)size;
|
||||
kfree(ptr);
|
||||
asm("hlt");
|
||||
}
|
||||
}
|
||||
|
||||
extern uintptr_t kheap_start;
|
||||
@@ -79,6 +79,7 @@ void kmain()
|
||||
if (!LIMINE_BASE_REVISION_SUPPORTED) hcf();
|
||||
|
||||
serial_init();
|
||||
timer_init();
|
||||
|
||||
// Populate boot context
|
||||
boot_ctx.fb = framebuffer_request.response ? framebuffer_request.response->framebuffers[0] : NULL;
|
||||
@@ -95,41 +96,19 @@ void kmain()
|
||||
|
||||
keyboard_init(FR);
|
||||
|
||||
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, // &bgColor
|
||||
NULL, NULL,
|
||||
NULL, 0, 0, 1,
|
||||
0, 0,
|
||||
0,
|
||||
0
|
||||
);
|
||||
term_init();
|
||||
|
||||
gdt_init();
|
||||
idt_init();
|
||||
|
||||
timer_init();
|
||||
vmm_init();
|
||||
|
||||
process_init();
|
||||
struct process_t* idle_proc = process_create("idle", (void*)idle_main, 0);
|
||||
idle_proc = process_create("idle", (void*)idle_main, 0);
|
||||
struct process_t* pedicel = process_create("pedicel", (void*)pedicel_main, 0);
|
||||
|
||||
process_display_list(processes_list);
|
||||
|
||||
scheduler_init();
|
||||
|
||||
current_process = idle_proc;
|
||||
current_process->status = RUNNING;
|
||||
|
||||
kputs(PEPPEROS_SPLASH);
|
||||
idle();
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ void process_display_list(struct process_t* processes_list)
|
||||
|
||||
struct process_t* process_create(char* name, void(*function)(void*), void* arg)
|
||||
{
|
||||
/* CLEAR_INTERRUPTS; */
|
||||
CLEAR_INTERRUPTS;
|
||||
struct process_t* proc = (struct process_t*)kmalloc(sizeof(struct process_t));
|
||||
|
||||
struct cpu_status_t* ctx = (struct cpu_status_t*)kmalloc(sizeof(struct cpu_status_t));
|
||||
@@ -79,7 +79,7 @@ struct process_t* process_create(char* name, void(*function)(void*), void* arg)
|
||||
|
||||
process_add(&processes_list, proc);
|
||||
|
||||
/* SET_INTERRUPTS; */
|
||||
SET_INTERRUPTS;
|
||||
return proc;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
extern struct process_t* processes_list;
|
||||
extern struct process_t* current_process;
|
||||
extern struct process_t* idle_proc;
|
||||
|
||||
void scheduler_init()
|
||||
{
|
||||
@@ -28,9 +29,8 @@ struct cpu_status_t* scheduler_schedule(struct cpu_status_t* context)
|
||||
|
||||
if (current_process == NULL)
|
||||
{
|
||||
// Wtf happened
|
||||
current_process = processes_list;
|
||||
//panic(NULL, "Scheduler called without current process");
|
||||
// If no more processes, then set IDLE as the current process, that's it.
|
||||
current_process = idle_proc;
|
||||
}
|
||||
|
||||
current_process->context = context;
|
||||
@@ -49,6 +49,8 @@ struct cpu_status_t* scheduler_schedule(struct cpu_status_t* context)
|
||||
if (current_process != NULL && current_process->status == DEAD)
|
||||
{
|
||||
process_delete(&prev_process, current_process);
|
||||
current_process = NULL;
|
||||
return idle_proc->context;
|
||||
} else
|
||||
{
|
||||
current_process->status = RUNNING;
|
||||
@@ -56,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);
|
||||
|
||||
load_cr3(VIRT_TO_PHYS((uint64_t)current_process->root_page_table));
|
||||
|
||||
@@ -18,6 +18,8 @@ interested in multi-core functionnality like SMP)
|
||||
|
||||
volatile uint64_t ticks = 0;
|
||||
|
||||
extern struct init_status init;
|
||||
|
||||
void pic_remap()
|
||||
{
|
||||
uint8_t master_mask = inb(0x21);
|
||||
@@ -91,4 +93,5 @@ void timer_init()
|
||||
pic_enable();
|
||||
pit_init();
|
||||
DEBUG("PIT initialized");
|
||||
init.timer = true;
|
||||
}
|
||||
Reference in New Issue
Block a user