dead@root
This commit is contained in:
		
							
								
								
									
										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 | ||||||
		Reference in New Issue
	
	Block a user