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