Mathieu Serandour 12 months ago
parent
commit
65b4da21f4
  1. 4
      Makefile
  2. BIN
      disk_root/EFI/BOOT/BOOTX64.EFI
  3. BIN
      disk_root/boot/limine.sys
  4. 3
      disk_root/boot/m.asm
  5. 1
      kernel/acpi/acpi.c
  6. 24
      kernel/drivers/azerty.s
  7. 23
      kernel/drivers/pcie_driver_interface.h
  8. 147
      kernel/drivers/ps2kb.c
  9. 19
      kernel/drivers/ps2kb.h
  10. 45
      kernel/entry.c
  11. 86
      kernel/int/pic.c
  12. 8
      kernel/int/pic.h
  13. 4
      kernel/lib/registers.h
  14. 11
      kernel/lib/regs.s
  15. 12
      ss.sh

4
Makefile

@ -16,12 +16,12 @@ QEMU_ARGS := -monitor stdio \
-bios /usr/share/ovmf/OVMF.fd \
-m 8192 \
-M q35 \
-usb \
-device usb-host \
-vga virtio \
-no-reboot \
-D qemu.log \
-drive format=raw,file=
# -usb \
# -device usb-host \
QEMU_DEBUG_ARGS:= -no-shutdown -d int $(QEMU_ARGS)

BIN
disk_root/EFI/BOOT/BOOTX64.EFI

Binary file not shown.

BIN
disk_root/boot/limine.sys

Binary file not shown.

3
disk_root/boot/m.asm

@ -0,0 +1,3 @@
[section .text]
start:
incbin "limine.sys"

1
kernel/acpi/acpi.c

@ -141,6 +141,7 @@ static void parse_madt(const struct MADT* table) {
break;
case APIC_TYPE_IO_INTERRUPT_SOURCE_OVERRIDE:
{
log_debug("ISSOU");
// const struct MADT_ioapic_interrupt_source_override_entry* entry = ptr;
}
break;

24
kernel/drivers/azerty.s

@ -0,0 +1,24 @@
; ps2 -> azerty
; translation table
[section .rodata]
[global ps2_azerty_table_lowercase]
[global ps2_azerty_table_uppercase]
ps2_azerty_table_lowercase:
db 0,0, "&e", '"', "'(-e_ca)=", 8
db 9, "azertyuiop^$", 10
db 0, "qsdfghjklmu", 0, 0, "*"
db "wxcvbn,;:!", 0,0
db 0,0, ' '
TIMES 80-53 db 0
db "<"
ps2_azerty_table_uppercase:
db 0,0, "1234567890)+", 8
db 9, "AZERTYUIOP^$", 10
db 0, "QSDFGHJKLM%", 0, 0, "*"
db "WXCVBN?./!", 0,0
db 0,0, ' '
TIMES 80-53 db 0
db "<"

23
kernel/drivers/pcie_driver_interface.h

@ -1,23 +0,0 @@
/**
* PCIE drivers interfaces:
*
* provide void init(void* config_space_base)
*
* functions to call:
* register_irq(unsigned)
* unregister_irq(unsigned)
*
* int register_timer(void callback(void), unsigned period)
* void unregister_timer(int timer_id)
*
*/
void
/**
* return 0 if the irq was successfully installed
*/
int register_irq(uint8_t irq_number, );

147
kernel/drivers/ps2kb.c

@ -0,0 +1,147 @@
#include "ps2kb.h"
#include "../lib/logging.h"
#include "../lib/registers.h"
#include "../lib/sprintf.h"
#include "../int/idt.h"
#include "../int/pic.h"
#include "../lib/registers.h"
static void kbevent_default_handler(const struct kbevent* event) {
(void) event;
}
static kbevent_handler handler = kbevent_default_handler;
static char lshift_state, rshift_state;
static uint8_t get_byte(void) {
// wait for the output bufer
// to be filled
while((inb(0x64) & 1) == 0) {
asm volatile("pause");
}
return inb(0x60);
}
// outputs a command to the controller
static void command_byte(uint8_t b) {
// wait for the input bufer
// to be empty
while((inb(0x64) & 2) == 1) {
asm volatile("pause");
}
outb(0x64, b);
}
extern const char ps2_azerty_table_lowercase[];
extern const char ps2_azerty_table_uppercase[];
static uint8_t leds_state = 0;
// by default, leds are disabled
int is_caps(void) {
// 3rd bit = 3rd led = caps
int s = (leds_state / 4) + (lshift_state | rshift_state);
return s % 2;
}
static int process_leds(uint8_t b) {
if(b == 0xba) {// caps lock
// flush data buffer
inb(0x60);
command_byte(0xED);
leds_state = leds_state ^ 4;
command_byte(leds_state);
return 1;
}
return 0;
}
static void process_byte(uint8_t b) {
if(b == 0xFA) // ACK
return;
else if(b == 0xFE) { // resend
// well shit
log_warn("something went wrong with the keyboard");
return;
}
else if(process_leds(b))
return;
struct kbevent ev = {
.type = (b&0x80) ? KEYRELEASED : KEYPRESSED,
.keycode = b&0x7f,
};
if(ev.keycode == 0x2A) {
lshift_state = ev.type;
return;
}
else if(ev.keycode == 0x36) {
rshift_state = ev.type;
return;
}
if(is_caps())
ev.scancode = ps2_azerty_table_uppercase[ev.keycode];
else
ev.scancode = ps2_azerty_table_lowercase[ev.keycode];
printf("%c", ev.scancode);
handler(&ev);
}
static void __attribute__((interrupt)) irq_handler(void* r) {
process_byte(inb(0x60));
pic_eoi(1);
}
void ps2kb_init(void) {
log_debug("init ps/2 keyboard...");
unsigned status = inb(0x64);
if(status & 0xc0) {
// error
log_warn("ps/2 controller error: %u", status);
return;
}
// enable ps2 through config byte
uint8_t config;
command_byte(0x20); // read config byte command
config = get_byte();
log_debug("zdf");
command_byte(0x6);
command_byte(config | 1);
set_irq_handler(17, irq_handler);
pic_mask_irq(1, 0);
for(;;)
asm("hlt");
//log_debug("dzdvf");
}
void ps2kb_set_event_callback(kbevent_handler h) {
handler = h;
}

19
kernel/drivers/ps2kb.h

@ -0,0 +1,19 @@
#pragma once
#include <stdint.h>
void ps2kb_init(void);
struct kbevent {
enum {
KEYRELEASED = 0,
KEYPRESSED = 1
} type;
uint32_t keycode;
uint32_t scancode;
};
typedef void (* kbevent_handler)(const struct kbevent* kbevent);
void ps2kb_set_event_callback(kbevent_handler h);

45
kernel/entry.c

@ -8,9 +8,11 @@
#include "acpi/acpi.h"
#include "int/apic.h"
#include "int/idt.h"
#include "int/pic.h"
#include "drivers/hpet.h"
#include "drivers/pcie.h"
#include "drivers/ps2kb.h"
#include "memory/physical_allocator.h"
#include "memory/paging.h"
@ -22,6 +24,7 @@
#include "lib/logging.h"
#include "lib/common.h"
#include "lib/registers.h"
#include "lib/dump.h"
#define KERNEL_STACK_SIZE 8192
@ -99,19 +102,19 @@ static void debug_terminal() {
puts(buff);
}
static void print_fb_infos(struct stivale2_struct_tag_framebuffer* fbtag) {
PRINT_VAL(fbtag->framebuffer_width);
PRINT_VAL(fbtag->framebuffer_height);
PRINT_VAL(fbtag->framebuffer_pitch);
PRINT_VAL(fbtag->framebuffer_bpp);
PRINT_HEX(fbtag->framebuffer_addr);
static void print_fb_infos(struct stivale2_struct_tag_framebuffer* framebuffer_tag) {
PRINT_VAL(framebuffer_tag->framebuffer_width);
PRINT_VAL(framebuffer_tag->framebuffer_height);
PRINT_VAL(framebuffer_tag->framebuffer_pitch);
PRINT_VAL(framebuffer_tag->framebuffer_bpp);
PRINT_HEX(framebuffer_tag->framebuffer_addr);
}
#pragma GCC diagnostic pop
static void init_memory(const struct stivale2_struct_tag_memmap* memmap_tag,
const struct stivale2_struct_tag_framebuffer* fbtag) {
const struct stivale2_struct_tag_framebuffer* framebuffer_tag) {
log_debug("init memory...");
init_physical_allocator(memmap_tag);
@ -120,9 +123,9 @@ static void init_memory(const struct stivale2_struct_tag_memmap* memmap_tag,
// map MMIOs
map_pages(
early_virtual_to_physical((void *)fbtag->framebuffer_addr),
early_virtual_to_physical((void *)framebuffer_tag->framebuffer_addr),
MMIO_BEGIN,
(fbtag->framebuffer_height * fbtag->framebuffer_pitch+0x0fff) / 0x1000,
(framebuffer_tag->framebuffer_height * framebuffer_tag->framebuffer_pitch+0x0fff) / 0x1000,
PRESENT_ENTRY
);
@ -142,14 +145,16 @@ void _start(struct stivale2_struct *stivale2_struct) {
// Let's get the terminal structure tag from the bootloader.
const struct stivale2_struct_tag_terminal* term_str_tag;
const struct stivale2_struct_tag_memmap* memmap_tag;
const struct stivale2_struct_tag_framebuffer* fbtag;
const struct stivale2_struct_tag_framebuffer* framebuffer_tag;
const struct stivale2_struct_tag_rsdp* rsdp_tag_ptr;
const struct stivale2_struct_tag_kernel_file_v2* boot_volume_tag;
term_str_tag = stivale2_get_tag(stivale2_struct, STIVALE2_STRUCT_TAG_TERMINAL_ID);
memmap_tag = stivale2_get_tag(stivale2_struct, STIVALE2_STRUCT_TAG_MEMMAP_ID);
fbtag = stivale2_get_tag(stivale2_struct, STIVALE2_STRUCT_TAG_FRAMEBUFFER_ID);
rsdp_tag_ptr = stivale2_get_tag(stivale2_struct, STIVALE2_STRUCT_TAG_RSDP_ID);
term_str_tag = stivale2_get_tag(stivale2_struct, STIVALE2_STRUCT_TAG_TERMINAL_ID);
memmap_tag = stivale2_get_tag(stivale2_struct, STIVALE2_STRUCT_TAG_MEMMAP_ID);
framebuffer_tag = stivale2_get_tag(stivale2_struct, STIVALE2_STRUCT_TAG_FRAMEBUFFER_ID);
rsdp_tag_ptr = stivale2_get_tag(stivale2_struct, STIVALE2_STRUCT_TAG_RSDP_ID);
boot_volume_tag = stivale2_get_tag(stivale2_struct, 0x9b4358364c19ee62);
// term_str_tag == NULL is not a blocking
// errror: stivale2 terminal is only used
@ -168,11 +173,11 @@ void _start(struct stivale2_struct *stivale2_struct) {
setup_isrs();
read_acpi_tables((void*)rsdp_tag_ptr->rsdp);
init_memory(memmap_tag, fbtag);
init_memory(memmap_tag, framebuffer_tag);
// first initialize our terminal
initVideo(fbtag, (void *)MMIO_BEGIN);
initVideo(framebuffer_tag, (void *)MMIO_BEGIN);
init_gdt_table();
// we cannot use stivale2 terminal
// after loading our gdt
@ -191,8 +196,12 @@ void _start(struct stivale2_struct *stivale2_struct) {
puts(log_get());
log_flush();
pcie_init();
// dump(boot_volume_tag->kernel_file, 160, 20, DUMP_HEX8);
log_info("boot file: %lx", boot_volume_tag->kernel_file);
//pcie_init();
pic_init();
ps2kb_init();
hpet_init();
apic_setup_clock();

86
kernel/int/pic.c

@ -0,0 +1,86 @@
#include "../lib/registers.h"
#include "../lib/assert.h"
#include "pic.h"
#define ICW1_ICW4 0x01 /* ICW4 (not) needed */
#define ICW1_SINGLE 0x02 /* Single (cascade) mode */
#define ICW1_INTERVAL4 0x04 /* Call address interval 4 (8) */
#define ICW1_LEVEL 0x08 /* Level triggered (edge) mode */
#define ICW1_INIT 0x10 /* Initialization - required! */
#define ICW4_8086 0x01 /* 8086/88 (MCS-80/85) mode */
#define ICW4_AUTO 0x02 /* Auto (normal) EOI */
#define ICW4_BUF_SLAVE 0x08 /* Buffered mode/slave */
#define ICW4_BUF_MASTER 0x0C /* Buffered mode/master */
#define ICW4_SFNM 0x10 /* Special fully nested (not) */
#define PIC_EOI 0x20 /* End-of-interrupt command code */
#define PIC1 0x20 /* IO base address for master PIC */
#define PIC2 0xA0 /* IO base address for slave PIC */
#define PIC1_COMMAND PIC1
#define PIC1_DATA (PIC1+1)
#define PIC2_COMMAND PIC2
#define PIC2_DATA (PIC2+1)
void pic_eoi(unsigned char irq)
{
if(irq >= 8)
outb(PIC2_COMMAND,PIC_EOI);
outb(PIC1_COMMAND,PIC_EOI);
}
static void io_wait(void) {
outb(0x80,0);
}
static uint16_t mask = 0xff;
void pic_init(void) {
outb(0x80, 0);
outb(PIC1_COMMAND, ICW1_INIT | ICW1_ICW4);
// starts the initialization sequence (in cascade mode)
io_wait();
outb(PIC2_COMMAND, ICW1_INIT | ICW1_ICW4);
io_wait();
outb(PIC1_DATA, 16);
// ICW2: Master PIC vector offset
io_wait();
outb(PIC2_DATA, 24);
// ICW2: Slave PIC vector offset
io_wait();
outb(PIC1_DATA, 4);
// ICW3: tell Master PIC that there is a slave PIC at IRQ2 (0000 0100)
io_wait();
outb(PIC2_DATA, 2);
// ICW3: tell Slave PIC its cascade identity (0000 0010)
io_wait();
outb(PIC1_DATA, ICW4_8086);
io_wait();
outb(PIC2_DATA, ICW4_8086);
io_wait();
// mask all interrupts
outb(PIC1_DATA, 0xff);
outb(PIC2_DATA, 0xff);
}
void pic_mask_irq(unsigned number, int do_mask) {
assert(number < 16);
if(do_mask)
mask |= 1 << number;
else
mask &= ~(1 << number);
outb(PIC1_DATA, mask & 0xff);
outb(PIC2_DATA, mask << 8);
}

8
kernel/int/pic.h

@ -0,0 +1,8 @@
#pragma once
void pic_init(void);
// mask = 1 => irq masked
// mask = 0 => irq unmasked
void pic_mask_irq(unsigned number, int mask);
void pic_eoi(unsigned char irq);

4
kernel/lib/registers.h

@ -28,4 +28,8 @@ uint64_t read_msr(uint32_t addr);
uint64_t write_msr(uint32_t addr, uint64_t value);
uint8_t inb(uint16_t port);
void outb(uint16_t port, uint8_t val);
#endif// REGISTERS_H

11
kernel/lib/regs.s

@ -112,6 +112,17 @@ inb:
pop rdx
ret
; void outb(uint16_t port, uint8_t val)
outb:
push rdx
mov rdx, rdi
mov rax, rsi
out dx, al
pop rdx
ret
; read_msr(uint32_t addr)

12
ss.sh

@ -0,0 +1,12 @@
#!/bin/sh
cd ./limine-bootloader/
rm -rf *
rm -rf .*
git clone https://github.com/limine-bootloader/limine.git . --branch=$V-binary
cp BOOTX64.EFI ../disk_root/EFI/BOOT/BOOTX64.EFI
cp limine.sys ../disk_root/boot/limine.sys
cd ..
make clean && make
Loading…
Cancel
Save