Adds starting processes via multiboot modules. Removes built-in module. Splits main.cu in main.cu and keyboard.cu.

This commit is contained in:
Felix Queissner 2015-10-16 14:05:37 +02:00
parent 6599c6c306
commit ebb537d5e1
9 changed files with 618 additions and 582 deletions

27
Depfile
View file

@ -2,9 +2,11 @@
Artifact=kernel Artifact=kernel
TempDir=obj TempDir=obj
SourceDir=asm src csl SourceDir=asm src csl
AdditionalObjects=obj/main.o AdditionalObjects=
ExternalObjects=conductance/|*.o ExternalObjects=conductance/|*.o
AdditionalDependencies=obj/main.in obj/keyboard.in
LexUseCpp LexUseCpp
YaccUseCpp YaccUseCpp
@ -28,25 +30,28 @@ LDFLAGS=-nostdlib -fno-builtin -Tkernel.ld
TOOLS=/home/felix/projects/Electronics/build-Electronics-Clang-Debug/bin TOOLS=/home/felix/projects/Electronics/build-Electronics-Clang-Debug/bin
obj/main.o: scripts/main.cu obj/main.in: scripts/main.cu
$(TOOLS)/copper \ $(TOOLS)/copper \
scripts/main.cu > \ scripts/main.cu > \
scripts/main.cu.spark scripts/main.cu.spark
$(TOOLS)/spark \ $(TOOLS)/spark \
scripts/main.cu.spark \ scripts/main.cu.spark \
obj/main.in obj/main.in
objcopy -B i386 -I binary -O elf32-i386 \
obj/main.in obj/main.o obj/keyboard.in: scripts/keyboard.cu
objcopy \ $(TOOLS)/copper \
--redefine-sym _binary_obj_main_in_start=mainscript_start \ scripts/keyboard.cu > \
--redefine-sym _binary_obj_main_in_end=mainscript_end \ scripts/keyboard.cu.spark
--redefine-sym _binary_obj_main_in_size=mainscript_size \ $(TOOLS)/spark \
obj/main.o scripts/keyboard.cu.spark \
obj/keyboard.in
QEMUFLAGS=-serial stdio -kernel kernel -initrd obj/main.in,obj/keyboard.in
.PHONY: run .PHONY: run
run: run:
qemu-system-i386 -serial stdio -kernel kernel qemu-system-i386 $(QEMUFLAGS)
.PHONY: debug .PHONY: debug
debug: debug:
qemu-system-i386 -s -S -serial stdio -kernel kernel qemu-system-i386 -s -S $(QEMUFLAGS)

View file

@ -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_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_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 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
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 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 .PHONY: clean
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 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 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 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 # src/console.c
obj/console.o: src/console.c include/console.h include/kstdlib.h \ 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 # src/vm.cpp
obj/vm.o: src/vm.cpp include/kstdlib.h include/varargs.h include/config.h \ 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/malloc.h include/timer.h include/dynamic.h include/console.h \
include/interrupts.h include/cpustate.h src/../csl/cpustatetype.hpp \ include/multiboot.h include/interrupts.h include/cpustate.h \
src/../csl/io.hpp src/../csl/casts.hpp src/../csl/cpustatetype.hpp src/../csl/io.hpp src/../csl/casts.hpp
$(CXX) -iquoteobj $(FLAGS) $(CXXFLAGS) -o $@ -c src/vm.cpp $(CXX) -iquoteobj $(FLAGS) $(CXXFLAGS) -o $@ -c src/vm.cpp
# csl/casts.cpp # csl/casts.cpp
@ -129,25 +129,28 @@ obj/start.o: asm/start.S
TOOLS=/home/felix/projects/Electronics/build-Electronics-Clang-Debug/bin TOOLS=/home/felix/projects/Electronics/build-Electronics-Clang-Debug/bin
obj/main.o: scripts/main.cu obj/main.in: scripts/main.cu
$(TOOLS)/copper \ $(TOOLS)/copper \
scripts/main.cu > \ scripts/main.cu > \
scripts/main.cu.spark scripts/main.cu.spark
$(TOOLS)/spark \ $(TOOLS)/spark \
scripts/main.cu.spark \ scripts/main.cu.spark \
obj/main.in obj/main.in
objcopy -B i386 -I binary -O elf32-i386 \
obj/main.in obj/main.o obj/keyboard.in: scripts/keyboard.cu
objcopy \ $(TOOLS)/copper \
--redefine-sym _binary_obj_main_in_start=mainscript_start \ scripts/keyboard.cu > \
--redefine-sym _binary_obj_main_in_end=mainscript_end \ scripts/keyboard.cu.spark
--redefine-sym _binary_obj_main_in_size=mainscript_size \ $(TOOLS)/spark \
obj/main.o scripts/keyboard.cu.spark \
obj/keyboard.in
QEMUFLAGS=-serial stdio -kernel kernel -initrd obj/main.in,obj/keyboard.in
.PHONY: run .PHONY: run
run: run:
qemu-system-i386 -serial stdio -kernel kernel qemu-system-i386 $(QEMUFLAGS)
.PHONY: debug .PHONY: debug
debug: debug:
qemu-system-i386 -s -S -serial stdio -kernel kernel qemu-system-i386 -s -S $(QEMUFLAGS)

154
scripts/keyboard.cu Normal file
View file

@ -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
!#

313
scripts/keyboard.cu.spark Normal file
View file

@ -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

View file

@ -2,58 +2,8 @@ NATIVE print(...);
NATIVE shutdown(); 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 PUB main() | i : INT
BEGIN BEGIN
print("Initialize keyboard...\n");
initKeyboard();
print("Hello World!\n"); print("Hello World!\n");
1 → i; 1 → i;
WHILE i <= 5 DO WHILE i <= 5 DO
@ -61,110 +11,3 @@ BEGIN
(i + 1) → i; (i + 1) → i;
END END
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
!#

View file

@ -1,117 +1,28 @@
; ============================================= ; =============================================
; compiled with Copper 1.0 ; compiled with Copper 1.0
; 2015-10-14 21:08:00 ; 2015-10-16 13:32:19
; ============================================= ; =============================================
; native method: print(…) ; native method: print(…)
; native method: shutdown(…) ; 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 ; 1, main
.export main .export main
main: main:
pushnil ; return value pushnil ; return value
pushnil ; i:INT32 pushnil ; i:INT32
pusht "Initialize keyboard...\n"
calln print 1
call initKeyboard 0
pusht "Hello World!\n" pusht "Hello World!\n"
calln print 1 calln print 1
pushi 2 1 pushi 2 1
store 1 store 1
_private_5: _private_0:
load 1 load 1
pushi 2 5 pushi 2 5
op2 8 op2 8
jmp_if_not _private_6 jmp_if_not _private_1
pusht "\n" pusht "\n"
load 1 load 1
calln print 2 calln print 2
@ -121,232 +32,9 @@ _private_5:
op2 0 op2 0
store 1 store 1
jmp _private_5 jmp _private_0
_private_6: _private_1:
ret ret
; end of main ; 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

View file

@ -8,6 +8,13 @@
#include <config.h> #include <config.h>
#include <serial.h> #include <serial.h>
static void halt()
{
while(1) {
__asm__ volatile ("cli; hlt;");
}
}
void die(const char *msg) void die(const char *msg)
{ {
die_extra(msg, ""); die_extra(msg, "");
@ -23,10 +30,7 @@ void die_extra(const char *msg, const char *extra)
kputs(extra); kputs(extra);
kputc('\''); kputc('\'');
} }
while(1) halt();
{
__asm__ volatile ("cli; hlt;");
}
} }
extern size_t mallocCount; extern size_t mallocCount;
@ -93,42 +97,42 @@ static void debug_test()
static void dumpMB(const MultibootStructure *mbHeader) static void dumpMB(const MultibootStructure *mbHeader)
{ {
kputs("Multiboot Information:\n"); serial_printf(SERIAL_COM1, "Multiboot Information:\n");
if(mbHeader->flags & MB_MEMSIZE) if(mbHeader->flags & MB_MEMSIZE)
{ {
kprintf("Lower Memory: %d kB\n", mbHeader->memLower); serial_printf(SERIAL_COM1, " Lower Memory: %d kB\n", mbHeader->memLower);
kprintf("Upper Memory: %d kB\n", mbHeader->memUpper); serial_printf(SERIAL_COM1, " Upper Memory: %d kB\n", mbHeader->memUpper);
} }
// TODO: MB_BOOTDEVICE // TODO: MB_BOOTDEVICE
if(mbHeader->flags & MB_COMMANDLINE) 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) if(mbHeader->flags & MB_MODULES)
{ {
const MultibootModule *mod = (const MultibootModule *)mbHeader->modules; const MultibootModule *mod = (const MultibootModule *)mbHeader->modules;
for(size_t i = 0; i < mbHeader->moduleCount; i++) 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) 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) 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) if(mbHeader->flags & MB_MEMORYMAP)
{ {
uintptr_t it = mbHeader->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++) for(size_t i = 0; i < mbHeader->memoryMapLength; i++)
{ {
const MultibootMemoryMap *mmap = (const MultibootMemoryMap *)it; const MultibootMemoryMap *mmap = (const MultibootMemoryMap *)it;
if(mmap->type == 1) 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 it += mmap->entry_size + 4; // Stupid offset :P
} }
} }
@ -136,7 +140,7 @@ static void dumpMB(const MultibootStructure *mbHeader)
// TODO: MB_CONFIG_TABLE // TODO: MB_CONFIG_TABLE
if(mbHeader->flags & MB_BOOTLOADER_NAME) 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 // TODO: MB_APS_TABLE
} }
@ -152,7 +156,7 @@ void putsuccess()
kputs("[success]"); kputs("[success]");
} }
extern void vm_start(); extern void vm_start(const MultibootStructure *mbHeader);
void init(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_init(SERIAL_COM1, 9600, SERIAL_PARITY_NONE, 8);
serial_write_str(SERIAL_COM1, "Debug Console Ready\n"); 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: "); kputs("Initialize physical memory management: ");
pmm_init(mbHeader); pmm_init(mbHeader);
@ -210,7 +218,7 @@ void init(const MultibootStructure *mbHeader)
kputs("\n"); kputs("\n");
vm_start(); vm_start(mbHeader);
irq_disable(); irq_disable();
@ -222,7 +230,7 @@ void init(const MultibootStructure *mbHeader)
malloc_print_list(0); malloc_print_list(0);
#endif #endif
while(1); halt();
} }
int main(int argc, char **argv) int main(int argc, char **argv)

View file

@ -2,6 +2,7 @@
#include <timer.h> #include <timer.h>
#include <dynamic.h> #include <dynamic.h>
#include <console.h> #include <console.h>
#include <multiboot.h>
#include <virtualmachine.hpp> #include <virtualmachine.hpp>
#include <vmtype.hpp> #include <vmtype.hpp>
@ -13,16 +14,6 @@
#include "../csl/io.hpp" #include "../csl/io.hpp"
#include "../csl/casts.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) void printVMValue(const VMValue &value)
{ {
switch(value.type().type()) { switch(value.type().type()) {
@ -62,15 +53,6 @@ struct dtortest {
~dtortest() { free(mem); kprintf("[free]"); } ~dtortest() { free(mem); kprintf("[free]"); }
} ;// object; } ;// object;
struct {
const char *ptr;
uint32_t size;
} mainAssembly {
&mainscript_start,
(uint32_t)&mainscript_size
};
struct IrqList { struct IrqList {
static const size_t length = 64; static const size_t length = 64;
volatile uint32_t read; volatile uint32_t read;
@ -127,7 +109,7 @@ ExceptionCode shutdown(VMValue &, const VMArray &)
int ReferenceCounted::counter = 0; 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(0x20, vm_handle_interrupt);
intr_set_handler(0x21, 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("toUInt16") = csl::toUInt16;
machine.import("toUInt32") = csl::toUInt32; machine.import("toUInt32") = csl::toUInt32;
Assembly *assembly = machine.load(mainAssembly.ptr, mainAssembly.size); using DriverProcess = ker::Pair<Process*,uint32_t>;
if(assembly == nullptr) { ker::Vector<DriverProcess> drivers;
kprintf("failed to load assembly :(\n");
return; 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<void*>(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()) 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 // check for IRQ requests
do do
{ {
@ -182,14 +221,14 @@ extern "C" void vm_start()
CpuState *cpu = &irqFiFo.items[irqFiFo.read]; CpuState *cpu = &irqFiFo.items[irqFiFo.read];
//* for(const auto &driver : drivers) {
Thread *thread = irqService->createThread(irqRoutine); Thread *thread = driver.first->createThread(driver.second);
thread->start({ thread->start({
VMValue::Int32(cpu->intr), VMValue::Int32(cpu->intr),
csl::createCpuState(cpu) csl::createCpuState(cpu)
}); });
thread->release(); thread->release();
// */ }
irqFiFo.read += 1; irqFiFo.read += 1;
irq_disable(); irq_disable();
@ -200,25 +239,7 @@ extern "C" void vm_start()
} }
irq_enable(); irq_enable();
} while(true); } 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("\n");
kprintf("unreleased objects: %d\n", ReferenceCounted::counter); kprintf("unreleased objects: %d\n", ReferenceCounted::counter);

View file

@ -59,7 +59,8 @@ DISTFILES += \
asm/dynamic.S \ asm/dynamic.S \
README.md \ README.md \
scripts/main.spark \ scripts/main.spark \
scripts/main.cu scripts/main.cu \
scripts/keyboard.cu
INCLUDEPATH += include INCLUDEPATH += include
DEPENDPATH += include DEPENDPATH += include