Initial commit
This commit is contained in:
23
kernel/cpu/idt.c
Normal file
23
kernel/cpu/idt.c
Normal 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
35
kernel/cpu/idt.h
Normal 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
426
kernel/cpu/interrupt.S
Normal 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
144
kernel/cpu/isr.c
Normal 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
140
kernel/cpu/isr.h
Normal 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
26
kernel/cpu/timer.c
Normal 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
12
kernel/cpu/timer.h
Normal 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
70
kernel/drivers/keyboard.c
Normal 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
10
kernel/drivers/keyboard.h
Normal 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
33
kernel/drivers/ports.c
Normal 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
51
kernel/drivers/ports.h
Normal 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
56
kernel/drivers/serial.c
Normal 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
12
kernel/drivers/serial.h
Normal 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
122
kernel/drivers/vgascreen.c
Normal 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;
|
||||
}
|
||||
34
kernel/drivers/vgascreen.h
Normal file
34
kernel/drivers/vgascreen.h
Normal 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
46
kernel/kernel.c
Normal 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
37
kernel/kprint.c
Normal 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
16
kernel/kprint.h
Normal 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
40
kernel/libc/libc.c
Normal 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
19
kernel/libc/libc.h
Normal 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
88
kernel/mem/mem.c
Normal 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
14
kernel/mem/mem.h
Normal 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
262
kernel/multiboot.h
Normal 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
22
kernel/types.h
Normal 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_ */
|
||||
Reference in New Issue
Block a user