dead@root
This commit is contained in:
commit
b739f2adc8
8
.gitignore
vendored
Normal file
8
.gitignore
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
*.o
|
||||||
|
*.bin
|
||||||
|
*.elf
|
||||||
|
*.img
|
||||||
|
isodir/
|
||||||
|
.vscode/
|
||||||
|
.idea/
|
||||||
|
*.iso
|
45
Makefile
Normal file
45
Makefile
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
CFLAGS = -ffreestanding -nostdlib -fno-builtin -fno-stack-protector -Wall -Wextra
|
||||||
|
LDFLAGS = -ffreestanding -nostdlib -lgcc
|
||||||
|
ASFLAGS =
|
||||||
|
CC = i686-elf-gcc
|
||||||
|
AS = i686-elf-as
|
||||||
|
LD = i686-elf-gcc
|
||||||
|
GRUB_FILE = grub-file
|
||||||
|
GRUB_MKRESCUE = grub-mkrescue
|
||||||
|
KERNEL = deados.bin
|
||||||
|
ISO = deados.iso
|
||||||
|
|
||||||
|
SOURCES_C = kernel.c tty.c idt.c timer.c io.c vga.c gdt.c sys.c irq.c isr.c keyboard.c shell.c string.c user_space.c syscall.c
|
||||||
|
SOURCES_ASM = boot.s idt_load.s gdt_flush.s pit_handler.s irq_e.s isr_e.s
|
||||||
|
OBJECTS = $(SOURCES_ASM:.s=.o) $(SOURCES_C:.c=.o)
|
||||||
|
|
||||||
|
ISO_DIR = isodir
|
||||||
|
GRUB_DIR = $(ISO_DIR)/boot/grub
|
||||||
|
|
||||||
|
.PHONY: all clean iso
|
||||||
|
|
||||||
|
all: $(ISO)
|
||||||
|
|
||||||
|
$(KERNEL): $(OBJECTS) linker.ld
|
||||||
|
$(LD) -T linker.ld -o $(KERNEL) $(OBJECTS) $(LDFLAGS)
|
||||||
|
|
||||||
|
%.o: %.c
|
||||||
|
$(CC) $(CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
%.o: %.s
|
||||||
|
$(AS) $(ASFLAGS) $< -o $@
|
||||||
|
|
||||||
|
iso: $(ISO)
|
||||||
|
|
||||||
|
$(ISO): $(KERNEL) grub.cfg
|
||||||
|
mkdir -p $(GRUB_DIR)
|
||||||
|
cp $(KERNEL) $(ISO_DIR)/boot/$(KERNEL)
|
||||||
|
cp grub.cfg $(GRUB_DIR)/grub.cfg
|
||||||
|
$(GRUB_MKRESCUE) -o $(ISO) $(ISO_DIR)
|
||||||
|
|
||||||
|
check-multiboot: $(KERNEL)
|
||||||
|
$(GRUB_FILE) --is-x86-multiboot $(KERNEL) && echo "multiboot confirmed" || echo "the file is not multiboot"
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(OBJECTS) $(KERNEL) $(ISO)
|
||||||
|
rm -rf $(ISO_DIR)
|
35
boot.s
Normal file
35
boot.s
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
.set ALIGN, 1<<0
|
||||||
|
.set MEMINFO, 1<<1
|
||||||
|
.set FLAGS, ALIGN | MEMINFO
|
||||||
|
.set MAGIC, 0x1BADB002 /* multiboot 1 */
|
||||||
|
.set CHECKSUM, -(MAGIC + FLAGS)
|
||||||
|
|
||||||
|
.section .multiboot
|
||||||
|
.align 4
|
||||||
|
.long MAGIC
|
||||||
|
.long FLAGS
|
||||||
|
.long CHECKSUM
|
||||||
|
|
||||||
|
.section .bss
|
||||||
|
.align 16
|
||||||
|
|
||||||
|
stack_bottom:
|
||||||
|
.skip 1024 * 32 # 32 KB
|
||||||
|
|
||||||
|
stack_top:
|
||||||
|
.section .text
|
||||||
|
.global _start
|
||||||
|
.type _start, @function
|
||||||
|
_start:
|
||||||
|
cli
|
||||||
|
mov $stack_top, %esp
|
||||||
|
|
||||||
|
call kernel_main
|
||||||
|
|
||||||
|
hlt
|
||||||
|
jmp 1
|
||||||
|
1:
|
||||||
|
jmp 1
|
||||||
|
|
||||||
|
|
||||||
|
.size _start, . - _start
|
18
build.sh
Executable file
18
build.sh
Executable file
@ -0,0 +1,18 @@
|
|||||||
|
set -ex
|
||||||
|
|
||||||
|
i686-elf-as boot.s -o boot.o
|
||||||
|
i686-elf-as idt_load.s -o idt_load.o
|
||||||
|
i686-elf-gcc -c kernel.c -o kernel.o -std=gnu99 -ffreestanding -O2 -Wall -Wextra
|
||||||
|
i686-elf-gcc -T linker.ld -o myos.bin -ffreestanding -O2 -nostdlib boot.o kernel.o idt_load.o -lgcc
|
||||||
|
|
||||||
|
if grub-file --is-x86-multiboot myos.bin; then
|
||||||
|
echo multiboot confirmed
|
||||||
|
else
|
||||||
|
echo the file is not multiboot
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
mkdir -p isodir/boot/grub
|
||||||
|
cp myos.bin isodir/boot/myos.bin
|
||||||
|
cp grub.cfg isodir/boot/grub/grub.cfg
|
||||||
|
grub-mkrescue -o myos.iso isodir
|
29
gdt.c
Normal file
29
gdt.c
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#include "gdt.h"
|
||||||
|
|
||||||
|
struct gdt_entry gdt[3];
|
||||||
|
struct gdt_ptr gdtp;
|
||||||
|
|
||||||
|
extern void gdt_flush(uint32_t);
|
||||||
|
|
||||||
|
void gdt_set_gate(int num, uint32_t base, uint32_t limit, uint8_t access, uint8_t gran) {
|
||||||
|
gdt[num].base_low = (base & 0xFFFF);
|
||||||
|
gdt[num].base_middle = (base >> 16) & 0xFF;
|
||||||
|
gdt[num].base_high = (base >> 24) & 0xFF;
|
||||||
|
|
||||||
|
gdt[num].limit_low = (limit & 0xFFFF);
|
||||||
|
gdt[num].granularity = (limit >> 16) & 0x0F;
|
||||||
|
|
||||||
|
gdt[num].granularity |= gran & 0xF0;
|
||||||
|
gdt[num].access = access;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gdt_install() {
|
||||||
|
gdtp.limit = (sizeof(struct gdt_entry) * 3) - 1;
|
||||||
|
gdtp.base = (uint32_t)&gdt;
|
||||||
|
|
||||||
|
gdt_set_gate(0, 0, 0, 0, 0); // Null segment
|
||||||
|
gdt_set_gate(1, 0, 0xFFFFFFFF, 0x9A, 0xCF); // Code segment
|
||||||
|
gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF); // Data segment
|
||||||
|
|
||||||
|
gdt_flush((uint32_t)&gdtp);
|
||||||
|
}
|
26
gdt.h
Normal file
26
gdt.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#ifndef GDT_H
|
||||||
|
#define GDT_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
struct gdt_entry {
|
||||||
|
uint16_t limit_low;
|
||||||
|
uint16_t base_low;
|
||||||
|
uint8_t base_middle;
|
||||||
|
uint8_t access;
|
||||||
|
uint8_t granularity;
|
||||||
|
uint8_t base_high;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct gdt_ptr {
|
||||||
|
uint16_t limit;
|
||||||
|
uint32_t base;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
extern struct gdt_entry gdt[3];
|
||||||
|
extern struct gdt_ptr gdtp;
|
||||||
|
|
||||||
|
void gdt_set_gate(int num, uint32_t base, uint32_t limit, uint8_t access, uint8_t gran);
|
||||||
|
void gdt_install();
|
||||||
|
|
||||||
|
#endif
|
19
gdt_flush.s
Normal file
19
gdt_flush.s
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
.global gdt_flush
|
||||||
|
|
||||||
|
gdt_flush:
|
||||||
|
cli
|
||||||
|
|
||||||
|
mov 4(%esp), %eax
|
||||||
|
lgdt (%eax)
|
||||||
|
|
||||||
|
mov $0x10, %ax
|
||||||
|
mov %ax, %ds
|
||||||
|
mov %ax, %es
|
||||||
|
mov %ax, %fs
|
||||||
|
mov %ax, %gs
|
||||||
|
mov %ax, %ss
|
||||||
|
|
||||||
|
jmp $0x08, $.flush
|
||||||
|
|
||||||
|
.flush:
|
||||||
|
ret
|
55
idt.c
Normal file
55
idt.c
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
#include "idt.h"
|
||||||
|
#include "io.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define IDT_ENTRIES 256
|
||||||
|
|
||||||
|
struct idt_entry {
|
||||||
|
uint16_t base_lo;
|
||||||
|
uint16_t sel;
|
||||||
|
uint8_t always0;
|
||||||
|
uint8_t flags;
|
||||||
|
uint16_t base_hi;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct idt_ptr {
|
||||||
|
uint16_t limit;
|
||||||
|
uint32_t base;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct idt_entry idt[IDT_ENTRIES];
|
||||||
|
struct idt_ptr idtp;
|
||||||
|
|
||||||
|
void idt_set_gate(uint8_t num, uint32_t base, uint16_t sel, uint8_t flags) {
|
||||||
|
idt[num].base_lo = base & 0xFFFF;
|
||||||
|
idt[num].base_hi = (base >> 16) & 0xFFFF;
|
||||||
|
idt[num].sel = sel;
|
||||||
|
idt[num].always0 = 0;
|
||||||
|
idt[num].flags = flags | 0x60;
|
||||||
|
}
|
||||||
|
|
||||||
|
void idt_install() {
|
||||||
|
idtp.limit = (sizeof(struct idt_entry) * IDT_ENTRIES) - 1;
|
||||||
|
idtp.base = (uint32_t)&idt;
|
||||||
|
idt_load();
|
||||||
|
}
|
||||||
|
|
||||||
|
void pic_remap(int offset1, int offset2) {
|
||||||
|
unsigned char a1, a2;
|
||||||
|
|
||||||
|
a1 = inb(0x21);
|
||||||
|
a2 = inb(0xA1);
|
||||||
|
|
||||||
|
outb(0x20, 0x11);
|
||||||
|
outb(0xA0, 0x11);
|
||||||
|
outb(0x21, offset1);
|
||||||
|
outb(0xA1, offset2);
|
||||||
|
outb(0x21, 0x04);
|
||||||
|
outb(0xA1, 0x02);
|
||||||
|
|
||||||
|
outb(0x21, 0x01);
|
||||||
|
outb(0xA1, 0x01);
|
||||||
|
|
||||||
|
outb(0x21, a1);
|
||||||
|
outb(0xA1, a2);
|
||||||
|
}
|
11
idt.h
Normal file
11
idt.h
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#ifndef IDT_H
|
||||||
|
#define IDT_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
extern void idt_load();
|
||||||
|
|
||||||
|
void idt_install();
|
||||||
|
void idt_set_gate(uint8_t num, uint32_t base, uint16_t sel, uint8_t flags);
|
||||||
|
|
||||||
|
#endif
|
5
idt_load.s
Normal file
5
idt_load.s
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
.section .text
|
||||||
|
.global idt_load
|
||||||
|
idt_load:
|
||||||
|
lidt [idtp]
|
||||||
|
ret
|
48
interrupts.h
Normal file
48
interrupts.h
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
#ifndef INTERUPTS_H
|
||||||
|
#define INTERUPTS_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
typedef struct stack_t Stack;
|
||||||
|
struct stack_t
|
||||||
|
{
|
||||||
|
/* Pushed the segs last */
|
||||||
|
uint32_t gs, fs, es, ds;
|
||||||
|
/* Pushed by 'pusha' */
|
||||||
|
uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax;
|
||||||
|
/* Our 'push #' and ecodes do this */
|
||||||
|
uint32_t id, err_code;
|
||||||
|
/* Pushed by the processor automatically */
|
||||||
|
uint32_t eip, cs, eflags, useresp, ss;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define NB_ISR_ROUTINES 256
|
||||||
|
|
||||||
|
void isr_install_handler(uint8_t isr, void (*handler)(Stack *registers));
|
||||||
|
void isr_uninstall_handler(uint8_t isr);
|
||||||
|
void isr_call_handler(Stack *registers);
|
||||||
|
void isr_install(void);
|
||||||
|
|
||||||
|
#define NB_IRQ_ROUTINES 16
|
||||||
|
|
||||||
|
#define PIC1 0x20 /* master PIC */
|
||||||
|
#define PIC2 0xA0 /* slave PIC */
|
||||||
|
#define PIC1_CMD PIC1
|
||||||
|
#define PIC1_DATA (PIC1 + 1)
|
||||||
|
#define PIC2_CMD PIC2
|
||||||
|
#define PIC2_DATA (PIC2 + 1)
|
||||||
|
#define PIC1_OFFSET 0x20
|
||||||
|
#define PIC2_OFFSET 0x28
|
||||||
|
|
||||||
|
#define PIC_EOI 0x20
|
||||||
|
|
||||||
|
#define ICW1_ICW4 0x01
|
||||||
|
#define ICW1_INIT 0x10
|
||||||
|
#define ICW4_8086 0x01
|
||||||
|
|
||||||
|
void irq_install_handler(uint8_t irq, void (*handler)(Stack *registers));
|
||||||
|
void irq_uninstall_handler(uint8_t irq);
|
||||||
|
void irq_call_handler(Stack *registers);
|
||||||
|
void irq_install(void);
|
||||||
|
|
||||||
|
#endif
|
18
io.c
Normal file
18
io.c
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#include "io.h"
|
||||||
|
|
||||||
|
void outb(uint16_t port, uint8_t val) {
|
||||||
|
asm volatile ("outb %0, %1" : : "a"(val), "Nd"(port));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t inb(uint16_t port) {
|
||||||
|
uint8_t ret;
|
||||||
|
asm volatile ("inb %1, %0" : "=a"(ret) : "Nd"(port));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void io_wait(void)
|
||||||
|
{
|
||||||
|
asm volatile ( "jmp 1f\n\t"
|
||||||
|
"1:jmp 2f\n\t"
|
||||||
|
"2:" );
|
||||||
|
}
|
10
io.h
Normal file
10
io.h
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#ifndef IO_H
|
||||||
|
#define IO_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
void outb(uint16_t port, uint8_t val);
|
||||||
|
uint8_t inb(uint16_t port);
|
||||||
|
void io_wait(void);
|
||||||
|
|
||||||
|
#endif
|
99
irq.c
Normal file
99
irq.c
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "interrupts.h"
|
||||||
|
#include "io.h"
|
||||||
|
#include "sys.h"
|
||||||
|
#include "idt.h"
|
||||||
|
|
||||||
|
extern void irq0(void);
|
||||||
|
extern void irq1(void);
|
||||||
|
extern void irq2(void);
|
||||||
|
extern void irq3(void);
|
||||||
|
extern void irq4(void);
|
||||||
|
extern void irq5(void);
|
||||||
|
extern void irq6(void);
|
||||||
|
extern void irq7(void);
|
||||||
|
extern void irq8(void);
|
||||||
|
extern void irq9(void);
|
||||||
|
extern void irq10(void);
|
||||||
|
extern void irq11(void);
|
||||||
|
extern void irq12(void);
|
||||||
|
extern void irq13(void);
|
||||||
|
extern void irq14(void);
|
||||||
|
extern void irq15(void);
|
||||||
|
|
||||||
|
void *irq_routines[NB_IRQ_ROUTINES] = {0};
|
||||||
|
|
||||||
|
void irq_install_handler(uint8_t irq, void (*handler)(Stack *registers))
|
||||||
|
{
|
||||||
|
irq_routines[irq] = handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
void irq_uninstall_handler(uint8_t irq)
|
||||||
|
{
|
||||||
|
irq_routines[irq] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void irq_call_handler(Stack *registers)
|
||||||
|
{
|
||||||
|
void (*handler)(Stack *registers);
|
||||||
|
handler = irq_routines[registers->id - 32];
|
||||||
|
if (handler)
|
||||||
|
handler(registers);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void irq_remap(void)
|
||||||
|
{
|
||||||
|
outb(PIC1_CMD, ICW1_INIT | ICW1_ICW4);
|
||||||
|
io_wait();
|
||||||
|
outb(PIC2_CMD, ICW1_INIT | ICW1_ICW4);
|
||||||
|
io_wait();
|
||||||
|
outb(PIC1_DATA, PIC1_OFFSET);
|
||||||
|
io_wait();
|
||||||
|
outb(PIC2_DATA, PIC2_OFFSET);
|
||||||
|
io_wait();
|
||||||
|
outb(PIC1_DATA, 0x04);
|
||||||
|
io_wait();
|
||||||
|
outb(PIC2_DATA, 0x02);
|
||||||
|
io_wait();
|
||||||
|
outb(PIC1_DATA, ICW4_8086);
|
||||||
|
io_wait();
|
||||||
|
outb(PIC2_DATA, ICW4_8086);
|
||||||
|
io_wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
void irq_install(void)
|
||||||
|
{
|
||||||
|
irq_remap();
|
||||||
|
|
||||||
|
idt_set_gate(32, (uint32_t)irq0, 0x08, 0x8E);
|
||||||
|
idt_set_gate(33, (uint32_t)irq1, 0x08, 0x8E);
|
||||||
|
idt_set_gate(34, (uint32_t)irq2, 0x08, 0x8E);
|
||||||
|
idt_set_gate(35, (uint32_t)irq3, 0x08, 0x8E);
|
||||||
|
idt_set_gate(36, (uint32_t)irq4, 0x08, 0x8E);
|
||||||
|
idt_set_gate(37, (uint32_t)irq5, 0x08, 0x8E);
|
||||||
|
idt_set_gate(38, (uint32_t)irq6, 0x08, 0x8E);
|
||||||
|
idt_set_gate(39, (uint32_t)irq7, 0x08, 0x8E);
|
||||||
|
idt_set_gate(40, (uint32_t)irq8, 0x08, 0x8E);
|
||||||
|
idt_set_gate(41, (uint32_t)irq9, 0x08, 0x8E);
|
||||||
|
idt_set_gate(42, (uint32_t)irq10, 0x08, 0x8E);
|
||||||
|
idt_set_gate(43, (uint32_t)irq11, 0x08, 0x8E);
|
||||||
|
idt_set_gate(44, (uint32_t)irq12, 0x08, 0x8E);
|
||||||
|
idt_set_gate(45, (uint32_t)irq13, 0x08, 0x8E);
|
||||||
|
idt_set_gate(46, (uint32_t)irq14, 0x08, 0x8E);
|
||||||
|
idt_set_gate(47, (uint32_t)irq15, 0x08, 0x8E);
|
||||||
|
|
||||||
|
sys_enable_interrupts();
|
||||||
|
}
|
||||||
|
|
||||||
|
void irq_handler(Stack *registers)
|
||||||
|
{
|
||||||
|
irq_call_handler(registers);
|
||||||
|
|
||||||
|
if (registers->id >= 40)
|
||||||
|
{
|
||||||
|
outb(PIC2_CMD, PIC_EOI);
|
||||||
|
}
|
||||||
|
|
||||||
|
outb(PIC1_CMD, PIC_EOI);
|
||||||
|
}
|
59
irq_e.s
Normal file
59
irq_e.s
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
.section .text
|
||||||
|
.align 4
|
||||||
|
|
||||||
|
.macro IRQ index entry
|
||||||
|
.global irq\index
|
||||||
|
.type irq\index, @function
|
||||||
|
irq\index:
|
||||||
|
cli
|
||||||
|
push $0x00
|
||||||
|
push $\entry
|
||||||
|
jmp irq_common_stub
|
||||||
|
.endm
|
||||||
|
|
||||||
|
IRQ 0, 32
|
||||||
|
IRQ 1, 33
|
||||||
|
IRQ 2, 34
|
||||||
|
IRQ 3, 35
|
||||||
|
IRQ 4, 36
|
||||||
|
IRQ 5, 37
|
||||||
|
IRQ 6, 38
|
||||||
|
IRQ 7, 39
|
||||||
|
IRQ 8, 40
|
||||||
|
IRQ 9, 41
|
||||||
|
IRQ 10, 42
|
||||||
|
IRQ 11, 43
|
||||||
|
IRQ 12, 44
|
||||||
|
IRQ 13, 45
|
||||||
|
IRQ 14, 46
|
||||||
|
IRQ 15, 47
|
||||||
|
|
||||||
|
irq_common_stub:
|
||||||
|
pusha
|
||||||
|
|
||||||
|
push %ds
|
||||||
|
push %es
|
||||||
|
push %fs
|
||||||
|
push %gs
|
||||||
|
|
||||||
|
mov $0x10, %ax
|
||||||
|
mov %ax, %ds
|
||||||
|
mov %ax, %es
|
||||||
|
mov %ax, %fs
|
||||||
|
mov %ax, %gs
|
||||||
|
|
||||||
|
mov %esp, %eax
|
||||||
|
push %eax
|
||||||
|
mov $irq_handler, %eax
|
||||||
|
|
||||||
|
call *%eax
|
||||||
|
pop %eax
|
||||||
|
|
||||||
|
pop %gs
|
||||||
|
pop %fs
|
||||||
|
pop %es
|
||||||
|
pop %ds
|
||||||
|
popa
|
||||||
|
|
||||||
|
add $8, %esp
|
||||||
|
iret
|
161
isr.c
Normal file
161
isr.c
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
#include "interrupts.h"
|
||||||
|
#include "io.h"
|
||||||
|
#include "sys.h"
|
||||||
|
#include "idt.h"
|
||||||
|
#include "tty.h"
|
||||||
|
|
||||||
|
extern void isr0(void);
|
||||||
|
extern void isr1(void);
|
||||||
|
extern void isr2(void);
|
||||||
|
extern void isr3(void);
|
||||||
|
extern void isr4(void);
|
||||||
|
extern void isr5(void);
|
||||||
|
extern void isr6(void);
|
||||||
|
extern void isr7(void);
|
||||||
|
extern void isr8(void);
|
||||||
|
extern void isr9(void);
|
||||||
|
extern void isr10(void);
|
||||||
|
extern void isr11(void);
|
||||||
|
extern void isr12(void);
|
||||||
|
extern void isr13(void);
|
||||||
|
extern void isr14(void);
|
||||||
|
extern void isr15(void);
|
||||||
|
extern void isr16(void);
|
||||||
|
extern void isr17(void);
|
||||||
|
extern void isr18(void);
|
||||||
|
extern void isr19(void);
|
||||||
|
extern void isr20(void);
|
||||||
|
extern void isr21(void);
|
||||||
|
extern void isr22(void);
|
||||||
|
extern void isr23(void);
|
||||||
|
extern void isr24(void);
|
||||||
|
extern void isr25(void);
|
||||||
|
extern void isr26(void);
|
||||||
|
extern void isr27(void);
|
||||||
|
extern void isr28(void);
|
||||||
|
extern void isr29(void);
|
||||||
|
extern void isr30(void);
|
||||||
|
extern void isr31(void);
|
||||||
|
extern void isr128(void);
|
||||||
|
|
||||||
|
void *isr_routines[NB_ISR_ROUTINES] = {0};
|
||||||
|
|
||||||
|
void isr_install_handler(uint8_t isr, void (*handler)(Stack *registers))
|
||||||
|
{
|
||||||
|
isr_routines[isr] = handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
void isr_uninstall_handler(uint8_t isr)
|
||||||
|
{
|
||||||
|
isr_routines[isr] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void isr_call_handler(Stack *registers)
|
||||||
|
{
|
||||||
|
void (*handler)(Stack *registers);
|
||||||
|
handler = isr_routines[registers->id];
|
||||||
|
if (handler)
|
||||||
|
handler(registers);
|
||||||
|
}
|
||||||
|
|
||||||
|
void isr_install(void)
|
||||||
|
{
|
||||||
|
idt_set_gate(0, (uint32_t)isr0, 0x08, 0x8E);
|
||||||
|
idt_set_gate(1, (uint32_t)isr1, 0x08, 0x8E);
|
||||||
|
idt_set_gate(2, (uint32_t)isr2, 0x08, 0x8E);
|
||||||
|
idt_set_gate(3, (uint32_t)isr3, 0x08, 0x8E);
|
||||||
|
idt_set_gate(4, (uint32_t)isr4, 0x08, 0x8E);
|
||||||
|
idt_set_gate(5, (uint32_t)isr5, 0x08, 0x8E);
|
||||||
|
idt_set_gate(6, (uint32_t)isr6, 0x08, 0x8E);
|
||||||
|
idt_set_gate(7, (uint32_t)isr7, 0x08, 0x8E);
|
||||||
|
|
||||||
|
idt_set_gate(8, (uint32_t)isr8, 0x08, 0x8E);
|
||||||
|
idt_set_gate(9, (uint32_t)isr9, 0x08, 0x8E);
|
||||||
|
idt_set_gate(10, (uint32_t)isr10, 0x08, 0x8E);
|
||||||
|
idt_set_gate(11, (uint32_t)isr11, 0x08, 0x8E);
|
||||||
|
idt_set_gate(12, (uint32_t)isr12, 0x08, 0x8E);
|
||||||
|
idt_set_gate(13, (uint32_t)isr13, 0x08, 0x8E);
|
||||||
|
idt_set_gate(14, (uint32_t)isr14, 0x08, 0x8E);
|
||||||
|
idt_set_gate(15, (uint32_t)isr15, 0x08, 0x8E);
|
||||||
|
|
||||||
|
idt_set_gate(16, (uint32_t)isr16, 0x08, 0x8E);
|
||||||
|
idt_set_gate(17, (uint32_t)isr17, 0x08, 0x8E);
|
||||||
|
idt_set_gate(18, (uint32_t)isr18, 0x08, 0x8E);
|
||||||
|
idt_set_gate(19, (uint32_t)isr19, 0x08, 0x8E);
|
||||||
|
idt_set_gate(20, (uint32_t)isr20, 0x08, 0x8E);
|
||||||
|
idt_set_gate(21, (uint32_t)isr21, 0x08, 0x8E);
|
||||||
|
idt_set_gate(22, (uint32_t)isr22, 0x08, 0x8E);
|
||||||
|
idt_set_gate(23, (uint32_t)isr23, 0x08, 0x8E);
|
||||||
|
|
||||||
|
idt_set_gate(24, (uint32_t)isr24, 0x08, 0x8E);
|
||||||
|
idt_set_gate(25, (uint32_t)isr25, 0x08, 0x8E);
|
||||||
|
idt_set_gate(26, (uint32_t)isr26, 0x08, 0x8E);
|
||||||
|
idt_set_gate(27, (uint32_t)isr27, 0x08, 0x8E);
|
||||||
|
idt_set_gate(28, (uint32_t)isr28, 0x08, 0x8E);
|
||||||
|
idt_set_gate(29, (uint32_t)isr29, 0x08, 0x8E);
|
||||||
|
idt_set_gate(30, (uint32_t)isr30, 0x08, 0x8E);
|
||||||
|
idt_set_gate(31, (uint32_t)isr31, 0x08, 0x8E);
|
||||||
|
|
||||||
|
idt_set_gate(128, (uint32_t)isr128, 0x08, 0x8E);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const 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 fault_handler(Stack *registers)
|
||||||
|
{
|
||||||
|
if (registers->id == 128)
|
||||||
|
isr_call_handler(registers);
|
||||||
|
|
||||||
|
if (registers->id < 32)
|
||||||
|
{
|
||||||
|
terminal_printc("Exception. System Halted!\n");
|
||||||
|
|
||||||
|
const char *message = exception_messages[registers->id];
|
||||||
|
while (*message)
|
||||||
|
{
|
||||||
|
terminal_putchar(*message);
|
||||||
|
message++;
|
||||||
|
}
|
||||||
|
|
||||||
|
isr_call_handler(registers);
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
sys_halt();
|
||||||
|
}
|
||||||
|
}
|
85
isr_e.s
Normal file
85
isr_e.s
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
.section .text
|
||||||
|
.align 4
|
||||||
|
|
||||||
|
.macro ISR_NO_ERR index
|
||||||
|
.global isr\index
|
||||||
|
isr\index:
|
||||||
|
cli
|
||||||
|
push $0
|
||||||
|
push $\index
|
||||||
|
jmp isr_common_stub
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro ISR_ERR index
|
||||||
|
.global isr\index
|
||||||
|
isr\index:
|
||||||
|
cli
|
||||||
|
push $\index
|
||||||
|
jmp isr_common_stub
|
||||||
|
.endm
|
||||||
|
|
||||||
|
|
||||||
|
ISR_NO_ERR 0 # Division By Zero Exception
|
||||||
|
ISR_NO_ERR 1 # Debug Exception
|
||||||
|
ISR_NO_ERR 2 # Non Maskable Interrupt Exception
|
||||||
|
ISR_NO_ERR 3 # Breakpoint Exception
|
||||||
|
ISR_NO_ERR 4 # Into Detected Overflow Exception
|
||||||
|
ISR_NO_ERR 5 # Out of Bounds Exception
|
||||||
|
ISR_NO_ERR 6 # Invalid Opcode Exception
|
||||||
|
ISR_NO_ERR 7 # No Coprocessor Exception
|
||||||
|
ISR_ERR 8 # Double Fault Exception
|
||||||
|
ISR_NO_ERR 9 # Coprocessor Segment Overrun Exception
|
||||||
|
ISR_ERR 10 # Bad TSS Exception
|
||||||
|
ISR_ERR 11 # Segment Not Present Exception
|
||||||
|
ISR_ERR 12 # Stack Fault Exception
|
||||||
|
ISR_ERR 13 # General Protection Fault Exception
|
||||||
|
ISR_ERR 14 # Page Fault Exception
|
||||||
|
ISR_NO_ERR 15 # Unknown Interrupt Exception
|
||||||
|
ISR_NO_ERR 16 # Coprocessor Fault Exception
|
||||||
|
ISR_NO_ERR 17 # Alignment Check Exception
|
||||||
|
ISR_NO_ERR 18 # Machine Check Exception
|
||||||
|
|
||||||
|
ISR_NO_ERR 19 # Other
|
||||||
|
ISR_NO_ERR 20
|
||||||
|
ISR_NO_ERR 21
|
||||||
|
ISR_NO_ERR 22
|
||||||
|
ISR_NO_ERR 23
|
||||||
|
ISR_NO_ERR 24
|
||||||
|
ISR_NO_ERR 25
|
||||||
|
ISR_NO_ERR 26
|
||||||
|
ISR_NO_ERR 27
|
||||||
|
ISR_NO_ERR 28
|
||||||
|
ISR_NO_ERR 29
|
||||||
|
ISR_NO_ERR 30
|
||||||
|
ISR_NO_ERR 31
|
||||||
|
ISR_NO_ERR 128 # Syscal
|
||||||
|
|
||||||
|
|
||||||
|
isr_common_stub:
|
||||||
|
pusha
|
||||||
|
push %ds
|
||||||
|
push %es
|
||||||
|
push %fs
|
||||||
|
push %gs
|
||||||
|
|
||||||
|
mov $0x10, %ax
|
||||||
|
mov %ax, %ds
|
||||||
|
mov %ax, %es
|
||||||
|
mov %ax, %fs
|
||||||
|
mov %ax, %gs
|
||||||
|
|
||||||
|
mov %esp, %eax
|
||||||
|
push %eax
|
||||||
|
mov $fault_handler, %eax
|
||||||
|
|
||||||
|
call *%eax
|
||||||
|
pop %eax
|
||||||
|
|
||||||
|
pop %gs
|
||||||
|
pop %fs
|
||||||
|
pop %es
|
||||||
|
pop %ds
|
||||||
|
popa
|
||||||
|
|
||||||
|
add $8, %esp
|
||||||
|
iret
|
45
kernel.c
Normal file
45
kernel.c
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "tty.h"
|
||||||
|
#include "gdt.h"
|
||||||
|
#include "idt.h"
|
||||||
|
#include "timer.h"
|
||||||
|
#include "sys.h"
|
||||||
|
#include "interrupts.h"
|
||||||
|
#include "keyboard.h"
|
||||||
|
#include "shell.h"
|
||||||
|
#include "user_space.h"
|
||||||
|
#include "syscall.h"
|
||||||
|
|
||||||
|
void kernel_main(void)
|
||||||
|
{
|
||||||
|
terminal_initialize();
|
||||||
|
gdt_install();
|
||||||
|
|
||||||
|
idt_install();
|
||||||
|
|
||||||
|
isr_install();
|
||||||
|
irq_install();
|
||||||
|
|
||||||
|
timer_install();
|
||||||
|
|
||||||
|
keyboard_install();
|
||||||
|
|
||||||
|
sys_enable_interrupts();
|
||||||
|
|
||||||
|
terminal_printc("Hello, &ekernel &7World!\n&5Magenta String Example\nThis is a &4red string&7.\n");
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
terminal_printc("&cDead &7");
|
||||||
|
terminal_putchar('0' + (i / 10));
|
||||||
|
terminal_putchar('0' + (i % 10));
|
||||||
|
terminal_printc("\n");
|
||||||
|
delay(500);
|
||||||
|
}
|
||||||
|
// syscall_init();
|
||||||
|
|
||||||
|
// enter_user_space();
|
||||||
|
|
||||||
|
shell_init();
|
||||||
|
}
|
202
keyboard.c
Normal file
202
keyboard.c
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "interrupts.h"
|
||||||
|
#include "io.h"
|
||||||
|
#include "keyboard.h"
|
||||||
|
|
||||||
|
unsigned char us_layout[] = {
|
||||||
|
/* SHIFT CTRL ALT */
|
||||||
|
0x1B, 0x1B, 0x1B, 0x1B, /* esc (0x01) */
|
||||||
|
'1', '!', '1', '1',
|
||||||
|
'2', '@', '2', '2',
|
||||||
|
'3', '#', '3', '3',
|
||||||
|
'4', '$', '4', '4',
|
||||||
|
'5', '%', '5', '5',
|
||||||
|
'6', '^', '6', '6',
|
||||||
|
'7', '&', '7', '7',
|
||||||
|
'8', '*', '8', '8',
|
||||||
|
'9', '(', '9', '9',
|
||||||
|
'0', ')', '0', '0',
|
||||||
|
'-', '_', '-', '-',
|
||||||
|
'=', '+', '=', '=',
|
||||||
|
0x08, 0x08, 0x7F, 0x08, /* backspace */
|
||||||
|
0x09, 0x09, 0x09, 0x09, /* tab */
|
||||||
|
'q', 'Q', 'q', 'q',
|
||||||
|
'w', 'W', 'w', 'w',
|
||||||
|
'e', 'E', 'e', 'e',
|
||||||
|
'r', 'R', 'r', 'r',
|
||||||
|
't', 'T', 't', 't',
|
||||||
|
'y', 'Y', 'y', 'y',
|
||||||
|
'u', 'U', 'u', 'u',
|
||||||
|
'i', 'I', 'i', 'i',
|
||||||
|
'o', 'O', 'o', 'o',
|
||||||
|
'p', 'P', 'p', 'p',
|
||||||
|
'[', '{', '[', '[',
|
||||||
|
']', '}', ']', ']',
|
||||||
|
0x0A, 0x0A, 0x0A, 0x0A, /* enter */
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, /* ctrl */
|
||||||
|
'a', 'A', 'a', 'a',
|
||||||
|
's', 'S', 's', 's',
|
||||||
|
'd', 'D', 'd', 'd',
|
||||||
|
'f', 'F', 'f', 'f',
|
||||||
|
'g', 'G', 'g', 'g',
|
||||||
|
'h', 'H', 'h', 'h',
|
||||||
|
'j', 'J', 'j', 'j',
|
||||||
|
'k', 'K', 'k', 'k',
|
||||||
|
'l', 'L', 'l', 'l',
|
||||||
|
';', ':', ';', ';',
|
||||||
|
0x27, 0x22, 0x27, 0x27, /* '" */
|
||||||
|
'`', '~', '`', '`', /* `~ */
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, /* Lshift (0x2a) */
|
||||||
|
'\\', '|', '\\', '\\',
|
||||||
|
'z', 'Z', 'z', 'z',
|
||||||
|
'x', 'X', 'x', 'x',
|
||||||
|
'c', 'C', 'c', 'c',
|
||||||
|
'v', 'V', 'v', 'v',
|
||||||
|
'b', 'B', 'b', 'b',
|
||||||
|
'n', 'N', 'n', 'n',
|
||||||
|
'm', 'M', 'm', 'm',
|
||||||
|
0x2C, 0x3C, 0x2C, 0x2C, /* ,< */
|
||||||
|
0x2E, 0x3E, 0x2E, 0x2E, /* .> */
|
||||||
|
0x2F, 0x3F, 0x2F, 0x2F, /* /? */
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, /* Rshift (0x36) */
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, /* (0x37) */
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, /* (0x38) */
|
||||||
|
' ', ' ', ' ', ' ', /* space */
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, /* (0x3a) */
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, /* (0x3b) */
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, /* (0x3c) */
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, /* (0x3d) */
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, /* (0x3e) */
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, /* (0x3f) */
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, /* (0x40) */
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, /* (0x41) */
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, /* (0x42) */
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, /* (0x43) */
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, /* (0x44) */
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, /* (0x45) */
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, /* (0x46) */
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, /* (0x47) */
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, /* (0x48) */
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, /* (0x49) */
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, /* (0x4a) */
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, /* (0x4b) */
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, /* (0x4c) */
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, /* (0x4d) */
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, /* (0x4e) */
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, /* (0x4f) */
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, /* (0x50) */
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, /* (0x51) */
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, /* (0x52) */
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, /* (0x53) */
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, /* (0x54) */
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, /* (0x55) */
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, /* (0x56) */
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, /* (0x57) */
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, /* (0x58) */
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, /* (0x59) */
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, /* (0x5a) */
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, /* (0x5b) */
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, /* (0x5c) */
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, /* (0x5d) */
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, /* (0x5e) */
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, /* (0x5f) */
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, /* (0x60) */
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF /* (0x61) */
|
||||||
|
};
|
||||||
|
|
||||||
|
volatile unsigned char buffer[KEYBOARD_BUFFER_SIZE];
|
||||||
|
volatile size_t buffer_index;
|
||||||
|
volatile size_t read_index;
|
||||||
|
|
||||||
|
void keyboard_clear_buffer(void)
|
||||||
|
{
|
||||||
|
buffer_index = 0;
|
||||||
|
read_index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int keyboard_getchar(void)
|
||||||
|
{
|
||||||
|
while (read_index == buffer_index)
|
||||||
|
;
|
||||||
|
|
||||||
|
int c = (int)buffer[read_index];
|
||||||
|
++read_index;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char keyboard_getscancode(void)
|
||||||
|
{
|
||||||
|
uint8_t scancode;
|
||||||
|
uint16_t index;
|
||||||
|
static uint8_t offset = 0;
|
||||||
|
|
||||||
|
scancode = inb(KEYBOARD_DATA);
|
||||||
|
--scancode;
|
||||||
|
|
||||||
|
if (scancode < 0x80)
|
||||||
|
{
|
||||||
|
switch (scancode)
|
||||||
|
{
|
||||||
|
case LSHIFT:
|
||||||
|
offset = 1;
|
||||||
|
break;
|
||||||
|
case RSHIFT:
|
||||||
|
offset = 1;
|
||||||
|
break;
|
||||||
|
case CTRL:
|
||||||
|
offset = 2;
|
||||||
|
break;
|
||||||
|
case ALT:
|
||||||
|
offset = 3;
|
||||||
|
break;
|
||||||
|
/* Character */
|
||||||
|
default:
|
||||||
|
index = scancode * 4 + offset;
|
||||||
|
return us_layout[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
scancode -= 0x80;
|
||||||
|
switch (scancode)
|
||||||
|
{
|
||||||
|
case LSHIFT:
|
||||||
|
offset = 0;
|
||||||
|
break;
|
||||||
|
case RSHIFT:
|
||||||
|
offset = 0;
|
||||||
|
break;
|
||||||
|
case CTRL:
|
||||||
|
offset = 0;
|
||||||
|
break;
|
||||||
|
case ALT:
|
||||||
|
offset = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void keyboard_handler(Stack *registers)
|
||||||
|
{
|
||||||
|
(void)(registers);
|
||||||
|
|
||||||
|
unsigned char c = keyboard_getscancode();
|
||||||
|
|
||||||
|
if (c)
|
||||||
|
{
|
||||||
|
buffer[buffer_index] = c;
|
||||||
|
++buffer_index;
|
||||||
|
if (buffer_index == KEYBOARD_BUFFER_SIZE)
|
||||||
|
keyboard_clear_buffer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void keyboard_install(void)
|
||||||
|
{
|
||||||
|
keyboard_clear_buffer();
|
||||||
|
irq_install_handler(1, keyboard_handler);
|
||||||
|
}
|
18
keyboard.h
Normal file
18
keyboard.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#ifndef KEYBOARD_H
|
||||||
|
#define KEYBOARD_H
|
||||||
|
|
||||||
|
#define KEYBOARD_BUFFER_SIZE 256
|
||||||
|
|
||||||
|
#define KEYBOARD_DATA 0x60
|
||||||
|
|
||||||
|
#define LSHIFT 0x29
|
||||||
|
#define RSHIFT 0x35
|
||||||
|
#define CTRL 0x1C
|
||||||
|
#define ALT 0x37
|
||||||
|
|
||||||
|
void keyboard_clear_buffer(void);
|
||||||
|
int keyboard_getchar(void);
|
||||||
|
unsigned char keyboard_getscancode(void);
|
||||||
|
void keyboard_install(void);
|
||||||
|
|
||||||
|
#endif
|
24
linker.ld
Normal file
24
linker.ld
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
ENTRY(_start)
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
. = 1M;
|
||||||
|
|
||||||
|
.text ALIGN(4K) :
|
||||||
|
{
|
||||||
|
*(.multiboot)
|
||||||
|
*(.text)
|
||||||
|
*(.rodata)
|
||||||
|
}
|
||||||
|
|
||||||
|
.data ALIGN(4K) :
|
||||||
|
{
|
||||||
|
*(.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
.bss ALIGN(4K) :
|
||||||
|
{
|
||||||
|
*(.bss)
|
||||||
|
*(COMMON)
|
||||||
|
}
|
||||||
|
}
|
12
pit_handler.s
Normal file
12
pit_handler.s
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
.section .text
|
||||||
|
.global pit_handler_asm
|
||||||
|
|
||||||
|
pit_handler_asm:
|
||||||
|
push %eax # Save the registers used by the C handler
|
||||||
|
push %ecx
|
||||||
|
push %edx
|
||||||
|
call pit_handler # Call the C handler
|
||||||
|
pop %edx # Restore the registers in reverse order
|
||||||
|
pop %ecx
|
||||||
|
pop %eax
|
||||||
|
iret # Return from interrupt
|
113
shell.c
Normal file
113
shell.c
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
#include <stdbool.h>
|
||||||
|
#include "keyboard.h"
|
||||||
|
#include "shell.h"
|
||||||
|
#include "tty.h"
|
||||||
|
#include "string.h"
|
||||||
|
|
||||||
|
void shell_init(void)
|
||||||
|
{
|
||||||
|
char input_buffer[SHELL_BUFFER_SIZE + 1];
|
||||||
|
size_t i;
|
||||||
|
char c;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
terminal_printc("\n");
|
||||||
|
terminal_printc("&7dead@&croot&7: /> ");
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
c = 0;
|
||||||
|
|
||||||
|
while (i < SHELL_BUFFER_SIZE)
|
||||||
|
{
|
||||||
|
c = keyboard_getchar();
|
||||||
|
|
||||||
|
if (c == '\b')
|
||||||
|
{
|
||||||
|
if (i > 0)
|
||||||
|
{
|
||||||
|
terminal_printc("\b \b");
|
||||||
|
--i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
terminal_putchar(c);
|
||||||
|
input_buffer[i] = c;
|
||||||
|
++i;
|
||||||
|
|
||||||
|
if (c == '\n')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
input_buffer[i] = '\0';
|
||||||
|
keyboard_clear_buffer();
|
||||||
|
shell_parse_input(input_buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void shell_help_command(void)
|
||||||
|
{
|
||||||
|
terminal_printc("List of commands:\n");
|
||||||
|
terminal_printc("help - Print out the list of commands.\n");
|
||||||
|
terminal_printc("exit - Exit the shell.\n");
|
||||||
|
terminal_printc("echo - Print out the message. &eWITH colors!&7\n");
|
||||||
|
terminal_printc("clear - Clear the terminal.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void shell_exit_command(void)
|
||||||
|
{
|
||||||
|
terminal_printc("Exiting shell...\n");
|
||||||
|
terminal_printc("Goodbye!\n");
|
||||||
|
while (1)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
void shell_echo_command(char *input)
|
||||||
|
{
|
||||||
|
char *message = input;
|
||||||
|
|
||||||
|
while (*message == ' ')
|
||||||
|
{
|
||||||
|
message++;
|
||||||
|
}
|
||||||
|
|
||||||
|
terminal_printc(message);
|
||||||
|
terminal_printc("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void shell_parse_input(char *input)
|
||||||
|
{
|
||||||
|
char *command = strtok(input, " \n");
|
||||||
|
char *first_param = strtok(NULL, " \n");
|
||||||
|
|
||||||
|
if (command == NULL || *command == '\0')
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(command, "help") == 0)
|
||||||
|
{
|
||||||
|
shell_help_command();
|
||||||
|
}
|
||||||
|
else if (strcmp(command, "echo") == 0)
|
||||||
|
{
|
||||||
|
shell_echo_command(first_param);
|
||||||
|
}
|
||||||
|
else if (strcmp(command, "exit") == 0)
|
||||||
|
{
|
||||||
|
shell_exit_command();
|
||||||
|
}
|
||||||
|
else if (strcmp(command, "clear") == 0)
|
||||||
|
{
|
||||||
|
terminal_clear();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
terminal_printc("Unknown command: '");
|
||||||
|
terminal_writestring(command);
|
||||||
|
terminal_printc("'\n");
|
||||||
|
terminal_printc("Type 'help' to print out the list of commands.\n");
|
||||||
|
}
|
||||||
|
}
|
9
shell.h
Normal file
9
shell.h
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#ifndef _KERNEL_SHELL_H
|
||||||
|
#define _KERNEL_SHELL_H
|
||||||
|
|
||||||
|
#define SHELL_BUFFER_SIZE 256
|
||||||
|
|
||||||
|
void shell_init(void);
|
||||||
|
void shell_parse_input(char *input);
|
||||||
|
|
||||||
|
#endif
|
76
string.c
Normal file
76
string.c
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
#include "string.h"
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
int strcmp(const char *str1, const char *str2)
|
||||||
|
{
|
||||||
|
while (*str1 && (*str1 == *str2))
|
||||||
|
{
|
||||||
|
str1++;
|
||||||
|
str2++;
|
||||||
|
}
|
||||||
|
return *(const unsigned char *)str1 - *(const unsigned char *)str2;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *strchr(const char *str, int c)
|
||||||
|
{
|
||||||
|
while (*str != '\0')
|
||||||
|
{
|
||||||
|
if (*str == c)
|
||||||
|
{
|
||||||
|
return (char *)str;
|
||||||
|
}
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *strtok(char *str, const char *delim)
|
||||||
|
{
|
||||||
|
static char *last_token = NULL;
|
||||||
|
char *token_start;
|
||||||
|
char *current;
|
||||||
|
|
||||||
|
if (str != NULL)
|
||||||
|
{
|
||||||
|
current = str;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
current = last_token;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (*current != '\0' && strchr(delim, *current) != NULL)
|
||||||
|
{
|
||||||
|
current++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*current == '\0')
|
||||||
|
{
|
||||||
|
last_token = NULL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
token_start = current;
|
||||||
|
|
||||||
|
while (*current != '\0' && strchr(delim, *current) == NULL)
|
||||||
|
{
|
||||||
|
current++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*current != '\0')
|
||||||
|
{
|
||||||
|
*current = '\0';
|
||||||
|
last_token = current + 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
last_token = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return token_start;
|
||||||
|
}
|
8
string.h
Normal file
8
string.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#ifndef STRING_H
|
||||||
|
#define STRING_H
|
||||||
|
|
||||||
|
char *strchr(const char *str, int c);
|
||||||
|
char *strtok(char *str, const char *delim);
|
||||||
|
int strcmp(const char *str1, const char *str2);
|
||||||
|
|
||||||
|
#endif
|
16
sys.c
Normal file
16
sys.c
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#include "sys.h"
|
||||||
|
|
||||||
|
void sys_halt(void)
|
||||||
|
{
|
||||||
|
asm volatile("hlt" ::: "memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
void sys_enable_interrupts(void)
|
||||||
|
{
|
||||||
|
asm volatile("sti" ::: "memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
void sys_disable_interrupts(void)
|
||||||
|
{
|
||||||
|
asm volatile("cli" ::: "memory");
|
||||||
|
}
|
8
sys.h
Normal file
8
sys.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#ifndef _KERNEL_SYS_H
|
||||||
|
#define _KERNEL_SYS_H
|
||||||
|
|
||||||
|
void sys_halt(void);
|
||||||
|
void sys_enable_interrupts(void);
|
||||||
|
void sys_disable_interrupts(void);
|
||||||
|
|
||||||
|
#endif
|
26
syscall.c
Normal file
26
syscall.c
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include "interrupts.h"
|
||||||
|
#include "syscall.h"
|
||||||
|
#include "tty.h"
|
||||||
|
|
||||||
|
void test_syscall()
|
||||||
|
{
|
||||||
|
terminal_printc("Test syscall called\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void syscall_handler(Stack *registers)
|
||||||
|
{
|
||||||
|
int sys_index = registers->eax;
|
||||||
|
|
||||||
|
if (sys_index != 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
test_syscall();
|
||||||
|
}
|
||||||
|
|
||||||
|
void syscall_init(void)
|
||||||
|
{
|
||||||
|
isr_install_handler(128, syscall_handler);
|
||||||
|
}
|
6
syscall.h
Normal file
6
syscall.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#ifndef SYSCALL_H
|
||||||
|
#define SYSCALL_H
|
||||||
|
|
||||||
|
void syscall_init(void);
|
||||||
|
|
||||||
|
#endif
|
40
timer.c
Normal file
40
timer.c
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
#include "timer.h"
|
||||||
|
#include "io.h"
|
||||||
|
#include "sys.h"
|
||||||
|
#include "idt.h"
|
||||||
|
|
||||||
|
#define PIT_FREQUENCY 1193182
|
||||||
|
#define PIT_CHANNEL_0 0x40
|
||||||
|
#define PIT_COMMAND 0x43
|
||||||
|
|
||||||
|
volatile uint32_t tick = 0;
|
||||||
|
|
||||||
|
void pit_handler()
|
||||||
|
{
|
||||||
|
tick++;
|
||||||
|
outb(0x20, 0x20);
|
||||||
|
}
|
||||||
|
|
||||||
|
void delay(uint32_t milliseconds)
|
||||||
|
{
|
||||||
|
uint32_t end = tick + milliseconds;
|
||||||
|
while (tick < end)
|
||||||
|
{
|
||||||
|
sys_halt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void pit_set_frequency(uint32_t frequency)
|
||||||
|
{
|
||||||
|
uint32_t divisor = PIT_FREQUENCY / frequency;
|
||||||
|
outb(PIT_COMMAND, 0x36);
|
||||||
|
outb(PIT_CHANNEL_0, divisor & 0xFF);
|
||||||
|
outb(PIT_CHANNEL_0, (divisor >> 8) & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
void timer_install(void)
|
||||||
|
{
|
||||||
|
pic_remap(0x20, 0x28);
|
||||||
|
pit_set_frequency(1000);
|
||||||
|
idt_set_gate(32, (uint32_t)pit_handler_asm, 0x08, 0x8E);
|
||||||
|
}
|
14
timer.h
Normal file
14
timer.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#ifndef TIMER_H
|
||||||
|
#define TIMER_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
extern void pit_handler_asm();
|
||||||
|
|
||||||
|
void pit_handler();
|
||||||
|
void delay(uint32_t milliseconds);
|
||||||
|
void pit_set_frequency(uint32_t frequency);
|
||||||
|
void pic_remap(int offset1, int offset2);
|
||||||
|
void timer_install(void);
|
||||||
|
|
||||||
|
#endif
|
190
tty.c
Normal file
190
tty.c
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
#include "tty.h"
|
||||||
|
#include "vga.h"
|
||||||
|
#include "io.h"
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
size_t strlen(const char *str)
|
||||||
|
{
|
||||||
|
size_t len = 0;
|
||||||
|
while (str[len])
|
||||||
|
len++;
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const size_t VGA_WIDTH = 80;
|
||||||
|
static const size_t VGA_HEIGHT = 25;
|
||||||
|
|
||||||
|
size_t terminal_row;
|
||||||
|
size_t terminal_column;
|
||||||
|
uint8_t terminal_color;
|
||||||
|
uint16_t *terminal_buffer;
|
||||||
|
|
||||||
|
void terminal_initialize(void)
|
||||||
|
{
|
||||||
|
terminal_row = 0;
|
||||||
|
terminal_column = 0;
|
||||||
|
terminal_color = vga_entry_color(VGA_COLOR_LIGHT_GREY, VGA_COLOR_BLACK);
|
||||||
|
terminal_buffer = (uint16_t *)0xB8000;
|
||||||
|
for (size_t y = 0; y < VGA_HEIGHT; y++)
|
||||||
|
{
|
||||||
|
for (size_t x = 0; x < VGA_WIDTH; x++)
|
||||||
|
{
|
||||||
|
const size_t index = y * VGA_WIDTH + x;
|
||||||
|
terminal_buffer[index] = vga_entry(' ', terminal_color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void terminal_setcolor(uint8_t color)
|
||||||
|
{
|
||||||
|
terminal_color = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
void terminal_putentryat(char c, uint8_t color, size_t x, size_t y)
|
||||||
|
{
|
||||||
|
const size_t index = y * VGA_WIDTH + x;
|
||||||
|
terminal_buffer[index] = vga_entry(c, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint16_t terminal_pos(uint8_t x, uint8_t y)
|
||||||
|
{
|
||||||
|
return y * VGA_WIDTH + x;
|
||||||
|
}
|
||||||
|
|
||||||
|
void terminal_scroll(void)
|
||||||
|
{
|
||||||
|
for (size_t y = 0; y < VGA_HEIGHT - 1; y++)
|
||||||
|
{
|
||||||
|
for (size_t x = 0; x < VGA_WIDTH; x++)
|
||||||
|
{
|
||||||
|
terminal_buffer[y * VGA_WIDTH + x] = terminal_buffer[(y + 1) * VGA_WIDTH + x];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (size_t x = 0; x < VGA_WIDTH; x++)
|
||||||
|
{
|
||||||
|
terminal_buffer[(VGA_HEIGHT - 1) * VGA_WIDTH + x] = vga_entry(' ', terminal_color);
|
||||||
|
}
|
||||||
|
terminal_row = VGA_HEIGHT - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void terminal_backspace(void)
|
||||||
|
{
|
||||||
|
if (terminal_column == 0)
|
||||||
|
{
|
||||||
|
terminal_column = VGA_WIDTH - 1;
|
||||||
|
if (terminal_row == 0)
|
||||||
|
{
|
||||||
|
terminal_column = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
--terminal_row;
|
||||||
|
}
|
||||||
|
uint16_t empty = vga_entry(' ', terminal_color);
|
||||||
|
uint16_t index = terminal_pos(terminal_column, terminal_row);
|
||||||
|
while (terminal_column > 0 && terminal_buffer[index] == empty)
|
||||||
|
{
|
||||||
|
--terminal_column;
|
||||||
|
index = terminal_pos(terminal_column, terminal_row);
|
||||||
|
}
|
||||||
|
if (terminal_buffer[index] != empty && terminal_column + 1 < VGA_WIDTH)
|
||||||
|
{
|
||||||
|
++terminal_column;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
--terminal_column;
|
||||||
|
}
|
||||||
|
uint16_t index = terminal_pos(terminal_column, terminal_row);
|
||||||
|
terminal_buffer[index] = vga_entry(' ', terminal_color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void terminal_putchar(char c)
|
||||||
|
{
|
||||||
|
if (c == '\n')
|
||||||
|
{
|
||||||
|
terminal_column = 0;
|
||||||
|
if (++terminal_row == VGA_HEIGHT)
|
||||||
|
{
|
||||||
|
terminal_scroll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (c == '\b')
|
||||||
|
{
|
||||||
|
terminal_backspace();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint16_t index = terminal_pos(terminal_column, terminal_row);
|
||||||
|
terminal_buffer[index] = vga_entry(c, terminal_color);
|
||||||
|
if (++terminal_column == VGA_WIDTH)
|
||||||
|
{
|
||||||
|
terminal_column = 0;
|
||||||
|
if (++terminal_row == VGA_HEIGHT)
|
||||||
|
{
|
||||||
|
terminal_scroll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
terminal_update_cursor();
|
||||||
|
}
|
||||||
|
|
||||||
|
void terminal_write(const char *data, size_t size)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < size; i++)
|
||||||
|
{
|
||||||
|
terminal_putchar(data[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void terminal_writestring(const char *data)
|
||||||
|
{
|
||||||
|
terminal_write(data, strlen(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
void terminal_printc(const char *data)
|
||||||
|
{
|
||||||
|
while (*data)
|
||||||
|
{
|
||||||
|
if (*data == '&' && ((*(data + 1) >= '0' && *(data + 1) <= '9') ||
|
||||||
|
(*(data + 1) >= 'a' && *(data + 1) <= 'f')))
|
||||||
|
{
|
||||||
|
terminal_setcolor(vga_entry_color(vga_color_from_char(*(data + 1)), VGA_COLOR_BLACK));
|
||||||
|
data += 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
terminal_putchar(*data);
|
||||||
|
data++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void terminal_update_cursor(void)
|
||||||
|
{
|
||||||
|
uint16_t pos = terminal_row * VGA_WIDTH + terminal_column;
|
||||||
|
|
||||||
|
outb(0x3D4, 14);
|
||||||
|
outb(0x3D5, pos >> 8);
|
||||||
|
outb(0x3D4, 15);
|
||||||
|
outb(0x3D5, pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
void terminal_clear(void)
|
||||||
|
{
|
||||||
|
for (size_t y = 0; y < VGA_HEIGHT; y++)
|
||||||
|
{
|
||||||
|
for (size_t x = 0; x < VGA_WIDTH; x++)
|
||||||
|
{
|
||||||
|
const size_t index = y * VGA_WIDTH + x;
|
||||||
|
terminal_buffer[index] = vga_entry(' ', terminal_color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
terminal_column = 0;
|
||||||
|
terminal_row = 0;
|
||||||
|
terminal_update_cursor();
|
||||||
|
}
|
17
tty.h
Normal file
17
tty.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#ifndef TERMINAL_H
|
||||||
|
#define TERMINAL_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
void terminal_initialize(void);
|
||||||
|
void terminal_setcolor(uint8_t color);
|
||||||
|
void terminal_putentryat(char c, uint8_t color, size_t x, size_t y);
|
||||||
|
void terminal_putchar(char c);
|
||||||
|
void terminal_write(const char *data, size_t size);
|
||||||
|
void terminal_writestring(const char *data);
|
||||||
|
void terminal_printc(const char *data);
|
||||||
|
void terminal_update_cursor(void);
|
||||||
|
void terminal_clear(void);
|
||||||
|
|
||||||
|
#endif
|
23
user_space.c
Normal file
23
user_space.c
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#include "user_space.h"
|
||||||
|
|
||||||
|
void enter_user_space(void)
|
||||||
|
{
|
||||||
|
asm volatile(" cli; \
|
||||||
|
mov $0x23, %ax; \
|
||||||
|
mov %ax, %ds; \
|
||||||
|
mov %ax, %es; \
|
||||||
|
mov %ax, %fs; \
|
||||||
|
mov %ax, %gs; \
|
||||||
|
mov %esp, %eax; \
|
||||||
|
pushl $0x23; \
|
||||||
|
pushl %eax; \
|
||||||
|
pushf; \
|
||||||
|
popl %eax; \
|
||||||
|
orl $0x200, %eax; \
|
||||||
|
pushl %eax; \
|
||||||
|
pushl $0x1B; \
|
||||||
|
push $1f; \
|
||||||
|
iret; \
|
||||||
|
1: \
|
||||||
|
");
|
||||||
|
}
|
6
user_space.h
Normal file
6
user_space.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#ifndef _USER_SPACE_H
|
||||||
|
#define _USER_SPACE_H
|
||||||
|
|
||||||
|
void enter_user_space(void);
|
||||||
|
|
||||||
|
#endif
|
31
vga.c
Normal file
31
vga.c
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#include "vga.h"
|
||||||
|
|
||||||
|
uint8_t vga_entry_color(enum vga_color fg, enum vga_color bg) {
|
||||||
|
return fg | bg << 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t vga_entry(unsigned char uc, uint8_t color) {
|
||||||
|
return (uint16_t) uc | (uint16_t) color << 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t vga_color_from_char(char color_code) {
|
||||||
|
switch (color_code) {
|
||||||
|
case '0': return VGA_COLOR_BLACK;
|
||||||
|
case '1': return VGA_COLOR_BLUE;
|
||||||
|
case '2': return VGA_COLOR_GREEN;
|
||||||
|
case '3': return VGA_COLOR_CYAN;
|
||||||
|
case '4': return VGA_COLOR_RED;
|
||||||
|
case '5': return VGA_COLOR_MAGENTA;
|
||||||
|
case '6': return VGA_COLOR_BROWN;
|
||||||
|
case '7': return VGA_COLOR_LIGHT_GREY;
|
||||||
|
case '8': return VGA_COLOR_DARK_GREY;
|
||||||
|
case '9': return VGA_COLOR_LIGHT_BLUE;
|
||||||
|
case 'a': return VGA_COLOR_LIGHT_GREEN;
|
||||||
|
case 'b': return VGA_COLOR_LIGHT_CYAN;
|
||||||
|
case 'c': return VGA_COLOR_LIGHT_RED;
|
||||||
|
case 'd': return VGA_COLOR_LIGHT_MAGENTA;
|
||||||
|
case 'e': return VGA_COLOR_LIGHT_BROWN;
|
||||||
|
case 'f': return VGA_COLOR_WHITE;
|
||||||
|
default: return VGA_COLOR_LIGHT_GREY;
|
||||||
|
}
|
||||||
|
}
|
29
vga.h
Normal file
29
vga.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#ifndef VGA_H
|
||||||
|
#define VGA_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
enum vga_color {
|
||||||
|
VGA_COLOR_BLACK = 0,
|
||||||
|
VGA_COLOR_BLUE = 1,
|
||||||
|
VGA_COLOR_GREEN = 2,
|
||||||
|
VGA_COLOR_CYAN = 3,
|
||||||
|
VGA_COLOR_RED = 4,
|
||||||
|
VGA_COLOR_MAGENTA = 5,
|
||||||
|
VGA_COLOR_BROWN = 6,
|
||||||
|
VGA_COLOR_LIGHT_GREY = 7,
|
||||||
|
VGA_COLOR_DARK_GREY = 8,
|
||||||
|
VGA_COLOR_LIGHT_BLUE = 9,
|
||||||
|
VGA_COLOR_LIGHT_GREEN = 10,
|
||||||
|
VGA_COLOR_LIGHT_CYAN = 11,
|
||||||
|
VGA_COLOR_LIGHT_RED = 12,
|
||||||
|
VGA_COLOR_LIGHT_MAGENTA = 13,
|
||||||
|
VGA_COLOR_LIGHT_BROWN = 14,
|
||||||
|
VGA_COLOR_WHITE = 15,
|
||||||
|
};
|
||||||
|
|
||||||
|
uint8_t vga_entry_color(enum vga_color fg, enum vga_color bg);
|
||||||
|
uint16_t vga_entry(unsigned char uc, uint8_t color);
|
||||||
|
uint8_t vga_color_from_char(char color_code);
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user