From ebb537d5e1010800210993aa164390f323db3caa Mon Sep 17 00:00:00 2001 From: Felix Queissner Date: Fri, 16 Oct 2015 14:05:37 +0200 Subject: [PATCH] Adds starting processes via multiboot modules. Removes built-in module. Splits main.cu in main.cu and keyboard.cu. --- Depfile | 27 ++-- Makefile | 35 +++-- scripts/keyboard.cu | 154 ++++++++++++++++++ scripts/keyboard.cu.spark | 313 ++++++++++++++++++++++++++++++++++++ scripts/main.cu | 157 ------------------- scripts/main.cu.spark | 322 +------------------------------------- src/init.c | 44 +++--- src/vm.cpp | 145 +++++++++-------- trainOS.pro | 3 +- 9 files changed, 618 insertions(+), 582 deletions(-) create mode 100644 scripts/keyboard.cu create mode 100644 scripts/keyboard.cu.spark diff --git a/Depfile b/Depfile index dfcb0fc..00f56a6 100644 --- a/Depfile +++ b/Depfile @@ -2,9 +2,11 @@ Artifact=kernel TempDir=obj SourceDir=asm src csl -AdditionalObjects=obj/main.o +AdditionalObjects= ExternalObjects=conductance/|*.o +AdditionalDependencies=obj/main.in obj/keyboard.in + LexUseCpp YaccUseCpp @@ -28,25 +30,28 @@ LDFLAGS=-nostdlib -fno-builtin -Tkernel.ld TOOLS=/home/felix/projects/Electronics/build-Electronics-Clang-Debug/bin -obj/main.o: scripts/main.cu +obj/main.in: scripts/main.cu $(TOOLS)/copper \ scripts/main.cu > \ scripts/main.cu.spark $(TOOLS)/spark \ scripts/main.cu.spark \ obj/main.in - objcopy -B i386 -I binary -O elf32-i386 \ - obj/main.in obj/main.o - objcopy \ - --redefine-sym _binary_obj_main_in_start=mainscript_start \ - --redefine-sym _binary_obj_main_in_end=mainscript_end \ - --redefine-sym _binary_obj_main_in_size=mainscript_size \ - obj/main.o + +obj/keyboard.in: scripts/keyboard.cu + $(TOOLS)/copper \ + scripts/keyboard.cu > \ + scripts/keyboard.cu.spark + $(TOOLS)/spark \ + scripts/keyboard.cu.spark \ + obj/keyboard.in + +QEMUFLAGS=-serial stdio -kernel kernel -initrd obj/main.in,obj/keyboard.in .PHONY: run run: - qemu-system-i386 -serial stdio -kernel kernel + qemu-system-i386 $(QEMUFLAGS) .PHONY: debug debug: - qemu-system-i386 -s -S -serial stdio -kernel kernel + qemu-system-i386 -s -S $(QEMUFLAGS) diff --git a/Makefile b/Makefile index d7680dc..f895e5d 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ TEMPLE = mono temple.exe SRCS_AS = asm/dynamic.S asm/intr_common_handler.S asm/multiboot.S asm/start.S SRCS_CC = src/console.c src/init.c src/interrupts.c src/malloc.c src/pmm.c src/serial.c src/stdlib.c src/timer.c src/vmm.c SRCS_CXX = src/cplusplus.cpp src/vm.cpp csl/casts.cpp csl/cpustatetype.cpp csl/io.cpp -OBJS = obj/dynamic.o obj/intr_common_handler.o obj/multiboot.o obj/start.o obj/console.o obj/init.o obj/interrupts.o obj/malloc.o obj/pmm.o obj/serial.o obj/stdlib.o obj/timer.o obj/vmm.o obj/cplusplus.o obj/vm.o obj/casts.o obj/cpustatetype.o obj/io.o obj/main.o +OBJS = obj/dynamic.o obj/intr_common_handler.o obj/multiboot.o obj/start.o obj/console.o obj/init.o obj/interrupts.o obj/malloc.o obj/pmm.o obj/serial.o obj/stdlib.o obj/timer.o obj/vmm.o obj/cplusplus.o obj/vm.o obj/casts.o obj/cpustatetype.o obj/io.o # Flags FLAGS = -g -Wall -Wextra -m32 -DCIRCUIT_OS -Dnullptr=0 -D__cdecl="__attribute__((cdecl))" -mno-sse -mno-sse2 -mno-mmx -I/home/felix/projects/Electronics/Electronics/Conductance -I/home/felix/projects/Electronics/Electronics/Tools @@ -28,10 +28,10 @@ all: kernel .PHONY: clean clean: - $(RM) obj/dynamic.o obj/intr_common_handler.o obj/multiboot.o obj/start.o obj/console.o obj/init.o obj/interrupts.o obj/malloc.o obj/pmm.o obj/serial.o obj/stdlib.o obj/timer.o obj/vmm.o obj/cplusplus.o obj/vm.o obj/casts.o obj/cpustatetype.o obj/io.o obj/main.o + $(RM) obj/dynamic.o obj/intr_common_handler.o obj/multiboot.o obj/start.o obj/console.o obj/init.o obj/interrupts.o obj/malloc.o obj/pmm.o obj/serial.o obj/stdlib.o obj/timer.o obj/vmm.o obj/cplusplus.o obj/vm.o obj/casts.o obj/cpustatetype.o obj/io.o -kernel: obj/dynamic.o obj/intr_common_handler.o obj/multiboot.o obj/start.o obj/console.o obj/init.o obj/interrupts.o obj/malloc.o obj/pmm.o obj/serial.o obj/stdlib.o obj/timer.o obj/vmm.o obj/cplusplus.o obj/vm.o obj/casts.o obj/cpustatetype.o obj/io.o obj/main.o conductance/assembly.o conductance/compoundtype.o conductance/instructions.o conductance/process.o conductance/string.o conductance/thread.o conductance/virtualmachine.o conductance/vmpointertype.o conductance/vmprimitivetype.o conductance/vmtype.o conductance/vmvalue.o conductance/vmvoidtype.o - $(LD) $(FLAGS) $(LDFLAGS) -o $@ obj/dynamic.o obj/intr_common_handler.o obj/multiboot.o obj/start.o obj/console.o obj/init.o obj/interrupts.o obj/malloc.o obj/pmm.o obj/serial.o obj/stdlib.o obj/timer.o obj/vmm.o obj/cplusplus.o obj/vm.o obj/casts.o obj/cpustatetype.o obj/io.o obj/main.o conductance/assembly.o conductance/compoundtype.o conductance/instructions.o conductance/process.o conductance/string.o conductance/thread.o conductance/virtualmachine.o conductance/vmpointertype.o conductance/vmprimitivetype.o conductance/vmtype.o conductance/vmvalue.o conductance/vmvoidtype.o +kernel: obj/dynamic.o obj/intr_common_handler.o obj/multiboot.o obj/start.o obj/console.o obj/init.o obj/interrupts.o obj/malloc.o obj/pmm.o obj/serial.o obj/stdlib.o obj/timer.o obj/vmm.o obj/cplusplus.o obj/vm.o obj/casts.o obj/cpustatetype.o obj/io.o conductance/assembly.o conductance/compoundtype.o conductance/instructions.o conductance/process.o conductance/string.o conductance/thread.o conductance/virtualmachine.o conductance/vmpointertype.o conductance/vmprimitivetype.o conductance/vmtype.o conductance/vmvalue.o conductance/vmvoidtype.o obj/main.in obj/keyboard.in + $(LD) $(FLAGS) $(LDFLAGS) -o $@ obj/dynamic.o obj/intr_common_handler.o obj/multiboot.o obj/start.o obj/console.o obj/init.o obj/interrupts.o obj/malloc.o obj/pmm.o obj/serial.o obj/stdlib.o obj/timer.o obj/vmm.o obj/cplusplus.o obj/vm.o obj/casts.o obj/cpustatetype.o obj/io.o conductance/assembly.o conductance/compoundtype.o conductance/instructions.o conductance/process.o conductance/string.o conductance/thread.o conductance/virtualmachine.o conductance/vmpointertype.o conductance/vmprimitivetype.o conductance/vmtype.o conductance/vmvalue.o conductance/vmvoidtype.o # src/console.c obj/console.o: src/console.c include/console.h include/kstdlib.h \ @@ -92,8 +92,8 @@ obj/cplusplus.o: src/cplusplus.cpp include/kstdlib.h include/varargs.h \ # src/vm.cpp obj/vm.o: src/vm.cpp include/kstdlib.h include/varargs.h include/config.h \ include/malloc.h include/timer.h include/dynamic.h include/console.h \ - include/interrupts.h include/cpustate.h src/../csl/cpustatetype.hpp \ - src/../csl/io.hpp src/../csl/casts.hpp + include/multiboot.h include/interrupts.h include/cpustate.h \ + src/../csl/cpustatetype.hpp src/../csl/io.hpp src/../csl/casts.hpp $(CXX) -iquoteobj $(FLAGS) $(CXXFLAGS) -o $@ -c src/vm.cpp # csl/casts.cpp @@ -129,25 +129,28 @@ obj/start.o: asm/start.S TOOLS=/home/felix/projects/Electronics/build-Electronics-Clang-Debug/bin -obj/main.o: scripts/main.cu +obj/main.in: scripts/main.cu $(TOOLS)/copper \ scripts/main.cu > \ scripts/main.cu.spark $(TOOLS)/spark \ scripts/main.cu.spark \ obj/main.in - objcopy -B i386 -I binary -O elf32-i386 \ - obj/main.in obj/main.o - objcopy \ - --redefine-sym _binary_obj_main_in_start=mainscript_start \ - --redefine-sym _binary_obj_main_in_end=mainscript_end \ - --redefine-sym _binary_obj_main_in_size=mainscript_size \ - obj/main.o + +obj/keyboard.in: scripts/keyboard.cu + $(TOOLS)/copper \ + scripts/keyboard.cu > \ + scripts/keyboard.cu.spark + $(TOOLS)/spark \ + scripts/keyboard.cu.spark \ + obj/keyboard.in + +QEMUFLAGS=-serial stdio -kernel kernel -initrd obj/main.in,obj/keyboard.in .PHONY: run run: - qemu-system-i386 -serial stdio -kernel kernel + qemu-system-i386 $(QEMUFLAGS) .PHONY: debug debug: - qemu-system-i386 -s -S -serial stdio -kernel kernel + qemu-system-i386 -s -S $(QEMUFLAGS) diff --git a/scripts/keyboard.cu b/scripts/keyboard.cu new file mode 100644 index 0000000..8b1de09 --- /dev/null +++ b/scripts/keyboard.cu @@ -0,0 +1,154 @@ + +.asmtype DRIVER +.name KEYBOARDDRIVER + +NATIVE print(...); + +NATIVE outb(port : UINT16, value : UINT8); +NATIVE inb(port : UINT16) → UINT8; + +NATIVE toInt32(…) → INT32; +NATIVE toUInt16(…) → UINT16; + +TYPE CpuState IS + eax : UINT32; + ebx : UINT32; + ecx : UINT32; +END + +PRI sendCommand(cmd : UINT8) +BEGIN + # Warten bis die Tastatur bereit ist, und der Befehlspuffer leer ist + WHILE (inb(100u16) & 2u8) =/= 0u8 DO + + END + outb(toUInt16(96), cmd); +END + +PRI initKeyboard() +BEGIN + # Tastaturpuffer leeren + WHILE (inb(100u16) & 1u8) =/= 0u8 DO + inb(96u16); + END + + # Tastatur aktivieren +# sendCommand(244u8); +END + +PRI handleKeyPress(keycode : INT, released : BOOL) +BEGIN + IF released = FALSE THEN + print("[keycode=", keycode, "]\n"); + END +END + +PUB main() | i : INT +BEGIN + print("Initialize keyboard...\n"); + initKeyboard(); +END + +# Status-Variablen fuer das Behandeln von e0- und e1-Scancodes +VAR e0Code : BOOL; + +# Wird auf 1 gesetzt, sobald e1 gelesen wurde, und auf 2, sobald das erste +# Datenbyte gelesen wurde +VAR e1Code : INT; + +VAR e1Prev : UINT16; + +PRI translateKeyCode(extend : INT, scancode : INT) → keycode : INT +BEGIN + print("[extend=", extend, ",scancode=", scancode, "]\n"); + 0 → keycode; + IF extend = 0 THEN + # LOTS OF CODE HERE. Maybe optimize this? :P + IF scancode = 10 THEN 1 → keycode; RETURN; END + END +END + +PRI handleKeyboardIRQ() | scancode : UINT8, keycode : INT, breakcode : BOOL +BEGIN + 0 → keycode; + FALSE → breakcode; + inb(96u16) → scancode; + + # Um einen Breakcode handelt es sich, wenn das oberste Bit gesetzt ist und + # es kein e0 oder e1 fuer einen Extended-scancode ist + IF ((scancode & 0x80u8) =/= 0u8) & ((e1Code =/= 0) | (scancode =/= 0xE1u8)) & (e0Code | (scancode =/= 0xE0u8)) THEN + TRUE → breakcode; + (scancode & 127u8) → scancode; + END + +# print("[scancode=", scancode, ",breakcode=", breakcode, "]"); + + IF e0Code THEN + # Fake shift abfangen und ignorieren + IF (scancode = 0x2Au8) | (scancode = 0x36u8) THEN + FALSE → e0Code; + RETURN; + END + + translateKeyCode(1, toInt32(scancode)) → keycode; + FALSE → e0Code; + ELSE + IF e1Code = 2 THEN + # Fertiger e1-Scancode + # Zweiten Scancode in hoeherwertiges Byte packen + (e1Prev | toUInt16(scancode * 256u8)) → e1Prev; + translateKeyCode(2, toInt32(e1Prev)) → keycode; + 0 → e1Code; + ELSE + IF e1Code = 1 THEN + # Erstes Byte fuer e1-Scancode + toUInt16(scancode) → e1Prev; + 2 → e1Code; + ELSE + IF scancode = 0xE0u8 THEN + TRUE → e0Code; + ELSE + IF scancode = 0xE1u8 THEN + 1 → e1Code; + ELSE + translateKeyCode(0, toInt32(scancode)) → keycode; + END + END + END + END + END + + IF keycode =/= 0 THEN + handleKeyPress(keycode, breakcode); + END +END + +PUB irq(id : INT, data : CpuState) +BEGIN +# print("irq:", id, ", ", data.eax, " ", data.ebx, "\n"); + IF id = 33 THEN + handleKeyboardIRQ(); + END + ~data; +END + +#! +Was noch gemacht werden muss, bis der Tastatur-Treiber funktionieren könnte: + ☑ Support für beliebige Typen in Copper + ☑ Pushen von Typen != INT + ☑ erweiterung von pushi um typcode (u?int(8|16|32), bool) + ☑ erweiterung von pushr um typcode + ☑ Simple type checks in Copper + ☑ Custom types in Copper + ☑ Native function calls in Copper + ☑ Bitwise Operations + ☑ outb und inb + ☑ NEW/DELETE + ☑ [TYPE] → + ☑ ~() + ☑ hex literals für Copper + ☑ 'RETURN' für Copper +Was noch gemacht werden muss, bis der Tastatur-Treiber schön aussieht: + ☐ ELSE-IF + ☐ ARRAYS +!# diff --git a/scripts/keyboard.cu.spark b/scripts/keyboard.cu.spark new file mode 100644 index 0000000..85713b2 --- /dev/null +++ b/scripts/keyboard.cu.spark @@ -0,0 +1,313 @@ +; ============================================= +; compiled with Copper 1.0 +; 2015-10-16 13:36:11 +; ============================================= + +.asmtype DRIVER +.name KEYBOARDDRIVER +; native method: print(…) +; native method: outb(…) +; native method: inb(…) → UINT8 +; native method: toInt32(…) → INT32 +; native method: toUInt16(…) → UINT16 +.type CpuState { + eax : UINT32; + ebx : UINT32; + ecx : UINT32; +} +.global e0Code BOOL +.global e1Code INT32 +.global e1Prev UINT16 + + + + + + + + +; 0, sendCommand +sendCommand: + pushnil ; return value +_private_0: + pushi 4 100 + callnr inb 1 + pushi 3 2 + op2 12 + pushi 3 0 + op2 6 + jmp_if_not _private_1 + jmp _private_0 +_private_1: + + load -1 + pushi 2 96 + callnr toUInt16 1 + calln outb 2 + + ret +; end of sendCommand + +; 0, initKeyboard +initKeyboard: + pushnil ; return value +_private_2: + pushi 4 100 + callnr inb 1 + pushi 3 1 + op2 12 + pushi 3 0 + op2 6 + jmp_if_not _private_3 + pushi 4 96 + calln inb 1 + + jmp _private_2 +_private_3: + + ret +; end of initKeyboard + +; 0, handleKeyPress +handleKeyPress: + pushnil ; return value + load -2 + pushi 6 0 + op2 5 + jmp_if_not _private_4 + pusht "]\n" + load -1 + pusht "[keycode=" + calln print 3 + +_private_4: + + ret +; end of handleKeyPress + +; 1, main +.export main +main: + pushnil ; return value + pushnil ; i:INT32 + pusht "Initialize keyboard...\n" + calln print 1 + + call initKeyboard 0 + + ret +; end of main + + + + +; 0, translateKeyCode +translateKeyCode: + pushnil ; return value + pusht "]\n" + load -2 + pusht ",scancode=" + load -1 + pusht "[extend=" + calln print 5 + + pushi 2 0 + store 0 + + load -1 + pushi 2 0 + op2 5 + jmp_if_not _private_5 + load -2 + pushi 2 10 + op2 5 + jmp_if_not _private_6 + pushi 2 1 + store 0 + + load 0 + retr + +_private_6: + +_private_5: + + load 0 + retr +; end of translateKeyCode + +; 0, handleKeyboardIRQ +handleKeyboardIRQ: + pushnil ; return value + pushnil ; scancode:UINT8 + pushnil ; keycode:INT32 + pushnil ; breakcode:BOOL + pushi 2 0 + store 2 + + pushi 6 0 + store 3 + + pushi 4 96 + callnr inb 1 + store 1 + + load 1 + pushi 3 128 + op2 12 + pushi 3 0 + op2 6 + loadg e1Code + pushi 2 0 + op2 6 + load 1 + pushi 3 225 + op2 6 + op2 11 + loadg e0Code + load 1 + pushi 3 224 + op2 6 + op2 11 + op2 12 + op2 12 + jmp_if_not _private_7 + pushi 6 1 + store 3 + + load 1 + pushi 3 127 + op2 12 + store 1 + +_private_7: + + loadg e0Code + jmp_if_not _private_8 + load 1 + pushi 3 42 + op2 5 + load 1 + pushi 3 54 + op2 5 + op2 11 + jmp_if_not _private_10 + pushi 6 0 + storeg e0Code + + ret + +_private_10: + + load 1 + callnr toInt32 1 + pushi 2 1 + callr translateKeyCode 2 + store 2 + + pushi 6 0 + storeg e0Code + + jmp _private_9 +_private_8: + loadg e1Code + pushi 2 2 + op2 5 + jmp_if_not _private_11 + loadg e1Prev + load 1 + pushi 3 256 + op2 2 + callnr toUInt16 1 + op2 11 + storeg e1Prev + + loadg e1Prev + callnr toInt32 1 + pushi 2 2 + callr translateKeyCode 2 + store 2 + + pushi 2 0 + storeg e1Code + + jmp _private_12 +_private_11: + loadg e1Code + pushi 2 1 + op2 5 + jmp_if_not _private_13 + load 1 + callnr toUInt16 1 + storeg e1Prev + + pushi 2 2 + storeg e1Code + + jmp _private_14 +_private_13: + load 1 + pushi 3 224 + op2 5 + jmp_if_not _private_15 + pushi 6 1 + storeg e0Code + + jmp _private_16 +_private_15: + load 1 + pushi 3 225 + op2 5 + jmp_if_not _private_17 + pushi 2 1 + storeg e1Code + + jmp _private_18 +_private_17: + load 1 + callnr toInt32 1 + pushi 2 0 + callr translateKeyCode 2 + store 2 + +_private_18: + +_private_16: + +_private_14: + +_private_12: + +_private_9: + + load 2 + pushi 2 0 + op2 6 + jmp_if_not _private_19 + load 3 + load 2 + call handleKeyPress 2 + +_private_19: + + ret +; end of handleKeyboardIRQ + +; 1, irq +.export irq +irq: + pushnil ; return value + load -1 + pushi 2 33 + op2 5 + jmp_if_not _private_20 + call handleKeyboardIRQ 0 + +_private_20: + + load -2 + destruct + + ret +; end of irq + diff --git a/scripts/main.cu b/scripts/main.cu index 5b3f33a..10272d7 100644 --- a/scripts/main.cu +++ b/scripts/main.cu @@ -2,58 +2,8 @@ NATIVE print(...); NATIVE shutdown(); -NATIVE outb(port : UINT16, value : UINT8); -NATIVE inb(port : UINT16) → UINT8; - -NATIVE toInt8(…) → INT8; -NATIVE toInt16(…) → INT16; -NATIVE toInt32(…) → INT32; - -NATIVE toUInt8(…) → UINT8; -NATIVE toUInt16(…) → UINT16; -NATIVE toUInt32(…) → UINT32; - -# NATIVE toBool(…) → BOOL; -# NATIVE toText(…) → TEXT; - -TYPE CpuState IS - eax : UINT32; - ebx : UINT32; - ecx : UINT32; -END - -PRI sendCommand(cmd : UINT8) -BEGIN - # Warten bis die Tastatur bereit ist, und der Befehlspuffer leer ist - WHILE (inb(100u16) & 2u8) =/= 0u8 DO - - END - outb(toUInt16(96), cmd); -END - -PRI initKeyboard() -BEGIN - # Tastaturpuffer leeren - WHILE (inb(100u16) & 1u8) =/= 0u8 DO - inb(96u16); - END - - # Tastatur aktivieren -# sendCommand(244u8); -END - -PRI handleKeyPress(keycode : INT, released : BOOL) -BEGIN - IF released = FALSE THEN - print("[keycode=", keycode, "]\n"); - END -END - PUB main() | i : INT BEGIN - print("Initialize keyboard...\n"); - initKeyboard(); - print("Hello World!\n"); 1 → i; WHILE i <= 5 DO @@ -61,110 +11,3 @@ BEGIN (i + 1) → i; END END - -# Status-Variablen fuer das Behandeln von e0- und e1-Scancodes -VAR e0Code : BOOL; -# Wird auf 1 gesetzt, sobald e1 gelesen wurde, und auf 2, sobald das erste -# Datenbyte gelesen wurde -VAR e1Code : INT; -VAR e1Prev : UINT16; - -PRI translateKeyCode(extend : INT, scancode : INT) → keycode : INT -BEGIN - print("[extend=", extend, ",scancode=", scancode, "]\n"); - 0 → keycode; - IF extend = 0 THEN - # LOTS OF CODE HERE. Maybe optimize this? :P - IF scancode = 10 THEN 1 → keycode; RETURN; END - END -END - -PRI handleKeyboardIRQ() | scancode : UINT8, keycode : INT, breakcode : BOOL -BEGIN - 0 → keycode; - FALSE → breakcode; - inb(96u16) → scancode; - - # Um einen Breakcode handelt es sich, wenn das oberste Bit gesetzt ist und - # es kein e0 oder e1 fuer einen Extended-scancode ist - IF ((scancode & 0x80u8) =/= 0u8) & ((e1Code =/= 0) | (scancode =/= 0xE1u8)) & (e0Code | (scancode =/= 0xE0u8)) THEN - TRUE → breakcode; - (scancode & 127u8) → scancode; - END - - IF scancode = 0x01u8 THEN - shutdown(); - RETURN; - END - -# print("[scancode=", scancode, ",breakcode=", breakcode, "]"); - - IF e0Code THEN - # Fake shift abfangen und ignorieren - IF (scancode = 0x2Au8) | (scancode = 0x36u8) THEN - FALSE → e0Code; - RETURN; - END - - translateKeyCode(1, toInt32(scancode)) → keycode; - FALSE → e0Code; - ELSE - IF e1Code = 2 THEN - # Fertiger e1-Scancode - # Zweiten Scancode in hoeherwertiges Byte packen - (e1Prev | toUInt16(scancode * 256u8)) → e1Prev; - translateKeyCode(2, toInt32(e1Prev)) → keycode; - 0 → e1Code; - ELSE - IF e1Code = 1 THEN - # Erstes Byte fuer e1-Scancode - toUInt16(scancode) → e1Prev; - 2 → e1Code; - ELSE - IF scancode = 0xE0u8 THEN - TRUE → e0Code; - ELSE - IF scancode = 0xE1u8 THEN - 1 → e1Code; - ELSE - translateKeyCode(0, toInt32(scancode)) → keycode; - END - END - END - END - END - - IF keycode =/= 0 THEN - handleKeyPress(keycode, breakcode); - END -END - -PUB irq(id : INT, data : CpuState) -BEGIN -# print("irq:", id, ", ", data.eax, " ", data.ebx, "\n"); - IF id = 33 THEN - handleKeyboardIRQ(); - END - ~data; -END - -#! -Was noch gemacht werden muss, bis der Tastatur-Treiber funktionieren könnte: - ☑ Support für beliebige Typen in Copper - ☑ Pushen von Typen != INT - ☑ erweiterung von pushi um typcode (u?int(8|16|32), bool) - ☑ erweiterung von pushr um typcode - ☑ Simple type checks in Copper - ☑ Custom types in Copper - ☑ Native function calls in Copper - ☑ Bitwise Operations - ☑ outb und inb - ☑ NEW/DELETE - ☑ [TYPE] → - ☑ ~() - ☑ hex literals für Copper - ☑ 'RETURN' für Copper -Was noch gemacht werden muss, bis der Tastatur-Treiber schön aussieht: - ☐ ELSE-IF - ☐ ARRAYS -!# diff --git a/scripts/main.cu.spark b/scripts/main.cu.spark index 96588ff..5a6dd1b 100644 --- a/scripts/main.cu.spark +++ b/scripts/main.cu.spark @@ -1,117 +1,28 @@ ; ============================================= ; compiled with Copper 1.0 -; 2015-10-14 21:08:00 +; 2015-10-16 13:32:19 ; ============================================= ; native method: print(…) ; native method: shutdown(…) -; native method: outb(…) -; native method: inb(…) → UINT8 -; native method: toInt8(…) → INT8 -; native method: toInt16(…) → INT16 -; native method: toInt32(…) → INT32 -; native method: toUInt8(…) → UINT8 -; native method: toUInt16(…) → UINT16 -; native method: toUInt32(…) → UINT32 -.type CpuState { - eax : UINT32; - ebx : UINT32; - ecx : UINT32; -} -.global e0Code BOOL -.global e1Code INT32 -.global e1Prev UINT16 - - - - - - - - - -; 0, sendCommand -sendCommand: - pushnil ; return value -_private_0: - pushi 4 100 - callnr inb 1 - pushi 3 2 - op2 12 - pushi 3 0 - op2 6 - jmp_if_not _private_1 - jmp _private_0 -_private_1: - - load -1 - pushi 2 96 - callnr toUInt16 1 - calln outb 2 - - ret -; end of sendCommand - -; 0, initKeyboard -initKeyboard: - pushnil ; return value -_private_2: - pushi 4 100 - callnr inb 1 - pushi 3 1 - op2 12 - pushi 3 0 - op2 6 - jmp_if_not _private_3 - pushi 4 96 - calln inb 1 - - jmp _private_2 -_private_3: - - ret -; end of initKeyboard - -; 0, handleKeyPress -handleKeyPress: - pushnil ; return value - load -2 - pushi 6 0 - op2 5 - jmp_if_not _private_4 - pusht "]\n" - load -1 - pusht "[keycode=" - calln print 3 - -_private_4: - - ret -; end of handleKeyPress - ; 1, main .export main main: pushnil ; return value pushnil ; i:INT32 - pusht "Initialize keyboard...\n" - calln print 1 - - call initKeyboard 0 - pusht "Hello World!\n" calln print 1 pushi 2 1 store 1 -_private_5: +_private_0: load 1 pushi 2 5 op2 8 - jmp_if_not _private_6 + jmp_if_not _private_1 pusht "\n" load 1 calln print 2 @@ -121,232 +32,9 @@ _private_5: op2 0 store 1 - jmp _private_5 -_private_6: + jmp _private_0 +_private_1: ret ; end of main - - - -; 0, translateKeyCode -translateKeyCode: - pushnil ; return value - pusht "]\n" - load -2 - pusht ",scancode=" - load -1 - pusht "[extend=" - calln print 5 - - pushi 2 0 - store 0 - - load -1 - pushi 2 0 - op2 5 - jmp_if_not _private_7 - load -2 - pushi 2 10 - op2 5 - jmp_if_not _private_8 - pushi 2 1 - store 0 - - load 0 - retr - -_private_8: - -_private_7: - - load 0 - retr -; end of translateKeyCode - -; 0, handleKeyboardIRQ -handleKeyboardIRQ: - pushnil ; return value - pushnil ; scancode:UINT8 - pushnil ; keycode:INT32 - pushnil ; breakcode:BOOL - pushi 2 0 - store 2 - - pushi 6 0 - store 3 - - pushi 4 96 - callnr inb 1 - store 1 - - load 1 - pushi 3 128 - op2 12 - pushi 3 0 - op2 6 - loadg e1Code - pushi 2 0 - op2 6 - load 1 - pushi 3 225 - op2 6 - op2 11 - loadg e0Code - load 1 - pushi 3 224 - op2 6 - op2 11 - op2 12 - op2 12 - jmp_if_not _private_9 - pushi 6 1 - store 3 - - load 1 - pushi 3 127 - op2 12 - store 1 - -_private_9: - - load 1 - pushi 3 1 - op2 5 - jmp_if_not _private_10 - calln shutdown 0 - - ret - -_private_10: - - loadg e0Code - jmp_if_not _private_11 - load 1 - pushi 3 42 - op2 5 - load 1 - pushi 3 54 - op2 5 - op2 11 - jmp_if_not _private_13 - pushi 6 0 - storeg e0Code - - ret - -_private_13: - - load 1 - callnr toInt32 1 - pushi 2 1 - callr translateKeyCode 2 - store 2 - - pushi 6 0 - storeg e0Code - - jmp _private_12 -_private_11: - loadg e1Code - pushi 2 2 - op2 5 - jmp_if_not _private_14 - loadg e1Prev - load 1 - pushi 3 256 - op2 2 - callnr toUInt16 1 - op2 11 - storeg e1Prev - - loadg e1Prev - callnr toInt32 1 - pushi 2 2 - callr translateKeyCode 2 - store 2 - - pushi 2 0 - storeg e1Code - - jmp _private_15 -_private_14: - loadg e1Code - pushi 2 1 - op2 5 - jmp_if_not _private_16 - load 1 - callnr toUInt16 1 - storeg e1Prev - - pushi 2 2 - storeg e1Code - - jmp _private_17 -_private_16: - load 1 - pushi 3 224 - op2 5 - jmp_if_not _private_18 - pushi 6 1 - storeg e0Code - - jmp _private_19 -_private_18: - load 1 - pushi 3 225 - op2 5 - jmp_if_not _private_20 - pushi 2 1 - storeg e1Code - - jmp _private_21 -_private_20: - load 1 - callnr toInt32 1 - pushi 2 0 - callr translateKeyCode 2 - store 2 - -_private_21: - -_private_19: - -_private_17: - -_private_15: - -_private_12: - - load 2 - pushi 2 0 - op2 6 - jmp_if_not _private_22 - load 3 - load 2 - call handleKeyPress 2 - -_private_22: - - ret -; end of handleKeyboardIRQ - -; 1, irq -.export irq -irq: - pushnil ; return value - load -1 - pushi 2 33 - op2 5 - jmp_if_not _private_23 - call handleKeyboardIRQ 0 - -_private_23: - - load -2 - destruct - - ret -; end of irq - diff --git a/src/init.c b/src/init.c index 0d4574d..0feedf9 100644 --- a/src/init.c +++ b/src/init.c @@ -8,6 +8,13 @@ #include #include +static void halt() +{ + while(1) { + __asm__ volatile ("cli; hlt;"); + } +} + void die(const char *msg) { die_extra(msg, ""); @@ -23,10 +30,7 @@ void die_extra(const char *msg, const char *extra) kputs(extra); kputc('\''); } - while(1) - { - __asm__ volatile ("cli; hlt;"); - } + halt(); } extern size_t mallocCount; @@ -93,42 +97,42 @@ static void debug_test() static void dumpMB(const MultibootStructure *mbHeader) { - kputs("Multiboot Information:\n"); + serial_printf(SERIAL_COM1, "Multiboot Information:\n"); if(mbHeader->flags & MB_MEMSIZE) { - kprintf("Lower Memory: %d kB\n", mbHeader->memLower); - kprintf("Upper Memory: %d kB\n", mbHeader->memUpper); + serial_printf(SERIAL_COM1, " Lower Memory: %d kB\n", mbHeader->memLower); + serial_printf(SERIAL_COM1, " Upper Memory: %d kB\n", mbHeader->memUpper); } // TODO: MB_BOOTDEVICE if(mbHeader->flags & MB_COMMANDLINE) { - kprintf("Commandline: %s\n", (const char*)mbHeader->commandline); + serial_printf(SERIAL_COM1, " Commandline: %s\n", (const char*)mbHeader->commandline); } if(mbHeader->flags & MB_MODULES) { const MultibootModule *mod = (const MultibootModule *)mbHeader->modules; for(size_t i = 0; i < mbHeader->moduleCount; i++) { - kprintf("Module %s [%d - %d]\n", (const char*)mod[i].name, mod[i].start, mod[i].end); + serial_printf(SERIAL_COM1, " Module %s [%d - %d]\n", (const char*)mod[i].name, mod[i].start, mod[i].end); } } if(mbHeader->flags & MB_SYMS_AOUT) { - kputs("Kernel File Format: a.out\n"); + serial_printf(SERIAL_COM1, " Kernel File Format: a.out\n"); } if(mbHeader->flags & MB_SYMS_ELF) { - kputs("Kernel File Format: ELF\n"); + serial_printf(SERIAL_COM1, " Kernel File Format: ELF\n"); } if(mbHeader->flags & MB_MEMORYMAP) { uintptr_t it = mbHeader->memoryMap; - kprintf("Memory Map: %d entries\n", mbHeader->memoryMapLength); + serial_printf(SERIAL_COM1, " Memory Map: %d entries\n", mbHeader->memoryMapLength); for(size_t i = 0; i < mbHeader->memoryMapLength; i++) { const MultibootMemoryMap *mmap = (const MultibootMemoryMap *)it; if(mmap->type == 1) - kprintf("Memory Map: [%d + %d] %s\n", (uint32_t)mmap->base, (uint32_t)mmap->length, mmap->type == 1 ? "free" : "preserved"); + serial_printf(SERIAL_COM1, " Memory Map: [%d + %d] %s\n", (uint32_t)mmap->base, (uint32_t)mmap->length, mmap->type == 1 ? "free" : "preserved"); it += mmap->entry_size + 4; // Stupid offset :P } } @@ -136,7 +140,7 @@ static void dumpMB(const MultibootStructure *mbHeader) // TODO: MB_CONFIG_TABLE if(mbHeader->flags & MB_BOOTLOADER_NAME) { - kprintf("Bootloader Name: %s\n", (const char*)mbHeader->bootLoaderName); + serial_printf(SERIAL_COM1, " Bootloader Name: %s\n", (const char*)mbHeader->bootLoaderName); } // TODO: MB_APS_TABLE } @@ -152,7 +156,7 @@ void putsuccess() kputs("[success]"); } -extern void vm_start(); +extern void vm_start(const MultibootStructure *mbHeader); void init(const MultibootStructure *mbHeader) { @@ -166,7 +170,11 @@ void init(const MultibootStructure *mbHeader) serial_init(SERIAL_COM1, 9600, SERIAL_PARITY_NONE, 8); serial_write_str(SERIAL_COM1, "Debug Console Ready\n"); - //dumpMB(mbHeader); + dumpMB(mbHeader); + + if(((mbHeader->flags & MB_MODULES) == 0) || (mbHeader->moduleCount == 0)) { + die_extra("BootProcessFailed", "No initial OS modules found."); + } kputs("Initialize physical memory management: "); pmm_init(mbHeader); @@ -210,7 +218,7 @@ void init(const MultibootStructure *mbHeader) kputs("\n"); - vm_start(); + vm_start(mbHeader); irq_disable(); @@ -222,7 +230,7 @@ void init(const MultibootStructure *mbHeader) malloc_print_list(0); #endif - while(1); + halt(); } int main(int argc, char **argv) diff --git a/src/vm.cpp b/src/vm.cpp index a339c1a..1f415e2 100644 --- a/src/vm.cpp +++ b/src/vm.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include @@ -13,16 +14,6 @@ #include "../csl/io.hpp" #include "../csl/casts.hpp" -extern "C" { - extern const char mainscript_start; - extern const char mainscript_end; - extern const char mainscript_size; - - extern const char firstrun_start; - extern const char firstrun_end; - extern const char firstrun_size; -} - void printVMValue(const VMValue &value) { switch(value.type().type()) { @@ -62,15 +53,6 @@ struct dtortest { ~dtortest() { free(mem); kprintf("[free]"); } } ;// object; - -struct { - const char *ptr; - uint32_t size; -} mainAssembly { - &mainscript_start, - (uint32_t)&mainscript_size -}; - struct IrqList { static const size_t length = 64; volatile uint32_t read; @@ -127,7 +109,7 @@ ExceptionCode shutdown(VMValue &, const VMArray &) int ReferenceCounted::counter = 0; -extern "C" void vm_start() +extern "C" void vm_start(const MultibootStructure *mbHeader) { // intr_set_handler(0x20, vm_handle_interrupt); intr_set_handler(0x21, vm_handle_interrupt); @@ -148,26 +130,83 @@ extern "C" void vm_start() machine.import("toUInt16") = csl::toUInt16; machine.import("toUInt32") = csl::toUInt32; - Assembly *assembly = machine.load(mainAssembly.ptr, mainAssembly.size); - if(assembly == nullptr) { - kprintf("failed to load assembly :(\n"); - return; + using DriverProcess = ker::Pair; + ker::Vector drivers; + + const MultibootModule *mod = (const MultibootModule *)mbHeader->modules; + for(size_t i = 0; i < mbHeader->moduleCount; i++) + { + kprintf("Loading Module '%s'...\n", (const char*)mod[i].name); + + size_t len = mod[i].end - mod[i].start; + + Assembly *assembly = machine.load(reinterpret_cast(mod[i].start), len); + if(assembly == nullptr) { + die("Failed to load assembly."); + return; + } + switch(assembly->type()) + { + case AssemblyType::Library: + { + // Assemblies don't need special treatment + break; + } + case AssemblyType::Executable: + { + Process *program = machine.createProcess(assembly, false); + if(program == nullptr) { + die("Failed to create process."); + return; + } + program->release(); + break; + } + case AssemblyType::Service: + { + Process *program = machine.createProcess(assembly, true); + if(program == nullptr) { + die("Failed to create service process."); + return; + } + program->release(); + break; + } + case AssemblyType::Driver: + { + Process *program = machine.createProcess(assembly, true); + if(program == nullptr) { + die("Failed to create driver process."); + return; + } + if(assembly->exports().contains("irq")) { + drivers.append({ program, assembly->exports()["irq"] }); + } else { + program->release(); + } + break; + } + default: + { + die("OS.UnknownAssemblyType"); + break; + } + } + assembly->release(); } - Process *irqService = machine.createProcess(assembly, true); - if(irqService == nullptr) { - kprintf("Failed to create process.\n"); - return; - } - - Thread *mainThread = irqService->mainThread(); - - uint32_t irqRoutine = irqService->assembly()->exports()["irq"]; - - bool osIsFailed = false; - while((shutdownRequested == false) && machine.step()) { + // Remove all terminated drivers + for(size_t i = 0; i < drivers.length(); ) { + if(drivers[i].first->isRunning()) { + i++; + } else { + drivers[i].first->release(); + drivers.remove(i); + } + } + // check for IRQ requests do { @@ -182,14 +221,14 @@ extern "C" void vm_start() CpuState *cpu = &irqFiFo.items[irqFiFo.read]; - //* - Thread *thread = irqService->createThread(irqRoutine); - thread->start({ - VMValue::Int32(cpu->intr), - csl::createCpuState(cpu) - }); - thread->release(); - // */ + for(const auto &driver : drivers) { + Thread *thread = driver.first->createThread(driver.second); + thread->start({ + VMValue::Int32(cpu->intr), + csl::createCpuState(cpu) + }); + thread->release(); + } irqFiFo.read += 1; irq_disable(); @@ -200,25 +239,7 @@ extern "C" void vm_start() } irq_enable(); } while(true); - - if(mainThread->isRunning() == false) { - if(osIsFailed == false) { - osIsFailed = true; - - kprintf("OS failed with: %s\n", execptionName(mainThread->exception())); - - // shutdownRequested = true; - } - } } - mainThread->release(); - mainThread = nullptr; - - irqService->release(); - irqService = nullptr; - - assembly->release(); - assembly = nullptr; } kprintf("\n"); kprintf("unreleased objects: %d\n", ReferenceCounted::counter); diff --git a/trainOS.pro b/trainOS.pro index 8f7549b..becb14b 100644 --- a/trainOS.pro +++ b/trainOS.pro @@ -59,7 +59,8 @@ DISTFILES += \ asm/dynamic.S \ README.md \ scripts/main.spark \ - scripts/main.cu + scripts/main.cu \ + scripts/keyboard.cu INCLUDEPATH += include DEPENDPATH += include