Initial commit

This commit is contained in:
2021-01-28 22:59:39 +01:00
commit d7f0e8dd36
30 changed files with 2092 additions and 0 deletions

23
kernel/cpu/idt.c Normal file
View File

@@ -0,0 +1,23 @@
//
// Created by rick on 8/18/19.
//
#include "idt.h"
idt_gate_t idt[IDT_REGISTERS];
idt_register_t idt_reg;
void set_idt_gate(int n, u32 handler) {
idt[n].low_offset = handler & 0xffff;
idt[n].sel = KERNEL_CS;
idt[n].always0 = 0;
idt[n].flags = 0x8E;
idt[n].high_offset = handler >> 16 & 0xFFFF;
}
void set_idt() {
idt_reg.base = (u32) &idt;
idt_reg.limit = IDT_REGISTERS * sizeof(idt_gate_t) - 1;
__asm__ __volatile__("lidtl (%0)" : : "r" (&idt_reg));
}

35
kernel/cpu/idt.h Normal file
View File

@@ -0,0 +1,35 @@
//
// Created by rick on 8/18/19.
//
#include "../types.h"
#ifndef MY_KERNEL_IDT_H
#define MY_KERNEL_IDT_H
#define KERNEL_CS 0x08
/* How every interrupt gate (handler) is defined */
typedef struct {
u16 low_offset; /* Lower 16 bits of handler function address */
u16 sel; /* Kernel segment selector */
u8 always0;
/* First byte
* Bit 7: "Interrupt is present"
* Bits 6-5: Privilege level of caller (0=kernel..3=user)
* Bit 4: Set to 0 for interrupt gates
* Bits 3-0: bits 1110 = decimal 14 = "32 bit interrupt gate" */
u8 flags;
u16 high_offset; /* Higher 16 bits of handler function address */
} __attribute__((packed)) idt_gate_t;
typedef struct {
u16 limit;
u32 base;
} __attribute__((packed)) idt_register_t;
#define IDT_REGISTERS 256
void set_idt_gate(int n, u32 handler);
void set_idt();
#endif //MY_KERNEL_IDT_H

426
kernel/cpu/interrupt.S Normal file
View File

@@ -0,0 +1,426 @@
.code32
# Defined in isr.c
#MISMATCH: "[extern isr_handler]"
#MISMATCH: "[extern irq_handler]"
# Common ISR code
isr_common_stub:
# 1. Save CPU state
pusha # Pushes edi,esi,ebp,esp,ebx,edx,ecx,eax
movw %ds,%ax # Lower 16-bits of eax = ds.
pushl %eax # save the data segment descriptor
movw $0x10,%ax # kernel data segment descriptor
movw %ax,%ds
movw %ax,%es
movw %ax,%fs
movw %ax,%gs
# 2. Call C handler
call isr_handler
# 3. Restore state
popl %eax
movw %ax,%ds
movw %ax,%es
movw %ax,%fs
movw %ax,%gs
popa
addl $8,%esp # Cleans up the pushed error code and pushed ISR number
sti
iret # pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP
# Common IRQ code. Identical to ISR code except for the 'call'
# and the 'pop ebx'
irq_common_stub:
pusha
movw %ds,%ax
pushl %eax
movw $0x10,%ax
movw %ax,%ds
movw %ax,%es
movw %ax,%fs
movw %ax,%gs
call irq_handler # Different than the ISR code
popl %ebx # Different than the ISR code
movw %bx,%ds
movw %bx,%es
movw %bx,%fs
movw %bx,%gs
popa
addl $8,%esp
sti
iret
# We don't get information about which interrupt was caller
# when the handler is run, so we will need to have a different handler
# for every interrupt.
# Furthermore, some interrupts push an error code onto the stack but others
# don't, so we will push a dummy error code for those which don't, so that
# we have a consistent stack for all of them.
# First make the ISRs global
.global isr0
.global isr1
.global isr2
.global isr3
.global isr4
.global isr5
.global isr6
.global isr7
.global isr8
.global isr9
.global isr10
.global isr11
.global isr12
.global isr13
.global isr14
.global isr15
.global isr16
.global isr17
.global isr18
.global isr19
.global isr20
.global isr21
.global isr22
.global isr23
.global isr24
.global isr25
.global isr26
.global isr27
.global isr28
.global isr29
.global isr30
.global isr31
.global irq0
.global irq1
.global irq2
.global irq3
.global irq4
.global irq5
.global irq6
.global irq7
.global irq8
.global irq9
.global irq10
.global irq11
.global irq12
.global irq13
.global irq14
.global irq15
# 0: Divide By Zero Exception
isr0:
cli
push $0
push $0
jmp isr_common_stub
# 1: Debug Exception
isr1:
cli
push $0
push $1
jmp isr_common_stub
# 2: Non Maskable Interrupt Exception
isr2:
cli
push $0
push $2
jmp isr_common_stub
# 3: Int 3 Exception
isr3:
cli
push $0
push $3
jmp isr_common_stub
# 4: INTO Exception
isr4:
cli
push $0
push $4
jmp isr_common_stub
# 5: Out of Bounds Exception
isr5:
cli
push $0
push $5
jmp isr_common_stub
# 6: Invalid Opcode Exception
isr6:
cli
push $0
push $6
jmp isr_common_stub
# 7: Coprocessor Not Available Exception
isr7:
cli
push $0
push $7
jmp isr_common_stub
# 8: Double Fault Exception (With Error Code!)
isr8:
cli
push $8
jmp isr_common_stub
# 9: Coprocessor Segment Overrun Exception
isr9:
cli
push $0
push $9
jmp isr_common_stub
# 10: Bad TSS Exception (With Error Code!)
isr10:
cli
push $10
jmp isr_common_stub
# 11: Segment Not Present Exception (With Error Code!)
isr11:
cli
push $11
jmp isr_common_stub
# 12: Stack Fault Exception (With Error Code!)
isr12:
cli
push $12
jmp isr_common_stub
# 13: General Protection Fault Exception (With Error Code!)
isr13:
cli
push $13
jmp isr_common_stub
# 14: Page Fault Exception (With Error Code!)
isr14:
cli
push $14
jmp isr_common_stub
# 15: Reserved Exception
isr15:
cli
push $0
push $15
jmp isr_common_stub
# 16: Floating Point Exception
isr16:
cli
push $0
push $16
jmp isr_common_stub
# 17: Alignment Check Exception
isr17:
cli
push $0
push $17
jmp isr_common_stub
# 18: Machine Check Exception
isr18:
cli
push $0
push $18
jmp isr_common_stub
# 19: Reserved
isr19:
cli
push $0
push $19
jmp isr_common_stub
# 20: Reserved
isr20:
cli
push $0
push $20
jmp isr_common_stub
# 21: Reserved
isr21:
cli
push $0
push $21
jmp isr_common_stub
# 22: Reserved
isr22:
cli
push $0
push $22
jmp isr_common_stub
# 23: Reserved
isr23:
cli
push $0
push $23
jmp isr_common_stub
# 24: Reserved
isr24:
cli
push $0
push $24
jmp isr_common_stub
# 25: Reserved
isr25:
cli
push $0
push $25
jmp isr_common_stub
# 26: Reserved
isr26:
cli
push $0
push $26
jmp isr_common_stub
# 27: Reserved
isr27:
cli
push $0
push $27
jmp isr_common_stub
# 28: Reserved
isr28:
cli
push $0
push $28
jmp isr_common_stub
# 29: Reserved
isr29:
cli
push $0
push $29
jmp isr_common_stub
# 30: Reserved
isr30:
cli
push $0
push $30
jmp isr_common_stub
# 31: Reserved
isr31:
cli
push $0
push $31
jmp isr_common_stub
# IRQ handlers
irq0:
cli
push $0
push $32
jmp irq_common_stub
irq1:
cli
push $1
push $33
jmp irq_common_stub
irq2:
cli
push $2
push $34
jmp irq_common_stub
irq3:
cli
push $3
push $35
jmp irq_common_stub
irq4:
cli
push $4
push $36
jmp irq_common_stub
irq5:
cli
push $5
push $37
jmp irq_common_stub
irq6:
cli
push $6
push $38
jmp irq_common_stub
irq7:
cli
push $7
push $39
jmp irq_common_stub
irq8:
cli
push $8
push $40
jmp irq_common_stub
irq9:
cli
push $9
push $41
jmp irq_common_stub
irq10:
cli
push $10
push $42
jmp irq_common_stub
irq11:
cli
push $11
push $43
jmp irq_common_stub
irq12:
cli
push $12
push $44
jmp irq_common_stub
irq13:
cli
push $13
push $45
jmp irq_common_stub
irq14:
cli
push $14
push $46
jmp irq_common_stub
irq15:
cli
push $15
push $47
jmp irq_common_stub

144
kernel/cpu/isr.c Normal file
View File

@@ -0,0 +1,144 @@
//
// Created by rick on 8/18/19.
//
#include "isr.h"
#include <kprint.h>
#include <cpu/idt.h>
#include <libc/libc.h>
#include <drivers/ports.h>
isr_t interrupt_handlers[256];
void isr_install() {
set_idt_gate(0, (u32) isr0);
set_idt_gate(1, (u32) isr1);
set_idt_gate(2, (u32) isr2);
set_idt_gate(3, (u32) isr3);
set_idt_gate(4, (u32) isr4);
set_idt_gate(5, (u32) isr5);
set_idt_gate(6, (u32) isr6);
set_idt_gate(7, (u32) isr7);
set_idt_gate(8, (u32) isr8);
set_idt_gate(9, (u32) isr9);
set_idt_gate(10, (u32) isr10);
set_idt_gate(11, (u32) isr11);
set_idt_gate(12, (u32) isr12);
set_idt_gate(13, (u32) isr13);
set_idt_gate(14, (u32) isr14);
set_idt_gate(15, (u32) isr15);
set_idt_gate(16, (u32) isr16);
set_idt_gate(17, (u32) isr17);
set_idt_gate(18, (u32) isr18);
set_idt_gate(19, (u32) isr19);
set_idt_gate(20, (u32) isr20);
set_idt_gate(21, (u32) isr21);
set_idt_gate(22, (u32) isr22);
set_idt_gate(23, (u32) isr23);
set_idt_gate(24, (u32) isr24);
set_idt_gate(25, (u32) isr25);
set_idt_gate(26, (u32) isr26);
set_idt_gate(27, (u32) isr27);
set_idt_gate(28, (u32) isr28);
set_idt_gate(29, (u32) isr29);
set_idt_gate(30, (u32) isr30);
set_idt_gate(31, (u32) isr31);
// Remap the PIC
port_byte_out(0x20, 0x11);
port_byte_out(0xA0, 0x11);
port_byte_out(0x21, 0x20);
port_byte_out(0xA1, 0x28);
port_byte_out(0x21, 0x04);
port_byte_out(0xA1, 0x02);
port_byte_out(0x21, 0x01);
port_byte_out(0xA1, 0x01);
port_byte_out(0x21, 0x0);
port_byte_out(0xA1, 0x0);
// Install the IRQs
set_idt_gate(32, (u32) irq0);
set_idt_gate(33, (u32) irq1);
set_idt_gate(34, (u32) irq2);
set_idt_gate(35, (u32) irq3);
set_idt_gate(36, (u32) irq4);
set_idt_gate(37, (u32) irq5);
set_idt_gate(38, (u32) irq6);
set_idt_gate(39, (u32) irq7);
set_idt_gate(40, (u32) irq8);
set_idt_gate(41, (u32) irq9);
set_idt_gate(42, (u32) irq10);
set_idt_gate(43, (u32) irq11);
set_idt_gate(44, (u32) irq12);
set_idt_gate(45, (u32) irq13);
set_idt_gate(46, (u32) irq14);
set_idt_gate(47, (u32) irq15);
set_idt(); // Load with ASM
}
char *exception_messages[] = {
"Division By Zero",
"Debug",
"Non Maskable Interrupt",
"Breakpoint",
"Into Detected Overflow",
"Out of Bounds",
"Invalid Opcode",
"No Coprocessor",
"Double Fault",
"Coprocessor Segment Overrun",
"Bad TSS",
"Segment Not Present",
"Stack Fault",
"General Protection Fault",
"Page Fault",
"Unknown Interrupt",
"Coprocessor Fault",
"Alignment Check",
"Machine Check",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved"
};
void isr_handler(registers_t r) {
kprint("received interrupt: ");
char s[3];
itoa(r.int_no, s);
kprint(s);
kprint("\n");
kprint(exception_messages[r.int_no]);
kprint("\n");
}
void register_interrupt_handler(u8 n, isr_t handler) {
interrupt_handlers[n] = handler;
}
void irq_handler(registers_t r) {
/* After every interrupt we need to send an EOI to the PICs
* or they will not send another interrupt again */
if (r.int_no >= 40) port_byte_out(0xA0, 0x20); /* slave */
port_byte_out(0x20, 0x20); /* master */
/* Handle the interrupt in a more modular way */
if (interrupt_handlers[r.int_no] != 0) {
isr_t handler = interrupt_handlers[r.int_no];
handler(r);
}
}

140
kernel/cpu/isr.h Normal file
View File

@@ -0,0 +1,140 @@
//
// Created by rick on 8/18/19.
//
#include "../types.h"
#ifndef MY_KERNEL_ISR_H
#define MY_KERNEL_ISR_H
/* ISRs reserved for CPU exceptions */
extern void isr0();
extern void isr1();
extern void isr2();
extern void isr3();
extern void isr4();
extern void isr5();
extern void isr6();
extern void isr7();
extern void isr8();
extern void isr9();
extern void isr10();
extern void isr11();
extern void isr12();
extern void isr13();
extern void isr14();
extern void isr15();
extern void isr16();
extern void isr17();
extern void isr18();
extern void isr19();
extern void isr20();
extern void isr21();
extern void isr22();
extern void isr23();
extern void isr24();
extern void isr25();
extern void isr26();
extern void isr27();
extern void isr28();
extern void isr29();
extern void isr30();
extern void isr31();
/* IRQ definitions */
extern void irq0();
extern void irq1();
extern void irq2();
extern void irq3();
extern void irq4();
extern void irq5();
extern void irq6();
extern void irq7();
extern void irq8();
extern void irq9();
extern void irq10();
extern void irq11();
extern void irq12();
extern void irq13();
extern void irq14();
extern void irq15();
#define IRQ0 32
#define IRQ1 33
#define IRQ2 34
#define IRQ3 35
#define IRQ4 36
#define IRQ5 37
#define IRQ6 38
#define IRQ7 39
#define IRQ8 40
#define IRQ9 41
#define IRQ10 42
#define IRQ11 43
#define IRQ12 44
#define IRQ13 45
#define IRQ14 46
#define IRQ15 47
typedef struct {
u32 ds;
u32 edi, esi, ebp, esp, ebx, edx, ecx, eax;
u32 int_no, err_code;
u32 eip, cs, eflags, useresp, ss;
} registers_t;
typedef void (*isr_t)(registers_t);
void register_interrupt_handler(u8 n, isr_t handler);
void isr_install();
void isr_handler(registers_t r);
#endif //MY_KERNEL_ISR_H

26
kernel/cpu/timer.c Normal file
View File

@@ -0,0 +1,26 @@
//
// Created by rick on 9/22/19.
//
#include "timer.h"
#include <drivers/ports.h>
#include <cpu/isr.h>
u32 tick = 0;
static void timer_callback(registers_t regs) {
tick++;
}
int init_timer(u32 freq) {
register_interrupt_handler(IRQ0, timer_callback);
u32 divisor = 1193180 / freq;
u8 low = (u8) (divisor & 0xFF);
u8 high = (u8) ((divisor >> 8) & 0xFF);
port_byte_out(PORT_PIT_COMMAND, PIT_MODE_BIN | PIT_MODE_SQUARE_WAVE | PIT_ACCESS_MODE_HL | PIT_CHANNEL_0);
port_byte_out(PORT_PIT_DATA_0, low);
port_byte_out(PORT_PIT_DATA_0, high);
return 0;
}

12
kernel/cpu/timer.h Normal file
View File

@@ -0,0 +1,12 @@
//
// Created by rick on 9/22/19.
//
#ifndef MY_KERNEL_TIMER_H
#define MY_KERNEL_TIMER_H
#include "../types.h"
int init_timer(u32 freq);
#endif //MY_KERNEL_TIMER_H

70
kernel/drivers/keyboard.c Normal file
View File

@@ -0,0 +1,70 @@
//
// Created by rick on 23-03-20.
//
#include "keyboard.h"
#include <kprint.h>
#include <drivers/ports.h>
#include <cpu/isr.h>
#include <libc/libc.h>
char scancodes_ascii[] = {
0, 0,
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', 0,
0, 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', 0,
0, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`',
0, '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', 0,
'*',
0, ' ',
0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // F1-F10
0, 0,
'7', '8', '9', '-',
'4', '5', '6', '+',
'1', '2', '3',
'0', 0,
0, // sysrq
0, 0, // weird
0, 0, // F11 F12
// weid
};
char *MSG_KEY = "Clicked on key 'x'\n";
void print_scancode(unsigned char scancode);
static void keyboard_callback(registers_t regs) {
unsigned char status = port_byte_in(PORT_PS2_STATUS);
// check if data available
if ((status & 0b00000001) == 0) {
return;
}
unsigned char scancode = port_byte_in(0x60);
print_scancode(scancode);
}
void init_keyboard() {
register_interrupt_handler(IRQ1, keyboard_callback);
}
void print_scancode(unsigned char scancode) {
char msg[256];
char release = 0;
if (scancode > 0x80) {
// release
release = 1;
scancode -= 0x80;
}
char code = scancodes_ascii[scancode];
if (code == 0) {
// special
} else {
if (release && code > 0x60 && code < 0x7B) {
code -= 0x20; // to lowercase
}
memcpy(msg, MSG_KEY, strlen(MSG_KEY));
msg[strlen(msg) - 3] = code;
kprint(msg);
}
}

10
kernel/drivers/keyboard.h Normal file
View File

@@ -0,0 +1,10 @@
//
// Created by rick on 23-03-20.
//
#ifndef MY_KERNEL_KEYBOARD_H
#define MY_KERNEL_KEYBOARD_H
void init_keyboard();
#endif //MY_KERNEL_KEYBOARD_H

33
kernel/drivers/ports.c Normal file
View File

@@ -0,0 +1,33 @@
/*
* ports.c
*
* Created on: Aug 18, 2019
* Author: rick
*/
#include "ports.h"
/**
* Read a byte from the specified port
*/
unsigned char port_byte_in(unsigned short port) {
unsigned char result;
__asm__("in %%dx, %%al" : "=a" (result) : "d" (port));
return result;
}
void port_byte_out(unsigned short port, unsigned char data) {
__asm__("out %%al, %%dx" : : "a" (data), "d" (port));
}
unsigned short port_word_in(unsigned short port) {
unsigned short result;
__asm__("in %%dx, %%ax" : "=a" (result) : "d" (port));
return result;
}
void port_wordt_out(unsigned short port, unsigned short data) {
__asm__("out %%ax, %%dx" : : "a" (data), "d" (port));
}

51
kernel/drivers/ports.h Normal file
View File

@@ -0,0 +1,51 @@
#ifndef MY_KERNEL_DRIVERS_PORT_H
#define MY_KERNEL_DRIVERS_PORT_H
//http://www.osdever.net/FreeVGA/vga/crtcreg.htm#0A
#define PORT_REG_SCREEN_CTRL 0x3d4
#define PORT_REG_SCREEN_CTRL_CURSOR_H 0x0E
#define PORT_REG_SCREEN_CTRL_CURSOR_L 0x0F
#define PORT_REG_SCREEN_DATA 0x3d5
// https://wiki.osdev.org/Serial_Ports
#define PORT_SERIAL_0 0x3f8
#define PORT_SERIAL_1 0x2f8
#define PORT_SERIAL_2 0x3e8
#define PORT_SERIAL_3 0x2e8
#define PORT_SERIAL_DATA 0
#define PORT_SERIAL_INTERRUPT 1
#define PORT_SERIAL_DLAB_LSB 0
#define PORT_SERIAL_DLAB_MSB 1
#define PORT_SERIAL_INTERRUPT_ID_FIFO 2
#define PORT_SERIAL_LINE_CONTROL 3
#define PORT_SERIAL_MODEM_CONTROL 4
#define PORT_SERIAL_LINE_STATUS 5
#define PORT_SERIAL_MODEM_STATUS 6
#define PORT_SERIAL_SCRATCH 6
// https://wiki.osdev.org/PIT
#define PORT_PIT_COMMAND 0x43
#define PIT_MODE_BIN 0x0
#define PIT_MODE_HW_STROBE 0b0101
#define PIT_MODE_SQUARE_WAVE 0b0110
#define PIT_ACCESS_MODE_HL 0b000011
#define PIT_CHANNEL_0 0b00000000
#define PORT_PIT_DATA_0 0x40
#define PORT_PIT_DATA_1 0x41
#define PORT_PIT_DATA_3 0x42
// https://wiki.osdev.org/%228042%22_PS/2_Controller
#define PORT_PS2_DATA 0x60
#define PORT_PS2_STATUS 0x64
#define PORT_PS2_COMMAND 0x64
unsigned char port_byte_in(unsigned short port);
void port_byte_out(unsigned short port, unsigned char data);
unsigned short port_word_in(unsigned short port);
void port_word_out(unsigned short port, unsigned short data);
#endif

56
kernel/drivers/serial.c Normal file
View File

@@ -0,0 +1,56 @@
//
// Created by rick on 28-01-21.
//
#include "serial.h"
#include <types.h>
#include <drivers/ports.h>
int serial_init() {
port_byte_out(PORT_SERIAL_0 + PORT_SERIAL_INTERRUPT, 0x00); // Disable all interrupts
port_byte_out(PORT_SERIAL_0 + PORT_SERIAL_LINE_CONTROL, 0x80); // Enable DLAB (set baud rate divisor)
port_byte_out(PORT_SERIAL_0 + PORT_SERIAL_DLAB_LSB, 0x03); // Set divisor to 3 (lo byte) 38400 baud
port_byte_out(PORT_SERIAL_0 + PORT_SERIAL_DLAB_MSB, 0x00); // (hi byte)
port_byte_out(PORT_SERIAL_0 + PORT_SERIAL_LINE_CONTROL, 0x03); // 8 bits, no parity, one stop bit
port_byte_out(PORT_SERIAL_0 + PORT_SERIAL_INTERRUPT_ID_FIFO,
0xC7); // Enable FIFO, clear them, with 14-byte threshold
port_byte_out(PORT_SERIAL_0 + PORT_SERIAL_MODEM_CONTROL, 0x0B); // IRQs enabled, RTS/DSR set
port_byte_out(PORT_SERIAL_0 + PORT_SERIAL_MODEM_CONTROL, 0x1E); // Set in loopback mode, test the serial chip
port_byte_out(PORT_SERIAL_0 + PORT_SERIAL_DATA,
0xAE); // Test serial chip (send byte 0xAE and check if serial returns same byte)
// Check if serial is faulty (i.e: not same byte as sent)
if (port_byte_in(PORT_SERIAL_0 + PORT_SERIAL_DATA) != 0xAE) {
return 1;
}
// If serial is not faulty set it in normal operation mode
// (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled)
port_byte_out(PORT_SERIAL_0 + PORT_SERIAL_MODEM_CONTROL, 0x0F);
return 0;
}
int is_transmit_empty() {
return port_byte_in(PORT_SERIAL_0 + PORT_SERIAL_LINE_STATUS) & 0x20;
}
void write_serial(char a) {
while (is_transmit_empty() == 0);
port_byte_out(PORT_SERIAL_0 + PORT_SERIAL_DATA, a);
}
void serial_kprint(char *msg) {
u32 i = 0;
while (1) {
char c = msg[i];
if (c == 0) {
break;
}
if (c == '\n') {
write_serial('\r');
}
write_serial(c);
i++;
}
}

12
kernel/drivers/serial.h Normal file
View File

@@ -0,0 +1,12 @@
//
// Created by rick on 28-01-21.
//
#ifndef NEW_KERNEL_SERIAL_H
#define NEW_KERNEL_SERIAL_H
int serial_init();
void serial_kprint(char *msg);
#endif //NEW_KERNEL_SERIAL_H

122
kernel/drivers/vgascreen.c Normal file
View File

@@ -0,0 +1,122 @@
//
// Created by rick on 8/18/19.
//
#include "vgascreen.h"
#include <libc/libc.h>
#include <drivers/ports.h>
char *_vga_character_memory = (char *) VGA_CHARACTER_MEMORY_LOCATION;
int get_offset(int col, int row);
int get_cursor_offset();
void set_cursor_offset(int offset);
int get_offset_row(int offset);
int get_offset_col(int offset);
int print_char(char character, int col, int row, char attributes);
void vga_clear_screen() {
int size = VGA_COL_MAX * VGA_ROW_MAX;
for (int i = 0; i < size; ++i) {
_vga_character_memory[i * 2] = ' ';
_vga_character_memory[i * 2 + 1] = VGA_WHITE | (VGA_BLACK << VGA_SHIFT_BG);
}
set_cursor_offset(0);
}
void kprint_at(char *message, int col, int row) {
int offset;
if (col > 0 && row > 0) {
offset = get_offset(col, row);
} else {
offset = get_cursor_offset();
row = get_offset_row(offset);
col = get_offset_col(offset);
}
int i = 0;
while (message[i] != 0) {
offset = print_char(message[i++], col, row, VGA_WHITE | (VGA_BLACK << VGA_SHIFT_BG));
row = get_offset_row(offset);
col = get_offset_col(offset);
}
}
void vga_kprint(char *message) {
kprint_at(message, -1, -1);
}
int print_char(char character, int col, int row, char attributes) {
if (!attributes) attributes = VGA_WHITE | (VGA_BLACK < VGA_SHIFT_BG);
if (col >= VGA_COL_MAX || row > +VGA_ROW_MAX) {
_vga_character_memory[2 * (VGA_COL_MAX) * (VGA_ROW_MAX) - 2] = 'E';
_vga_character_memory[2 * (VGA_COL_MAX) * (VGA_ROW_MAX) - 1] = VGA_RED | (VGA_WHITE < VGA_SHIFT_BG);
return get_offset(col, row);
}
int offset;
if (col >= 0 && row >= 0) {
offset = get_offset(col, row);
} else {
offset = get_cursor_offset();
}
if (character == '\n') {
row = get_offset_row(offset);
offset = get_offset(0, row + 1);
} else {
_vga_character_memory[offset] = character;
_vga_character_memory[offset + 1] = attributes;
offset += 2;
}
if (offset >= (VGA_COL_MAX * 2 * VGA_ROW_MAX)) {
memcpy(_vga_character_memory,
_vga_character_memory + (VGA_COL_MAX * 2),
(2 * VGA_COL_MAX * VGA_ROW_MAX) - (2 * VGA_COL_MAX));
for (int i = 0; i < VGA_COL_MAX; ++i) {
_vga_character_memory[get_offset(i, VGA_ROW_MAX - 1)] = ' ';
}
offset = get_offset(0, VGA_ROW_MAX - 1);
}
set_cursor_offset(offset);
return offset;
}
int get_cursor_offset() {
port_byte_out(PORT_REG_SCREEN_CTRL, PORT_REG_SCREEN_CTRL_CURSOR_H);
int offset = ((int) port_byte_in(PORT_REG_SCREEN_DATA)) << 8;
port_byte_out(PORT_REG_SCREEN_CTRL, PORT_REG_SCREEN_CTRL_CURSOR_L);
offset += port_byte_in(PORT_REG_SCREEN_DATA);
return offset * 2;
}
void set_cursor_offset(int offset) {
offset /= 2;
port_byte_out(PORT_REG_SCREEN_CTRL, PORT_REG_SCREEN_CTRL_CURSOR_L);
port_byte_out(PORT_REG_SCREEN_DATA, (unsigned char) (offset & 0xFF));
port_byte_out(PORT_REG_SCREEN_CTRL, PORT_REG_SCREEN_CTRL_CURSOR_H);
port_byte_out(PORT_REG_SCREEN_DATA, (unsigned char) (offset >> 8) & 0xFF);
}
int get_offset(int col, int row) {
return (row * VGA_COL_MAX + col) * 2;
}
int get_offset_row(int offset) {
return offset / (VGA_COL_MAX * 2);
}
int get_offset_col(int offset) {
return (offset - (get_offset_row(offset) * 2 * VGA_COL_MAX)) / 2;
}

View File

@@ -0,0 +1,34 @@
//
// Created by rick on 8/18/19.
//
#ifndef MY_KERNEL_DRIVERS_VGASCREEN_H
#define MY_KERNEL_DRIVERS_VGASCREEN_H
#define VGA_CHARACTER_MEMORY_LOCATION 0xb8000
#define VGA_BLACK 0x0
#define VGA_BLUE 0x1
#define VGA_GREEN 0x2
#define VGA_CIAN 0x3
#define VGA_RED 0x4
#define VGA_PURPLE 0x5
#define VGA_ORANGE 0x6
#define VGA_GRAY 0x7
#define VGA_DARK_GRAY 0x8
#define VGA_LIGHT_BLUE 0x9
#define VGA_LIGHT_GREEN 0xA
#define VGA_LIGHT_RED 0xB
#define VGA_PINK 0xD
#define VGA_YELLOW 0xE
#define VGA_WHITE 0xF
#define VGA_SHIFT_BG 4
#define VGA_BLINK 0x80
#define VGA_COL_MAX 80
#define VGA_ROW_MAX 25
void vga_clear_screen();
void vga_kprint(char *msg);
#endif //MY_KERNEL_VGASCREEN_H

46
kernel/kernel.c Normal file
View File

@@ -0,0 +1,46 @@
#include <drivers/ports.h>
#include <drivers/vgascreen.h>
#include <libc/libc.h>
#include <cpu/isr.h>
#include <cpu/timer.h>
#include <drivers/keyboard.h>
#include <mem/mem.h>
#include <multiboot.h>
#include <drivers/serial.h>
#include "kprint.h"
char *msg_booted = "Booted Successfully!\n";
void kmain(multiboot_info_t *multiboot_info) {
isr_install();
init_mmap((struct multiboot_mmap_entry *) multiboot_info->mmap_addr,
multiboot_info->mmap_length / sizeof(struct multiboot_mmap_entry));
vga_clear_screen();
vga_clear_screen(' ', VGA_WHITE | (VGA_GRAY << VGA_SHIFT_BG));
kprint_register(vga_kprint);
serial_init();
kprint_register(serial_kprint);
// vga_print_string(msg_booted, VGA_WHITE | (VGA_DARK_GRAY << VGA_SHIFT_BG));
kprint(msg_booted);
kprint((char *) multiboot_info->boot_loader_name);
multiboot_memory_map_t *fe = multiboot_info->mmap_addr;
// port_byte_out(0x3d4, 14);
// int pos = port_byte_in(0x3d5);
// pos <<= 8;
//
// port_byte_out(0x3d4, 15);
// pos += port_byte_in(0x3d5);
asm volatile("sti");
init_timer(50);
init_keyboard();
print_mmap_info();
// vga_set_raw(pos * 2, 'X');
// vga_set_raw(pos * 2 + 1, 0xf);
do {} while (1);
}

37
kernel/kprint.c Normal file
View File

@@ -0,0 +1,37 @@
//
// Created by rick on 28-01-21.
//
#include "kprint.h"
#define MAX_HANDLERS 8
kprint_handler handlers[MAX_HANDLERS] = {
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
};
void kprint_register(kprint_handler handler) {
for (int i = 0; i < MAX_HANDLERS; ++i) {
if (handlers[i] == NULL) {
handlers[i] = handler;
break;
}
}
// todo handle
}
void kprint(char *msg) {
for (int i = 0; i < MAX_HANDLERS; ++i) {
if (handlers[i] == NULL) {
continue;
}
handlers[i](msg);
}
}

16
kernel/kprint.h Normal file
View File

@@ -0,0 +1,16 @@
//
// Created by rick on 28-01-21.
//
#ifndef NEW_KERNEL_KPRINT_H
#define NEW_KERNEL_KPRINT_H
#endif //NEW_KERNEL_KPRINT_H
#include <types.h>
typedef void (*kprint_handler)(char *);
void kprint_register(kprint_handler);
void kprint(char *msg);

40
kernel/libc/libc.c Normal file
View File

@@ -0,0 +1,40 @@
/*
* libc.c
*
* Created on: Oct 11, 2018
* Author: rick
*/
#include "libc.h"
int memcpy(char *dst, char *src, int amount) {
for (int i = 0; i < amount; i++) {
dst[i] = src[i];
}
return 0;
}
int memset(char *dst, char data, int amount) {
for (int i = 0; i < amount; ++i) {
dst[i] = data;
}
return 0;
}
int itoa(int i, char *target) {
target[0] = (char) (i % 10 + '0');
target[1] = '\0';
if (i > 9) {
itoa(i / 10, target + 1);
}
return 0;
}
int strlen(char *str) {
int length = 0;
while (str[length] != 0) {
length++;
}
return length;
}

19
kernel/libc/libc.h Normal file
View File

@@ -0,0 +1,19 @@
/*
* libc.h
*
* Created on: Oct 11, 2018
* Author: rick
*/
#ifndef KERNEL_LIBC_LIBC_H_
#define KERNEL_LIBC_LIBC_H_
int memcpy(char *dst, char *src, int amount);
int memset(char *dst, char data, int amount);
int itoa(int i, char *target);
int strlen(char *str);
#endif /* KERNEL_LIBC_LIBC_H_ */

88
kernel/mem/mem.c Normal file
View File

@@ -0,0 +1,88 @@
//
// Created by rick on 22-04-20.
//
#include <types.h>
#include <kprint.h>
#include <mem/mem.h>
#include <libc/libc.h>
char *msg_index = "Idx: ";
char *msg_addr = "Address: ";
char *msg_len = "Length: ";
char *msg_type = "Type: ";
char *msg_nl = "\n";
typedef struct {
u64 address;
u64 length;
#define MMAP_TYPE_UNDEFINED 0
#define MMAP_TYPE_AVAILABLE 1
#define MMAP_TYPE_RESERVED 2
#define MMAP_TYPE_ACPI_RECLAIMABLE 3
#define MMAP_TYPE_NVS 4
#define MMAP_TYPE_BADRAM 5
u32 type;
} __attribute((packed)) mmap_entry;
char *msg_lu = "0123456789ABCDEF";
mmap_entry memmap[16] = {
{0, 0, 0},
{0, 0, 0},
{0, 0, 0},
{0, 0, 0},
{0, 0, 0},
{0, 0, 0},
{0, 0, 0},
{0, 0, 0},
{0, 0, 0},
{0, 0, 0},
{0, 0, 0},
{0, 0, 0},
{0, 0, 0},
{0, 0, 0},
{0, 0, 0},
{0, 0, 0},
};
void init_mmap(struct multiboot_mmap_entry *entries, u32 count) {
for (u32 i = 0; i < count; ++i) {
memmap[i].address = entries[i].addr;
memmap[i].length = entries[i].len;
memmap[i].type = entries[i].type;
}
}
void print_hex_u64(u64 input) {
char msg[18] = "0x0000000000000000";
for (int i = 0; i < 16; ++i) {
int val = input >> (4 * i) & 0xF;
msg[17 - i] = msg_lu[val];
}
kprint(msg);
}
void print_mmap_info() {
for (int i = 0; i < 16; ++i) {
if (memmap[i].type == 0) {
break;
}
char *tmp_str = " ";
kprint(msg_index);
itoa(i, tmp_str);
kprint(tmp_str);
kprint(msg_nl);
kprint(msg_addr);
print_hex_u64(memmap[i].address);
kprint(msg_nl);
kprint(msg_len);
print_hex_u64(memmap[i].length);
kprint(msg_nl);
kprint(msg_type);
itoa(memmap[i].type, tmp_str);
kprint(tmp_str);
kprint(msg_nl);
kprint(msg_nl);
}
}

14
kernel/mem/mem.h Normal file
View File

@@ -0,0 +1,14 @@
//
// Created by rick on 22-04-20.
//
#ifndef NEW_KERNEL_MEM_H
#define NEW_KERNEL_MEM_H
#include <multiboot.h>
void init_mmap(struct multiboot_mmap_entry *entries, u32 count);
void print_mmap_info();
#endif //NEW_KERNEL_MEM_H

262
kernel/multiboot.h Normal file
View File

@@ -0,0 +1,262 @@
//* multiboot.h - Multiboot header file. */
/* Copyright (C) 1999,2003,2007,2008,2009,2010 Free Software Foundation, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ANY
* DEVELOPER OR DISTRIBUTOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
* IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef MULTIBOOT_HEADER
#define MULTIBOOT_HEADER 1
/* How many bytes from the start of the file we search for the header. */
#define MULTIBOOT_SEARCH 8192
#define MULTIBOOT_HEADER_ALIGN 4
/* The magic field should contain this. */
#define MULTIBOOT_HEADER_MAGIC 0x1BADB002
/* This should be in %eax. */
#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002
/* Alignment of multiboot modules. */
#define MULTIBOOT_MOD_ALIGN 0x00001000
/* Alignment of the multiboot info structure. */
#define MULTIBOOT_INFO_ALIGN 0x00000004
/* Flags set in the flags member of the multiboot header. */
/* Align all boot modules on i386 page (4KB) boundaries. */
#define MULTIBOOT_PAGE_ALIGN 0x00000001
/* Must pass memory information to OS. */
#define MULTIBOOT_MEMORY_INFO 0x00000002
/* Must pass video information to OS. */
#define MULTIBOOT_VIDEO_MODE 0x00000004
/* This flag indicates the use of the address fields in the header. */
#define MULTIBOOT_AOUT_KLUDGE 0x00010000
/* Flags to be set in the flags member of the multiboot info structure. */
/* is there basic lower/upper memory information? */
#define MULTIBOOT_INFO_MEMORY 0x00000001
/* is there a boot device set? */
#define MULTIBOOT_INFO_BOOTDEV 0x00000002
/* is the command-line defined? */
#define MULTIBOOT_INFO_CMDLINE 0x00000004
/* are there modules to do something with? */
#define MULTIBOOT_INFO_MODS 0x00000008
/* These next two are mutually exclusive */
/* is there a symbol table loaded? */
#define MULTIBOOT_INFO_AOUT_SYMS 0x00000010
/* is there an ELF section header table? */
#define MULTIBOOT_INFO_ELF_SHDR 0X00000020
/* is there a full memory map? */
#define MULTIBOOT_INFO_MEM_MAP 0x00000040
/* Is there drive info? */
#define MULTIBOOT_INFO_DRIVE_INFO 0x00000080
/* Is there a config table? */
#define MULTIBOOT_INFO_CONFIG_TABLE 0x00000100
/* Is there a boot loader name? */
#define MULTIBOOT_INFO_BOOT_LOADER_NAME 0x00000200
/* Is there a APM table? */
#define MULTIBOOT_INFO_APM_TABLE 0x00000400
/* Is there video information? */
#define MULTIBOOT_INFO_VBE_INFO 0x00000800
#define MULTIBOOT_INFO_FRAMEBUFFER_INFO 0x00001000
#ifndef ASM_FILE
typedef unsigned char multiboot_uint8_t;
typedef unsigned short multiboot_uint16_t;
typedef unsigned int multiboot_uint32_t;
typedef unsigned long long multiboot_uint64_t;
struct multiboot_header {
/* Must be MULTIBOOT_MAGIC - see above. */
multiboot_uint32_t magic;
/* Feature flags. */
multiboot_uint32_t flags;
/* The above fields plus this one must equal 0 mod 2^32. */
multiboot_uint32_t checksum;
/* These are only valid if MULTIBOOT_AOUT_KLUDGE is set. */
multiboot_uint32_t header_addr;
multiboot_uint32_t load_addr;
multiboot_uint32_t load_end_addr;
multiboot_uint32_t bss_end_addr;
multiboot_uint32_t entry_addr;
/* These are only valid if MULTIBOOT_VIDEO_MODE is set. */
multiboot_uint32_t mode_type;
multiboot_uint32_t width;
multiboot_uint32_t height;
multiboot_uint32_t depth;
};
/* The symbol table for a.out. */
struct multiboot_aout_symbol_table {
multiboot_uint32_t tabsize;
multiboot_uint32_t strsize;
multiboot_uint32_t addr;
multiboot_uint32_t reserved;
};
typedef struct multiboot_aout_symbol_table multiboot_aout_symbol_table_t;
/* The section header table for ELF. */
struct multiboot_elf_section_header_table {
multiboot_uint32_t num;
multiboot_uint32_t size;
multiboot_uint32_t addr;
multiboot_uint32_t shndx;
};
typedef struct multiboot_elf_section_header_table multiboot_elf_section_header_table_t;
struct multiboot_info {
/* Multiboot info version number */
multiboot_uint32_t flags;
/* Available memory from BIOS */
multiboot_uint32_t mem_lower;
multiboot_uint32_t mem_upper;
/* "root" partition */
multiboot_uint32_t boot_device;
/* Kernel command line */
multiboot_uint32_t cmdline;
/* Boot-Module list */
multiboot_uint32_t mods_count;
multiboot_uint32_t mods_addr;
union {
multiboot_aout_symbol_table_t aout_sym;
multiboot_elf_section_header_table_t elf_sec;
} u;
/* Memory Mapping buffer */
multiboot_uint32_t mmap_length;
multiboot_uint32_t mmap_addr;
/* Drive Info buffer */
multiboot_uint32_t drives_length;
multiboot_uint32_t drives_addr;
/* ROM configuration table */
multiboot_uint32_t config_table;
/* Boot Loader Name */
multiboot_uint32_t boot_loader_name;
/* APM table */
multiboot_uint32_t apm_table;
/* Video */
multiboot_uint32_t vbe_control_info;
multiboot_uint32_t vbe_mode_info;
multiboot_uint16_t vbe_mode;
multiboot_uint16_t vbe_interface_seg;
multiboot_uint16_t vbe_interface_off;
multiboot_uint16_t vbe_interface_len;
multiboot_uint64_t framebuffer_addr;
multiboot_uint32_t framebuffer_pitch;
multiboot_uint32_t framebuffer_width;
multiboot_uint32_t framebuffer_height;
multiboot_uint8_t framebuffer_bpp;
#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0
#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1
#define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT 2
multiboot_uint8_t framebuffer_type;
union {
struct {
multiboot_uint32_t framebuffer_palette_addr;
multiboot_uint16_t framebuffer_palette_num_colors;
};
struct {
multiboot_uint8_t framebuffer_red_field_position;
multiboot_uint8_t framebuffer_red_mask_size;
multiboot_uint8_t framebuffer_green_field_position;
multiboot_uint8_t framebuffer_green_mask_size;
multiboot_uint8_t framebuffer_blue_field_position;
multiboot_uint8_t framebuffer_blue_mask_size;
};
};
};
typedef struct multiboot_info multiboot_info_t;
struct multiboot_color {
multiboot_uint8_t red;
multiboot_uint8_t green;
multiboot_uint8_t blue;
};
struct multiboot_mmap_entry {
multiboot_uint32_t size;
multiboot_uint64_t addr;
multiboot_uint64_t len;
#define MULTIBOOT_MEMORY_AVAILABLE 1
#define MULTIBOOT_MEMORY_RESERVED 2
#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3
#define MULTIBOOT_MEMORY_NVS 4
#define MULTIBOOT_MEMORY_BADRAM 5
multiboot_uint32_t type;
} __attribute__((packed));
typedef struct multiboot_mmap_entry multiboot_memory_map_t;
struct multiboot_mod_list {
/* the memory used goes from bytes mod_start to mod_end-1 inclusive */
multiboot_uint32_t mod_start;
multiboot_uint32_t mod_end;
/* Module command line */
multiboot_uint32_t cmdline;
/* padding to take it to 16 bytes (must be zero) */
multiboot_uint32_t pad;
};
typedef struct multiboot_mod_list multiboot_module_t;
/* APM BIOS info. */
struct multiboot_apm_info {
multiboot_uint16_t version;
multiboot_uint16_t cseg;
multiboot_uint32_t offset;
multiboot_uint16_t cseg_16;
multiboot_uint16_t dseg;
multiboot_uint16_t flags;
multiboot_uint16_t cseg_len;
multiboot_uint16_t cseg_16_len;
multiboot_uint16_t dseg_len;
};
#endif /* ! ASM_FILE */
#endif /* ! MULTIBOOT_HEADER */

22
kernel/types.h Normal file
View File

@@ -0,0 +1,22 @@
/*
* types.h
*
* Created on: Nov 1, 2018
* Author: rick
*/
#ifndef KERNEL_LIBC_TYPES_H_
#define KERNEL_LIBC_TYPES_H_
# define NULL (void *)0
typedef unsigned long long u64;
typedef long long s64;
typedef unsigned int u32;
typedef int s32;
typedef unsigned short u16;
typedef short s16;
typedef unsigned char u8;
typedef char s8;
#endif /* KERNEL_LIBC_TYPES_H_ */