Refactored into multiple files
This commit is contained in:
parent
0fa405dd98
commit
880118e7b4
12
Makefile
12
Makefile
@ -1,9 +1,15 @@
|
|||||||
|
#TODO make the makefile use targets instead of this mess
|
||||||
all:
|
all:
|
||||||
nasm boot.nasm -o boot.bin
|
nasm boot.nasm -o boot.bin
|
||||||
nasm -f elf32 -o entry.o entry.nasm
|
nasm -f elf32 -o entry.o entry.nasm
|
||||||
clang -target "i686-elf" -ffreestanding -m32 -march=pentium-m -fno-stack-protector -nostdlib -c -o kernel.o kernel.c
|
nasm -f elf32 -o handler.o handler.nasm
|
||||||
#clang -target "i686-elf" -O2 -ffreestanding -m32 -march=i386 -fno-stack-protector -nostdlib -c -o kernel.o kernel.c
|
nasm -f elf32 -o v86.o v86.nasm
|
||||||
gcc -Tlink.ld -m32 -ffreestanding -nostartfiles -nostdlib -o kernel.bin entry.o kernel.o
|
clang -target "i686-elf" -ffreestanding -m32 -O2 -march=pentium-m -fno-stack-protector -nostdlib -c kernel.c
|
||||||
|
clang -target "i686-elf" -ffreestanding -m32 -O2 -mgeneral-regs-only -march=pentium-m -fno-stack-protector -nostdlib -c print.c
|
||||||
|
# not sure why but if interrupt.c has any optimization everything just breaks immediately
|
||||||
|
clang -target "i686-elf" -ffreestanding -m32 -mgeneral-regs-only -march=pentium-m -fno-stack-protector -nostdlib -c interrupt.c
|
||||||
|
#clang -target "i686-elf" -ffreestanding -m32 -mgeneral-regs-only -march=i386 -fno-stack-protector -nostdlib -c -o kernel.o kernel.c
|
||||||
|
gcc -Tlink.ld -m32 -ffreestanding -nostartfiles -nostdlib -o kernel.bin entry.o v86.o handler.o kernel.o print.o interrupt.o
|
||||||
dd bs=256 count=1 conv=notrunc if=boot.bin of=virtdisk.bin
|
dd bs=256 count=1 conv=notrunc if=boot.bin of=virtdisk.bin
|
||||||
dd bs=512 seek=1 conv=notrunc if=kernel.bin of=virtdisk.bin
|
dd bs=512 seek=1 conv=notrunc if=kernel.bin of=virtdisk.bin
|
||||||
virtdisk:
|
virtdisk:
|
||||||
|
221
entry.nasm
221
entry.nasm
@ -1,5 +1,4 @@
|
|||||||
[BITS 16]
|
[BITS 16]
|
||||||
|
|
||||||
global entry
|
global entry
|
||||||
entry:
|
entry:
|
||||||
cli ; no interrupts
|
cli ; no interrupts
|
||||||
@ -22,12 +21,16 @@ mov esp, ebp
|
|||||||
mov eax, 0x1f001f00
|
mov eax, 0x1f001f00
|
||||||
mov ecx, (80*25)/2
|
mov ecx, (80*25)/2
|
||||||
mov edi, 0xb8000
|
mov edi, 0xb8000
|
||||||
rep stosd
|
rep stosd ; clear screen
|
||||||
call start
|
call start
|
||||||
hlt_loop:
|
hlt_loop:
|
||||||
hlt
|
hlt
|
||||||
jmp hlt_loop
|
jmp hlt_loop
|
||||||
|
|
||||||
|
extern start
|
||||||
|
|
||||||
|
; currently unused first 8MB identity paging
|
||||||
|
; taken from Linux 0.01
|
||||||
setup_paging:
|
setup_paging:
|
||||||
mov ecx, 1024*3 ; 3K?
|
mov ecx, 1024*3 ; 3K?
|
||||||
xor eax, eax
|
xor eax, eax
|
||||||
@ -50,87 +53,6 @@ or eax, 0x80000000
|
|||||||
mov cr0, eax ; set paging bit
|
mov cr0, eax ; set paging bit
|
||||||
ret ; flushes pre-fetch queue
|
ret ; flushes pre-fetch queue
|
||||||
|
|
||||||
[BITS 16]
|
|
||||||
real_hexprint:
|
|
||||||
xor cx, cx
|
|
||||||
mov bl, al
|
|
||||||
shr al, 4
|
|
||||||
jmp .donibble
|
|
||||||
.nibble2:
|
|
||||||
mov al, bl
|
|
||||||
inc cx
|
|
||||||
.donibble:
|
|
||||||
and al, 0x0F
|
|
||||||
cmp al, 0x0A
|
|
||||||
jl .noadjust
|
|
||||||
add al, 'A' - '0' - 10
|
|
||||||
.noadjust:
|
|
||||||
add al, '0'
|
|
||||||
mov ah, 0x1f
|
|
||||||
stosw
|
|
||||||
test cx, cx
|
|
||||||
jz .nibble2
|
|
||||||
ret
|
|
||||||
real_printword:
|
|
||||||
mov dx, ax
|
|
||||||
mov al, ah
|
|
||||||
call real_hexprint
|
|
||||||
mov ax, dx
|
|
||||||
call real_hexprint
|
|
||||||
ret
|
|
||||||
extern v86Code
|
|
||||||
v86Code:
|
|
||||||
mov ax, 0xb814
|
|
||||||
mov es, ax
|
|
||||||
mov di, 20
|
|
||||||
mov ax, sp
|
|
||||||
call real_printword
|
|
||||||
add di, 2
|
|
||||||
mov ax, ds
|
|
||||||
call real_printword
|
|
||||||
add di, 2
|
|
||||||
mov ax, cs
|
|
||||||
call real_printword
|
|
||||||
.loop:
|
|
||||||
inc byte [0]
|
|
||||||
;mov ax, 0x1111
|
|
||||||
;mov ds, ax
|
|
||||||
;mov ax, 0x2222
|
|
||||||
;mov es, ax
|
|
||||||
;mov ax, 0x3333
|
|
||||||
;mov fs, ax
|
|
||||||
;mov ax, 0x4444
|
|
||||||
;mov gs, ax
|
|
||||||
;mov ax, 0x5555
|
|
||||||
;mov ss, ax
|
|
||||||
;mov ax, 0x6666
|
|
||||||
;mov sp, ax
|
|
||||||
int 3
|
|
||||||
;jmp .loop
|
|
||||||
mov ax, 0x13
|
|
||||||
int 0x10
|
|
||||||
int 0x30 ; exit
|
|
||||||
jmp $
|
|
||||||
extern real_test
|
|
||||||
real_test:
|
|
||||||
nop
|
|
||||||
nop
|
|
||||||
nop
|
|
||||||
jmp $
|
|
||||||
[BITS 32]
|
|
||||||
; extern void enter_v86(uint32_t ss, uint32_t esp, uint32_t cs, uint32_t eip);
|
|
||||||
global enter_v86
|
|
||||||
enter_v86:
|
|
||||||
mov ebp, esp ; save stack pointer
|
|
||||||
push dword [ebp+4] ; ss
|
|
||||||
push dword [ebp+8] ; esp
|
|
||||||
pushfd ; eflags
|
|
||||||
or dword [esp], (1 << 17) ; set VM flags
|
|
||||||
;or dword [esp], (3 << 12) ; IOPL 3
|
|
||||||
push dword [ebp+12] ; cs
|
|
||||||
push dword [ebp+16] ; eip
|
|
||||||
iret
|
|
||||||
|
|
||||||
user_test:
|
user_test:
|
||||||
mov dword [0xb8000], 0x0f000f00 | 'U' | 's' << 16
|
mov dword [0xb8000], 0x0f000f00 | 'U' | 's' << 16
|
||||||
mov dword [0xb8004], 0x0f000f00 | 'e' | 'r' << 16
|
mov dword [0xb8004], 0x0f000f00 | 'e' | 'r' << 16
|
||||||
@ -163,137 +85,6 @@ push 0x18 | 3
|
|||||||
push user_test
|
push user_test
|
||||||
iret
|
iret
|
||||||
|
|
||||||
extern unhandled_handler
|
|
||||||
unhandled_handler:
|
|
||||||
mov ax, 0x10
|
|
||||||
mov ds, ax
|
|
||||||
mov dword [0xb8000], 0x0f000f00 | 'E' | 'R' << 16
|
|
||||||
mov dword [0xb8004], 0x0f000f00 | 'R' | 'O' << 16
|
|
||||||
mov dword [0xb8008], 0x0f000f00 | 'R' | '!' << 16
|
|
||||||
.hlt:
|
|
||||||
hlt
|
|
||||||
jmp .hlt
|
|
||||||
|
|
||||||
extern gpf_handler_v86
|
|
||||||
global gpfHandler
|
|
||||||
gpfHandler:
|
|
||||||
iret
|
|
||||||
mov ax, 0x10
|
|
||||||
mov ds, ax
|
|
||||||
;jmp gpf_handler_v86
|
|
||||||
mov word [0xb8000], 0x0f00 | 'G'
|
|
||||||
mov word [0xb8002], 0x0f00 | 'P'
|
|
||||||
mov word [0xb8004], 0x0f00 | 'F'
|
|
||||||
.hlt:
|
|
||||||
hlt
|
|
||||||
jmp .hlt
|
|
||||||
|
|
||||||
scancodesToAscii: db 0, 0 ; 0x00 - 0x01
|
|
||||||
db "1234567890" ; 0x02 - 0x0B
|
|
||||||
db "-=" ; 0x0C - 0x0D
|
|
||||||
db 0, 0 ; 0x0E - 0x0F
|
|
||||||
db "qwertyuiop[]" ; 0x10 - 0x1B
|
|
||||||
db 0, 0 ; 0x1C - 0x1D
|
|
||||||
db "asdfghjkl;'`" ; 0x1E - 0x29
|
|
||||||
db 0 ; 0x2A
|
|
||||||
db "\zxcvbnm,./" ; 0x2B - 0x35
|
|
||||||
db 0 ; 0x36
|
|
||||||
db '*' ; 0x37
|
|
||||||
db 0 ; 0x38
|
|
||||||
db ' ' ; 0x39
|
|
||||||
db 'C'
|
|
||||||
scancodesToAsciiEnd:
|
|
||||||
cursorCurrent: dd 0xb8000 + (80*6*2)
|
|
||||||
global keyboardHandler
|
|
||||||
keyboardHandler:
|
|
||||||
push eax
|
|
||||||
push ebx
|
|
||||||
push ds
|
|
||||||
mov ax, 0x10
|
|
||||||
mov ds, ax
|
|
||||||
xor eax, eax
|
|
||||||
in al, 0x60
|
|
||||||
cmp eax, 0x3A
|
|
||||||
jg .done
|
|
||||||
mov al, [scancodesToAscii+eax]
|
|
||||||
test al, al
|
|
||||||
jz .done
|
|
||||||
mov ebx, [cursorCurrent]
|
|
||||||
mov byte [ebx], al
|
|
||||||
add dword [cursorCurrent], 2
|
|
||||||
mov byte [KBDWAIT], 1
|
|
||||||
.done:
|
|
||||||
mov al, 0x20
|
|
||||||
out 0x20, al
|
|
||||||
pop ds
|
|
||||||
pop ebx
|
|
||||||
pop eax
|
|
||||||
iret
|
|
||||||
|
|
||||||
KBDWAIT: db 0
|
|
||||||
global kbd_wait
|
|
||||||
kbd_wait:
|
|
||||||
mov byte [KBDWAIT], 0
|
|
||||||
.loop:
|
|
||||||
hlt
|
|
||||||
xor eax, eax
|
|
||||||
mov al, [KBDWAIT]
|
|
||||||
test eax, eax
|
|
||||||
jz .loop
|
|
||||||
ret
|
|
||||||
|
|
||||||
global timerHandler
|
|
||||||
timerHandler:
|
|
||||||
push eax
|
|
||||||
push ds
|
|
||||||
mov ax, 0x10
|
|
||||||
mov ds, ax
|
|
||||||
inc byte [(0xb8000 + (80*8*2))]
|
|
||||||
mov al, 0x20
|
|
||||||
out 0x20, al
|
|
||||||
pop ds
|
|
||||||
pop eax
|
|
||||||
iret
|
|
||||||
|
|
||||||
global picInit
|
|
||||||
picInit:
|
|
||||||
mov al, 0x11 ; initialization sequence
|
|
||||||
out 0x20, al ; send to 8259A-1
|
|
||||||
jmp $+2
|
|
||||||
jmp $+2
|
|
||||||
out 0xA0, al ; and to 8259A-2
|
|
||||||
jmp $+2
|
|
||||||
jmp $+2
|
|
||||||
mov al, 0x20 ; start of hardware ints (0x20)
|
|
||||||
out 0x21, al
|
|
||||||
jmp $+2
|
|
||||||
jmp $+2
|
|
||||||
mov al, 0x28 ; start of hardware ints 2 (0x28)
|
|
||||||
out 0xA1, al
|
|
||||||
jmp $+2
|
|
||||||
jmp $+2
|
|
||||||
mov al, 0x04 ; 8259-1 is master
|
|
||||||
out 0x21, al
|
|
||||||
jmp $+2
|
|
||||||
jmp $+2
|
|
||||||
mov al, 0x02 ; 8259-2 is slave
|
|
||||||
out 0xA1, al
|
|
||||||
jmp $+2
|
|
||||||
jmp $+2
|
|
||||||
mov al, 0x01 ; 8086 mode for both
|
|
||||||
out 0x21, al
|
|
||||||
jmp $+2
|
|
||||||
jmp $+2
|
|
||||||
out 0xA1, al
|
|
||||||
jmp $+2
|
|
||||||
jmp $+2
|
|
||||||
mov al, 0xFF ; all interrupts off for now
|
|
||||||
out 0x21, al
|
|
||||||
jmp $+2
|
|
||||||
jmp $+2
|
|
||||||
out 0xA1, al
|
|
||||||
ret
|
|
||||||
|
|
||||||
global flushTSS
|
global flushTSS
|
||||||
flushTSS:
|
flushTSS:
|
||||||
mov ax, 0x28
|
mov ax, 0x28
|
||||||
@ -302,8 +93,6 @@ ret
|
|||||||
|
|
||||||
extern tss_data
|
extern tss_data
|
||||||
|
|
||||||
extern start
|
|
||||||
|
|
||||||
gdt_desc:
|
gdt_desc:
|
||||||
dw gdt_end - gdt
|
dw gdt_end - gdt
|
||||||
dd gdt
|
dd gdt
|
||||||
|
130
handler.nasm
Normal file
130
handler.nasm
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
extern unhandled_handler
|
||||||
|
unhandled_handler:
|
||||||
|
mov ax, 0x10
|
||||||
|
mov ds, ax
|
||||||
|
mov dword [0xb8000], 0x0f000f00 | 'E' | 'R' << 16
|
||||||
|
mov dword [0xb8004], 0x0f000f00 | 'R' | 'O' << 16
|
||||||
|
mov dword [0xb8008], 0x0f000f00 | 'R' | '!' << 16
|
||||||
|
.hlt:
|
||||||
|
hlt
|
||||||
|
jmp .hlt
|
||||||
|
|
||||||
|
extern gpf_handler_v86
|
||||||
|
global gpfHandler
|
||||||
|
gpfHandler:
|
||||||
|
iret
|
||||||
|
mov ax, 0x10
|
||||||
|
mov ds, ax
|
||||||
|
;jmp gpf_handler_v86
|
||||||
|
mov word [0xb8000], 0x0f00 | 'G'
|
||||||
|
mov word [0xb8002], 0x0f00 | 'P'
|
||||||
|
mov word [0xb8004], 0x0f00 | 'F'
|
||||||
|
.hlt:
|
||||||
|
hlt
|
||||||
|
jmp .hlt
|
||||||
|
|
||||||
|
scancodesToAscii: db 0, 0 ; 0x00 - 0x01
|
||||||
|
db "1234567890" ; 0x02 - 0x0B
|
||||||
|
db "-=" ; 0x0C - 0x0D
|
||||||
|
db 0, 0 ; 0x0E - 0x0F
|
||||||
|
db "qwertyuiop[]" ; 0x10 - 0x1B
|
||||||
|
db 0, 0 ; 0x1C - 0x1D
|
||||||
|
db "asdfghjkl;'`" ; 0x1E - 0x29
|
||||||
|
db 0 ; 0x2A
|
||||||
|
db "\zxcvbnm,./" ; 0x2B - 0x35
|
||||||
|
db 0 ; 0x36
|
||||||
|
db '*' ; 0x37
|
||||||
|
db 0 ; 0x38
|
||||||
|
db ' ' ; 0x39
|
||||||
|
db 'C'
|
||||||
|
scancodesToAsciiEnd:
|
||||||
|
cursorCurrent: dd 0xb8000 + (80*6*2)
|
||||||
|
global keyboardHandler
|
||||||
|
keyboardHandler:
|
||||||
|
push eax
|
||||||
|
push ebx
|
||||||
|
push ds
|
||||||
|
mov ax, 0x10
|
||||||
|
mov ds, ax
|
||||||
|
xor eax, eax
|
||||||
|
in al, 0x60
|
||||||
|
cmp eax, 0x3A
|
||||||
|
jg .done
|
||||||
|
mov al, [scancodesToAscii+eax]
|
||||||
|
test al, al
|
||||||
|
jz .done
|
||||||
|
mov ebx, [cursorCurrent]
|
||||||
|
mov byte [ebx], al
|
||||||
|
add dword [cursorCurrent], 2
|
||||||
|
mov byte [KBDWAIT], 1
|
||||||
|
.done:
|
||||||
|
mov al, 0x20
|
||||||
|
out 0x20, al
|
||||||
|
pop ds
|
||||||
|
pop ebx
|
||||||
|
pop eax
|
||||||
|
iret
|
||||||
|
|
||||||
|
KBDWAIT: db 0
|
||||||
|
global kbd_wait
|
||||||
|
kbd_wait:
|
||||||
|
mov byte [KBDWAIT], 0
|
||||||
|
.loop:
|
||||||
|
hlt
|
||||||
|
xor eax, eax
|
||||||
|
mov al, [KBDWAIT]
|
||||||
|
test eax, eax
|
||||||
|
jz .loop
|
||||||
|
ret
|
||||||
|
|
||||||
|
global timerHandler
|
||||||
|
timerHandler:
|
||||||
|
push eax
|
||||||
|
push ds
|
||||||
|
mov ax, 0x10
|
||||||
|
mov ds, ax
|
||||||
|
inc byte [(0xb8000 + (80*8*2))]
|
||||||
|
mov al, 0x20
|
||||||
|
out 0x20, al
|
||||||
|
pop ds
|
||||||
|
pop eax
|
||||||
|
iret
|
||||||
|
|
||||||
|
global picInit
|
||||||
|
picInit:
|
||||||
|
mov al, 0x11 ; initialization sequence
|
||||||
|
out 0x20, al ; send to 8259A-1
|
||||||
|
jmp $+2
|
||||||
|
jmp $+2
|
||||||
|
out 0xA0, al ; and to 8259A-2
|
||||||
|
jmp $+2
|
||||||
|
jmp $+2
|
||||||
|
mov al, 0x20 ; start of hardware ints (0x20)
|
||||||
|
out 0x21, al
|
||||||
|
jmp $+2
|
||||||
|
jmp $+2
|
||||||
|
mov al, 0x28 ; start of hardware ints 2 (0x28)
|
||||||
|
out 0xA1, al
|
||||||
|
jmp $+2
|
||||||
|
jmp $+2
|
||||||
|
mov al, 0x04 ; 8259-1 is master
|
||||||
|
out 0x21, al
|
||||||
|
jmp $+2
|
||||||
|
jmp $+2
|
||||||
|
mov al, 0x02 ; 8259-2 is slave
|
||||||
|
out 0xA1, al
|
||||||
|
jmp $+2
|
||||||
|
jmp $+2
|
||||||
|
mov al, 0x01 ; 8086 mode for both
|
||||||
|
out 0x21, al
|
||||||
|
jmp $+2
|
||||||
|
jmp $+2
|
||||||
|
out 0xA1, al
|
||||||
|
jmp $+2
|
||||||
|
jmp $+2
|
||||||
|
mov al, 0xFF ; all interrupts off for now
|
||||||
|
out 0x21, al
|
||||||
|
jmp $+2
|
||||||
|
jmp $+2
|
||||||
|
out 0xA1, al
|
||||||
|
ret
|
272
interrupt.c
Normal file
272
interrupt.c
Normal file
@ -0,0 +1,272 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include "print.h"
|
||||||
|
|
||||||
|
#include "interrupt.h"
|
||||||
|
|
||||||
|
struct __attribute__((__packed__)) IDTR_t {
|
||||||
|
uint16_t size;
|
||||||
|
uint32_t offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct __attribute__((__packed__)) InterruptDescriptor32 {
|
||||||
|
uint16_t offset_1; // offset bits 0..15
|
||||||
|
uint16_t selector; // a code segment selector in GDT or LDT
|
||||||
|
uint8_t zero; // unused, set to 0
|
||||||
|
uint8_t type_attributes; // gate type, dpl, and p fields
|
||||||
|
uint16_t offset_2; // offset bits 16..31
|
||||||
|
};
|
||||||
|
|
||||||
|
__attribute__((aligned(0x10)))
|
||||||
|
struct InterruptDescriptor32 IDT[256];
|
||||||
|
struct IDTR_t IDTR;
|
||||||
|
|
||||||
|
void outb(uint16_t port, uint8_t value) {
|
||||||
|
asm volatile("outb %%al, %%dx" : : "d"(port), "a"(value));
|
||||||
|
}
|
||||||
|
uint8_t inb(uint16_t port) {
|
||||||
|
uint8_t value;
|
||||||
|
asm volatile("inb %%dx, %%al" : "=a"(value) : "d"(port));
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
FARPTR i386LinearToFp(void *ptr)
|
||||||
|
{
|
||||||
|
unsigned seg, off;
|
||||||
|
off = (uintptr_t) ptr & 0xffff;
|
||||||
|
seg = ((uintptr_t) ptr >> 16);
|
||||||
|
return MK_FP(seg, off);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void IRQ_set_mask(char IRQline) {
|
||||||
|
uint16_t port;
|
||||||
|
uint8_t value;
|
||||||
|
if (IRQline < 8) {
|
||||||
|
port = 0x21;
|
||||||
|
} else {
|
||||||
|
port = 0xA1;
|
||||||
|
IRQline -= 8;
|
||||||
|
}
|
||||||
|
value = inb(port) | (1 << IRQline);
|
||||||
|
outb(port, value);
|
||||||
|
}
|
||||||
|
void IRQ_clear_mask(char IRQline) {
|
||||||
|
uint16_t port;
|
||||||
|
uint8_t value;
|
||||||
|
if (IRQline < 8) {
|
||||||
|
port = 0x21;
|
||||||
|
} else {
|
||||||
|
port = 0xA1;
|
||||||
|
IRQline -= 8;
|
||||||
|
}
|
||||||
|
value = inb(port) & ~(1 << IRQline);
|
||||||
|
outb(port, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
char v86_if = 0;
|
||||||
|
extern void real_test();
|
||||||
|
extern void kbd_wait();
|
||||||
|
#define VALID_FLAGS 0xDFF
|
||||||
|
__attribute__ ((interrupt))
|
||||||
|
void gpf_handler_v86(struct interrupt_frame *frame, unsigned long error_code) {
|
||||||
|
asm volatile("mov %%ax,%%ds"::"a"(0x10));
|
||||||
|
uint8_t *ip;
|
||||||
|
uint16_t *stack, *ivt;
|
||||||
|
uint32_t *stack32;
|
||||||
|
char is_operand32 = 0, is_address32 = 0;
|
||||||
|
ip = (size_t)(((frame->cs << 4) + frame->eip) & 0xFFFFF);
|
||||||
|
ivt = (uint16_t*)0x0000;
|
||||||
|
stack = FP_TO_LINEAR(frame->ss, frame->esp);
|
||||||
|
stack32 = (uint32_t*)stack;
|
||||||
|
|
||||||
|
char *vga = (char*)0xb8000 + (160 * 10);
|
||||||
|
vga[0] = 'I'; vga[2] = 'P'; printWord(frame->eip, &vga[4]); vga += 14;
|
||||||
|
vga[0] = 'C'; vga[2] = 'S'; printWord(frame->cs, &vga[4]); vga += 14;
|
||||||
|
vga[0] = 'F'; vga[2] = 'L'; printDword(frame->eflags, &vga[4]); vga += 14;
|
||||||
|
vga = (char*)0xb8000 + (160 * 11);
|
||||||
|
vga[0] = 'S'; vga[2] = 'P'; printWord(frame->esp, &vga[4]); vga += 14;
|
||||||
|
vga[0] = 'S'; vga[2] = 'S'; printWord(frame->ss, &vga[4]); vga += 14;
|
||||||
|
vga = (char*)0xb8000 + (160 * 12);
|
||||||
|
vga[0] = 'E'; vga[2] = 'S'; printWord(frame->es, &vga[4]); vga += 14;
|
||||||
|
vga[0] = 'D'; vga[2] = 'S'; printWord(frame->ds, &vga[4]); vga += 14;
|
||||||
|
vga[0] = 'F'; vga[2] = 'S'; printWord(frame->fs, &vga[4]); vga += 14;
|
||||||
|
vga[0] = 'G'; vga[2] = 'S'; printWord(frame->gs, &vga[4]); vga += 14;
|
||||||
|
|
||||||
|
//vga[2]++;
|
||||||
|
//printDword(frame, &vga[20]);
|
||||||
|
//vga = &vga[38];
|
||||||
|
//uint32_t *fr = frame;
|
||||||
|
//for (int i = 0; i < sizeof(struct interrupt_frame)/sizeof(uint32_t); i++) {
|
||||||
|
// printDword(fr[i], vga);
|
||||||
|
// vga += (sizeof(uint32_t)*2+1)*2;
|
||||||
|
//}
|
||||||
|
//vga = (char*)0xb80A0;
|
||||||
|
//printDword(ip, &vga[20]);
|
||||||
|
//vga = &vga[38];
|
||||||
|
//for (int i = 0; i < 16; i++) {
|
||||||
|
// printByte(ip[i], vga);
|
||||||
|
// vga += (sizeof(uint8_t)*2)*2;
|
||||||
|
//}
|
||||||
|
vga = (char*)0xb8000 + (160*3);
|
||||||
|
for(;;) {
|
||||||
|
switch (ip[0]) {
|
||||||
|
case 0x66: // O32
|
||||||
|
is_operand32 = 1;
|
||||||
|
ip++;
|
||||||
|
frame->eip = (uint16_t)(frame->eip + 1);
|
||||||
|
break;
|
||||||
|
case 0x67: // A32
|
||||||
|
is_address32 = 1;
|
||||||
|
ip++;
|
||||||
|
frame->eip = (uint16_t)(frame->eip + 1);
|
||||||
|
break;
|
||||||
|
case 0x9C: // PUSHF
|
||||||
|
if (is_operand32) {
|
||||||
|
frame->esp = ((frame->esp & 0xffff) - 4) & 0xffff;
|
||||||
|
stack32--;
|
||||||
|
stack32[0] = frame->eflags & VALID_FLAGS;
|
||||||
|
if (v86_if)
|
||||||
|
stack32[0] |= EFLAG_IF;
|
||||||
|
else
|
||||||
|
stack32[0] &= ~EFLAG_IF;
|
||||||
|
} else {
|
||||||
|
frame->esp = ((frame->esp & 0xffff) - 2) & 0xffff;
|
||||||
|
stack--;
|
||||||
|
stack[0] = (uint16_t)frame->eflags;
|
||||||
|
if (v86_if)
|
||||||
|
stack[0] |= EFLAG_IF;
|
||||||
|
else
|
||||||
|
stack[0] &= ~EFLAG_IF;
|
||||||
|
}
|
||||||
|
frame->eip = (uint16_t)(frame->eip + 1);
|
||||||
|
goto done;
|
||||||
|
case 0x9D: // POPF
|
||||||
|
if (is_operand32) {
|
||||||
|
frame->eflags = EFLAG_IF | EFLAG_VM | (stack32[0] & VALID_FLAGS);
|
||||||
|
v86_if = (stack32[0] & EFLAG_IF) != 0;
|
||||||
|
frame->esp = ((frame->esp & 0xffff) + 4) & 0xffff;
|
||||||
|
} else {
|
||||||
|
frame->eflags = EFLAG_IF | EFLAG_VM | stack[0];
|
||||||
|
v86_if = (stack[0] & EFLAG_IF) != 0;
|
||||||
|
frame->esp = ((frame->esp & 0xffff) + 2) & 0xffff;
|
||||||
|
}
|
||||||
|
frame->eip = (uint16_t)(frame->eip + 1);
|
||||||
|
goto done;
|
||||||
|
case 0xCD: // INT n
|
||||||
|
vga[0] = 'I'; vga[2]++; if (vga[2] < '0') vga[2] = '0';
|
||||||
|
asm volatile("nop\nnop");
|
||||||
|
switch (ip[1]) {
|
||||||
|
case 0x30: // Exit V86 Mode?
|
||||||
|
asm volatile("nop\nnop");
|
||||||
|
asm volatile("jmp jmp_usermode_test");
|
||||||
|
//__builtin_unreachable();
|
||||||
|
break;
|
||||||
|
//case 0x20: // ???
|
||||||
|
//case 0x21: // ???
|
||||||
|
case 0x3: // Debugger trap
|
||||||
|
kbd_wait();
|
||||||
|
asm volatile("nop");
|
||||||
|
default:
|
||||||
|
stack -= 3;
|
||||||
|
frame->esp = ((frame->esp & 0xffff) - 6) & 0xffff;
|
||||||
|
|
||||||
|
stack[0] = (uint16_t) (frame->eip + 2);
|
||||||
|
stack[1] = frame->cs;
|
||||||
|
stack[2] = (uint16_t) frame->eflags;
|
||||||
|
|
||||||
|
if (v86_if)
|
||||||
|
stack[2] |= EFLAG_IF;
|
||||||
|
else
|
||||||
|
stack[2] &= ~EFLAG_IF;
|
||||||
|
|
||||||
|
frame->cs = ivt[ip[1] * 2 + 1];
|
||||||
|
frame->eip = ivt[ip[1] * 2];
|
||||||
|
asm volatile("nop");
|
||||||
|
//frame->cs = 0;
|
||||||
|
//frame->eip = real_test;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
goto done;
|
||||||
|
case 0xCF: // IRET
|
||||||
|
frame->eip = stack[0];
|
||||||
|
frame->cs = stack[1];
|
||||||
|
frame->eflags = EFLAG_IF | EFLAG_VM | stack[2];
|
||||||
|
v86_if = (stack[2] & EFLAG_IF) != 0;
|
||||||
|
frame->esp = ((frame->esp & 0xffff) + 6) & 0xffff;
|
||||||
|
goto done;
|
||||||
|
case 0xFA: // CLI
|
||||||
|
v86_if = 0;
|
||||||
|
frame->eip = (uint16_t) (frame->eip + 1);
|
||||||
|
goto done;
|
||||||
|
case 0xFB: // STI
|
||||||
|
v86_if = 1;
|
||||||
|
frame->eip = (uint16_t) (frame->eip + 1);
|
||||||
|
goto done;
|
||||||
|
default:
|
||||||
|
for(;;);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
done:
|
||||||
|
vga = (char*)0xb8000 + (160 * 13);
|
||||||
|
vga[0] = 'I'; vga[2] = 'P'; printWord(frame->eip, &vga[4]); vga += 14;
|
||||||
|
vga[0] = 'C'; vga[2] = 'S'; printWord(frame->cs, &vga[4]); vga += 14;
|
||||||
|
vga[0] = 'F'; vga[2] = 'L'; printDword(frame->eflags, &vga[4]); vga += 14;
|
||||||
|
vga = (char*)0xb8000 + (160 * 14);
|
||||||
|
vga[0] = 'S'; vga[2] = 'P'; printWord(frame->esp, &vga[4]); vga += 14;
|
||||||
|
vga[0] = 'S'; vga[2] = 'S'; printWord(frame->ss, &vga[4]); vga += 14;
|
||||||
|
vga = (char*)0xb8000 + (160 * 15);
|
||||||
|
vga[0] = 'E'; vga[2] = 'S'; printWord(frame->es, &vga[4]); vga += 14;
|
||||||
|
vga[0] = 'D'; vga[2] = 'S'; printWord(frame->ds, &vga[4]); vga += 14;
|
||||||
|
vga[0] = 'F'; vga[2] = 'S'; printWord(frame->fs, &vga[4]); vga += 14;
|
||||||
|
vga[0] = 'G'; vga[2] = 'S'; printWord(frame->gs, &vga[4]); vga += 14;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern void timerHandler();
|
||||||
|
extern void keyboardHandler();
|
||||||
|
extern void gpfHandler();
|
||||||
|
extern void unhandled_handler();
|
||||||
|
extern void picInit();
|
||||||
|
void set_system_gate(uint8_t gate, void (*handler)()) {
|
||||||
|
IDT[gate].offset_1 = (uint32_t)(size_t)handler & 0xFFFF;
|
||||||
|
IDT[gate].offset_2 = ((uint32_t)(size_t)handler >> 16) & 0xFFFF;
|
||||||
|
IDT[gate].selector = 0x08;
|
||||||
|
IDT[gate].type_attributes = 0x8E;
|
||||||
|
}
|
||||||
|
void set_trap_gate(uint8_t gate, void (*handler)()) {
|
||||||
|
IDT[gate].offset_1 = (uint32_t)(size_t)handler & 0xFFFF;
|
||||||
|
IDT[gate].offset_2 = ((uint32_t)(size_t)handler >> 16) & 0xFFFF;
|
||||||
|
IDT[gate].selector = 0x08;
|
||||||
|
IDT[gate].type_attributes = 0x8F;
|
||||||
|
}
|
||||||
|
void setup_interrupts() {
|
||||||
|
IDTR.size = 256*8 - 1;
|
||||||
|
IDTR.offset = (uint32_t)(size_t)IDT;
|
||||||
|
for (int i = 0; i < 256; i++) {
|
||||||
|
*(uint64_t*)&IDT[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 9; i++) {
|
||||||
|
set_trap_gate(i, unhandled_handler);
|
||||||
|
}
|
||||||
|
for (int i = 10; i < 15; i++) {
|
||||||
|
set_trap_gate(i, unhandled_handler);
|
||||||
|
}
|
||||||
|
for (int i = 16; i < 22; i++) {
|
||||||
|
set_trap_gate(i, unhandled_handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
set_system_gate(0x20, timerHandler);
|
||||||
|
set_system_gate(0x21, keyboardHandler);
|
||||||
|
set_trap_gate(13, gpf_handler_v86);
|
||||||
|
//set_trap_gate(13, gpfHandler);
|
||||||
|
|
||||||
|
asm volatile("lidt %0": : "m"(IDTR));
|
||||||
|
picInit();
|
||||||
|
IRQ_clear_mask(0);
|
||||||
|
IRQ_clear_mask(1);
|
||||||
|
asm volatile("sti");
|
||||||
|
}
|
||||||
|
|
35
interrupt.h
Normal file
35
interrupt.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
struct interrupt_frame {
|
||||||
|
uint32_t eip, cs;
|
||||||
|
uint32_t eflags;
|
||||||
|
uint32_t esp, ss;
|
||||||
|
uint32_t es, ds, fs, gs;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Real Mode helper macros */
|
||||||
|
/* segment:offset pair */
|
||||||
|
typedef uint32_t FARPTR;
|
||||||
|
|
||||||
|
/* Make a FARPTR from a segment and an offset */
|
||||||
|
#define MK_FP(seg, off) ((FARPTR) (((uint32_t) (seg) << 16) | (uint16_t) (off)))
|
||||||
|
|
||||||
|
/* Extract the segment part of a FARPTR */
|
||||||
|
#define FP_SEG(fp) (((FARPTR) fp) >> 16)
|
||||||
|
|
||||||
|
/* Extract the offset part of a FARPTR */
|
||||||
|
#define FP_OFF(fp) (((FARPTR) fp) & 0xffff)
|
||||||
|
|
||||||
|
/* Convert a segment:offset pair to a linear address */
|
||||||
|
#define FP_TO_LINEAR(seg, off) ((void*)(uintptr_t)((((uint32_t)seg) << 4) + ((uint32_t)off)))
|
||||||
|
|
||||||
|
#define EFLAG_IF ((uint32_t)1 << 9)
|
||||||
|
#define EFLAG_VM ((uint32_t)1 << 17)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
__attribute__ ((interrupt))
|
||||||
|
void gpf_handler_v86(struct interrupt_frame *frame, unsigned long error_code);
|
||||||
|
|
||||||
|
void setup_interrupts();
|
360
kernel.c
360
kernel.c
@ -1,22 +1,11 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
typedef unsigned short word;
|
#include "print.h"
|
||||||
|
#include "interrupt.h"
|
||||||
|
|
||||||
char nibbleToHex(char n) {
|
#include "tss.c"
|
||||||
return n > 9 ? (n - 10) + 'A' : n + '0';
|
|
||||||
}
|
typedef unsigned short word;
|
||||||
void printByte(char v, short *buff) {
|
|
||||||
*(char *)&buff[0] = nibbleToHex((v >> 4) & 0xF);
|
|
||||||
*(char *)&buff[1] = nibbleToHex(v & 0xF);
|
|
||||||
}
|
|
||||||
void printWord(short v, short *buff) {
|
|
||||||
printByte(v >> 8, buff);
|
|
||||||
printByte(v, &buff[2]);
|
|
||||||
}
|
|
||||||
void printDword(int v, short *buff) {
|
|
||||||
printWord(v >> 16, buff);
|
|
||||||
printWord(v, &buff[4]);
|
|
||||||
}
|
|
||||||
|
|
||||||
char check_apic() {
|
char check_apic() {
|
||||||
uint32_t eax, ebx, ecx, edx;
|
uint32_t eax, ebx, ecx, edx;
|
||||||
@ -29,335 +18,6 @@ char check_sse() {
|
|||||||
return (edx & (1 << 25)) != 0;
|
return (edx & (1 << 25)) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct __attribute__((__packed__)) IDTR_t {
|
|
||||||
uint16_t size;
|
|
||||||
uint32_t offset;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct __attribute__((__packed__)) InterruptDescriptor32 {
|
|
||||||
uint16_t offset_1; // offset bits 0..15
|
|
||||||
uint16_t selector; // a code segment selector in GDT or LDT
|
|
||||||
uint8_t zero; // unused, set to 0
|
|
||||||
uint8_t type_attributes; // gate type, dpl, and p fields
|
|
||||||
uint16_t offset_2; // offset bits 16..31
|
|
||||||
};
|
|
||||||
|
|
||||||
__attribute__((aligned(0x10)))
|
|
||||||
struct InterruptDescriptor32 IDT[256];
|
|
||||||
struct IDTR_t IDTR;
|
|
||||||
|
|
||||||
void outb(uint16_t port, uint8_t value) {
|
|
||||||
asm volatile("outb %%al, %%dx" : : "d"(port), "a"(value));
|
|
||||||
}
|
|
||||||
uint8_t inb(uint16_t port) {
|
|
||||||
uint8_t value;
|
|
||||||
asm volatile("inb %%dx, %%al" : "=a"(value) : "d"(port));
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void IRQ_set_mask(char IRQline) {
|
|
||||||
uint16_t port;
|
|
||||||
uint8_t value;
|
|
||||||
if (IRQline < 8) {
|
|
||||||
port = 0x21;
|
|
||||||
} else {
|
|
||||||
port = 0xA1;
|
|
||||||
IRQline -= 8;
|
|
||||||
}
|
|
||||||
value = inb(port) | (1 << IRQline);
|
|
||||||
outb(port, value);
|
|
||||||
}
|
|
||||||
void IRQ_clear_mask(char IRQline) {
|
|
||||||
uint16_t port;
|
|
||||||
uint8_t value;
|
|
||||||
if (IRQline < 8) {
|
|
||||||
port = 0x21;
|
|
||||||
} else {
|
|
||||||
port = 0xA1;
|
|
||||||
IRQline -= 8;
|
|
||||||
}
|
|
||||||
value = inb(port) & ~(1 << IRQline);
|
|
||||||
outb(port, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct interrupt_frame {
|
|
||||||
uint32_t eip, cs;
|
|
||||||
uint32_t eflags;
|
|
||||||
uint32_t esp, ss;
|
|
||||||
uint32_t es, ds, fs, gs;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Real Mode helper macros */
|
|
||||||
/* segment:offset pair */
|
|
||||||
typedef uint32_t FARPTR;
|
|
||||||
|
|
||||||
/* Make a FARPTR from a segment and an offset */
|
|
||||||
#define MK_FP(seg, off) ((FARPTR) (((uint32_t) (seg) << 16) | (uint16_t) (off)))
|
|
||||||
|
|
||||||
/* Extract the segment part of a FARPTR */
|
|
||||||
#define FP_SEG(fp) (((FARPTR) fp) >> 16)
|
|
||||||
|
|
||||||
/* Extract the offset part of a FARPTR */
|
|
||||||
#define FP_OFF(fp) (((FARPTR) fp) & 0xffff)
|
|
||||||
|
|
||||||
/* Convert a segment:offset pair to a linear address */
|
|
||||||
#define FP_TO_LINEAR(seg, off) ((void*)(uintptr_t)((((uint32_t)seg) << 4) + ((uint32_t)off)))
|
|
||||||
|
|
||||||
FARPTR i386LinearToFp(void *ptr)
|
|
||||||
{
|
|
||||||
unsigned seg, off;
|
|
||||||
off = (uintptr_t) ptr & 0xffff;
|
|
||||||
seg = ((uintptr_t) ptr >> 16);
|
|
||||||
return MK_FP(seg, off);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define EFLAG_IF ((uint32_t)1 << 9)
|
|
||||||
#define EFLAG_VM ((uint32_t)1 << 17)
|
|
||||||
|
|
||||||
char v86_if = 0;
|
|
||||||
extern void real_test();
|
|
||||||
extern void kbd_wait();
|
|
||||||
#define VALID_FLAGS 0xDFF
|
|
||||||
__attribute__ ((interrupt))
|
|
||||||
void gpf_handler_v86(struct interrupt_frame *frame, uint32_t error_code) {
|
|
||||||
asm volatile("mov %%ax,%%ds"::"a"(0x10));
|
|
||||||
uint8_t *ip;
|
|
||||||
uint16_t *stack, *ivt;
|
|
||||||
uint32_t *stack32;
|
|
||||||
char is_operand32 = 0, is_address32 = 0;
|
|
||||||
ip = ((frame->cs << 4) + frame->eip) & 0xFFFFF;
|
|
||||||
ivt = (uint16_t*)0x0000;
|
|
||||||
stack = FP_TO_LINEAR(frame->ss, frame->esp);
|
|
||||||
stack32 = (uint32_t*)stack;
|
|
||||||
|
|
||||||
char *vga = (char*)0xb8000 + (160 * 10);
|
|
||||||
vga[0] = 'I'; vga[2] = 'P'; printWord(frame->eip, &vga[4]); vga += 14;
|
|
||||||
vga[0] = 'C'; vga[2] = 'S'; printWord(frame->cs, &vga[4]); vga += 14;
|
|
||||||
vga[0] = 'F'; vga[2] = 'L'; printDword(frame->eflags, &vga[4]); vga += 14;
|
|
||||||
vga = (char*)0xb8000 + (160 * 11);
|
|
||||||
vga[0] = 'S'; vga[2] = 'P'; printWord(frame->esp, &vga[4]); vga += 14;
|
|
||||||
vga[0] = 'S'; vga[2] = 'S'; printWord(frame->ss, &vga[4]); vga += 14;
|
|
||||||
vga = (char*)0xb8000 + (160 * 12);
|
|
||||||
vga[0] = 'E'; vga[2] = 'S'; printWord(frame->es, &vga[4]); vga += 14;
|
|
||||||
vga[0] = 'D'; vga[2] = 'S'; printWord(frame->ds, &vga[4]); vga += 14;
|
|
||||||
vga[0] = 'F'; vga[2] = 'S'; printWord(frame->fs, &vga[4]); vga += 14;
|
|
||||||
vga[0] = 'G'; vga[2] = 'S'; printWord(frame->gs, &vga[4]); vga += 14;
|
|
||||||
|
|
||||||
//vga[2]++;
|
|
||||||
//printDword(frame, &vga[20]);
|
|
||||||
//vga = &vga[38];
|
|
||||||
//uint32_t *fr = frame;
|
|
||||||
//for (int i = 0; i < sizeof(struct interrupt_frame)/sizeof(uint32_t); i++) {
|
|
||||||
// printDword(fr[i], vga);
|
|
||||||
// vga += (sizeof(uint32_t)*2+1)*2;
|
|
||||||
//}
|
|
||||||
//vga = (char*)0xb80A0;
|
|
||||||
//printDword(ip, &vga[20]);
|
|
||||||
//vga = &vga[38];
|
|
||||||
//for (int i = 0; i < 16; i++) {
|
|
||||||
// printByte(ip[i], vga);
|
|
||||||
// vga += (sizeof(uint8_t)*2)*2;
|
|
||||||
//}
|
|
||||||
vga = (char*)0xb8000 + (160*3);
|
|
||||||
for(;;) {
|
|
||||||
switch (ip[0]) {
|
|
||||||
case 0x66: // O32
|
|
||||||
is_operand32 = 1;
|
|
||||||
ip++;
|
|
||||||
frame->eip = (uint16_t)(frame->eip + 1);
|
|
||||||
break;
|
|
||||||
case 0x67: // A32
|
|
||||||
is_address32 = 1;
|
|
||||||
ip++;
|
|
||||||
frame->eip = (uint16_t)(frame->eip + 1);
|
|
||||||
break;
|
|
||||||
case 0x9C: // PUSHF
|
|
||||||
if (is_operand32) {
|
|
||||||
frame->esp = ((frame->esp & 0xffff) - 4) & 0xffff;
|
|
||||||
stack32--;
|
|
||||||
stack32[0] = frame->eflags & VALID_FLAGS;
|
|
||||||
if (v86_if)
|
|
||||||
stack32[0] |= EFLAG_IF;
|
|
||||||
else
|
|
||||||
stack32[0] &= ~EFLAG_IF;
|
|
||||||
} else {
|
|
||||||
frame->esp = ((frame->esp & 0xffff) - 2) & 0xffff;
|
|
||||||
stack--;
|
|
||||||
stack[0] = (uint16_t)frame->eflags;
|
|
||||||
if (v86_if)
|
|
||||||
stack[0] |= EFLAG_IF;
|
|
||||||
else
|
|
||||||
stack[0] &= ~EFLAG_IF;
|
|
||||||
}
|
|
||||||
frame->eip = (uint16_t)(frame->eip + 1);
|
|
||||||
goto done;
|
|
||||||
case 0x9D: // POPF
|
|
||||||
if (is_operand32) {
|
|
||||||
frame->eflags = EFLAG_IF | EFLAG_VM | (stack32[0] & VALID_FLAGS);
|
|
||||||
v86_if = (stack32[0] & EFLAG_IF) != 0;
|
|
||||||
frame->esp = ((frame->esp & 0xffff) + 4) & 0xffff;
|
|
||||||
} else {
|
|
||||||
frame->eflags = EFLAG_IF | EFLAG_VM | stack[0];
|
|
||||||
v86_if = (stack[0] & EFLAG_IF) != 0;
|
|
||||||
frame->esp = ((frame->esp & 0xffff) + 2) & 0xffff;
|
|
||||||
}
|
|
||||||
frame->eip = (uint16_t)(frame->eip + 1);
|
|
||||||
goto done;
|
|
||||||
case 0xCD: // INT n
|
|
||||||
vga[0] = 'I'; vga[2]++; if (vga[2] < '0') vga[2] = '0';
|
|
||||||
asm volatile("nop\nnop");
|
|
||||||
switch (ip[1]) {
|
|
||||||
case 0x30: // Exit V86 Mode?
|
|
||||||
asm volatile("nop\nnop");
|
|
||||||
asm volatile("jmp jmp_usermode_test");
|
|
||||||
//__builtin_unreachable();
|
|
||||||
break;
|
|
||||||
//case 0x20: // ???
|
|
||||||
//case 0x21: // ???
|
|
||||||
case 0x3: // Debugger trap
|
|
||||||
kbd_wait();
|
|
||||||
asm volatile("nop");
|
|
||||||
default:
|
|
||||||
stack -= 3;
|
|
||||||
frame->esp = ((frame->esp & 0xffff) - 6) & 0xffff;
|
|
||||||
|
|
||||||
stack[0] = (uint16_t) (frame->eip + 2);
|
|
||||||
stack[1] = frame->cs;
|
|
||||||
stack[2] = (uint16_t) frame->eflags;
|
|
||||||
|
|
||||||
if (v86_if)
|
|
||||||
stack[2] |= EFLAG_IF;
|
|
||||||
else
|
|
||||||
stack[2] &= ~EFLAG_IF;
|
|
||||||
|
|
||||||
frame->cs = ivt[ip[1] * 2 + 1];
|
|
||||||
frame->eip = ivt[ip[1] * 2];
|
|
||||||
asm volatile("nop");
|
|
||||||
//frame->cs = 0;
|
|
||||||
//frame->eip = real_test;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
goto done;
|
|
||||||
case 0xCF: // IRET
|
|
||||||
frame->eip = stack[0];
|
|
||||||
frame->cs = stack[1];
|
|
||||||
frame->eflags = EFLAG_IF | EFLAG_VM | stack[2];
|
|
||||||
v86_if = (stack[2] & EFLAG_IF) != 0;
|
|
||||||
frame->esp = ((frame->esp & 0xffff) + 6) & 0xffff;
|
|
||||||
goto done;
|
|
||||||
case 0xFA: // CLI
|
|
||||||
v86_if = 0;
|
|
||||||
frame->eip = (uint16_t) (frame->eip + 1);
|
|
||||||
goto done;
|
|
||||||
case 0xFB: // STI
|
|
||||||
v86_if = 1;
|
|
||||||
frame->eip = (uint16_t) (frame->eip + 1);
|
|
||||||
goto done;
|
|
||||||
default:
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
done:
|
|
||||||
vga = (char*)0xb8000 + (160 * 13);
|
|
||||||
vga[0] = 'I'; vga[2] = 'P'; printWord(frame->eip, &vga[4]); vga += 14;
|
|
||||||
vga[0] = 'C'; vga[2] = 'S'; printWord(frame->cs, &vga[4]); vga += 14;
|
|
||||||
vga[0] = 'F'; vga[2] = 'L'; printDword(frame->eflags, &vga[4]); vga += 14;
|
|
||||||
vga = (char*)0xb8000 + (160 * 14);
|
|
||||||
vga[0] = 'S'; vga[2] = 'P'; printWord(frame->esp, &vga[4]); vga += 14;
|
|
||||||
vga[0] = 'S'; vga[2] = 'S'; printWord(frame->ss, &vga[4]); vga += 14;
|
|
||||||
vga = (char*)0xb8000 + (160 * 15);
|
|
||||||
vga[0] = 'E'; vga[2] = 'S'; printWord(frame->es, &vga[4]); vga += 14;
|
|
||||||
vga[0] = 'D'; vga[2] = 'S'; printWord(frame->ds, &vga[4]); vga += 14;
|
|
||||||
vga[0] = 'F'; vga[2] = 'S'; printWord(frame->fs, &vga[4]); vga += 14;
|
|
||||||
vga[0] = 'G'; vga[2] = 'S'; printWord(frame->gs, &vga[4]); vga += 14;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern void timerHandler();
|
|
||||||
extern void keyboardHandler();
|
|
||||||
extern void gpfHandler();
|
|
||||||
extern void unhandled_handler();
|
|
||||||
extern void picInit();
|
|
||||||
void set_system_gate(uint8_t gate, void (*handler)()) {
|
|
||||||
IDT[gate].offset_1 = (uint32_t)handler & 0xFFFF;
|
|
||||||
IDT[gate].offset_2 = ((uint32_t)handler >> 16) & 0xFFFF;
|
|
||||||
IDT[gate].selector = 0x08;
|
|
||||||
IDT[gate].type_attributes = 0x8E;
|
|
||||||
}
|
|
||||||
void set_trap_gate(uint8_t gate, void (*handler)()) {
|
|
||||||
IDT[gate].offset_1 = (uint32_t)handler & 0xFFFF;
|
|
||||||
IDT[gate].offset_2 = ((uint32_t)handler >> 16) & 0xFFFF;
|
|
||||||
IDT[gate].selector = 0x08;
|
|
||||||
IDT[gate].type_attributes = 0x8F;
|
|
||||||
}
|
|
||||||
void setup_interrupts() {
|
|
||||||
IDTR.size = 256*8 - 1;
|
|
||||||
IDTR.offset = (uint32_t)IDT;
|
|
||||||
for (int i = 0; i < 256; i++) {
|
|
||||||
*(uint64_t*)&IDT[i] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < 9; i++) {
|
|
||||||
set_trap_gate(i, unhandled_handler);
|
|
||||||
}
|
|
||||||
for (int i = 10; i < 15; i++) {
|
|
||||||
set_trap_gate(i, unhandled_handler);
|
|
||||||
}
|
|
||||||
for (int i = 16; i < 22; i++) {
|
|
||||||
set_trap_gate(i, unhandled_handler);
|
|
||||||
}
|
|
||||||
|
|
||||||
set_system_gate(0x20, timerHandler);
|
|
||||||
set_system_gate(0x21, keyboardHandler);
|
|
||||||
set_trap_gate(13, gpf_handler_v86);
|
|
||||||
//set_trap_gate(13, gpfHandler);
|
|
||||||
|
|
||||||
asm volatile("lidt %0": : "m"(IDTR));
|
|
||||||
picInit();
|
|
||||||
IRQ_clear_mask(0);
|
|
||||||
IRQ_clear_mask(1);
|
|
||||||
asm volatile("sti");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
struct __attribute__((__packed__)) tss_entry_struct {
|
|
||||||
uint32_t prev_tss;
|
|
||||||
uint32_t esp0;
|
|
||||||
uint32_t ss0;
|
|
||||||
uint32_t esp1;
|
|
||||||
uint32_t ss1;
|
|
||||||
uint32_t esp2;
|
|
||||||
uint32_t ss2;
|
|
||||||
uint32_t cr3;
|
|
||||||
uint32_t eip;
|
|
||||||
uint32_t eflags;
|
|
||||||
uint32_t eax;
|
|
||||||
uint32_t ecx;
|
|
||||||
uint32_t edx;
|
|
||||||
uint32_t ebx;
|
|
||||||
uint32_t esp;
|
|
||||||
uint32_t ebp;
|
|
||||||
uint32_t esi;
|
|
||||||
uint32_t edi;
|
|
||||||
uint32_t es;
|
|
||||||
uint32_t cs;
|
|
||||||
uint32_t ss;
|
|
||||||
uint32_t ds;
|
|
||||||
uint32_t fs;
|
|
||||||
uint32_t gs;
|
|
||||||
uint32_t ldt;
|
|
||||||
uint32_t trap;
|
|
||||||
uint32_t iomap_base;
|
|
||||||
};
|
|
||||||
struct tss_entry_struct *tss_data;
|
|
||||||
void write_tss() {
|
|
||||||
tss_data = (struct tss_entry_struct *)0x20000;
|
|
||||||
for (int i = 0; i < 0x2080; i++)
|
|
||||||
((uint8_t*)tss_data)[i] = 0;
|
|
||||||
tss_data->ss0 = 0x10;
|
|
||||||
tss_data->esp0 = 0x400000;
|
|
||||||
tss_data->iomap_base = 0x80;
|
|
||||||
}
|
|
||||||
|
|
||||||
void enable_sse() {
|
void enable_sse() {
|
||||||
asm volatile(
|
asm volatile(
|
||||||
"mov %%cr0, %%eax\n"
|
"mov %%cr0, %%eax\n"
|
||||||
@ -394,7 +54,6 @@ void print_cr4() {
|
|||||||
|
|
||||||
extern void enter_v86(uint32_t ss, uint32_t esp, uint32_t cs, uint32_t eip);
|
extern void enter_v86(uint32_t ss, uint32_t esp, uint32_t cs, uint32_t eip);
|
||||||
extern void v86Code();
|
extern void v86Code();
|
||||||
extern void flushTSS();
|
|
||||||
extern void jmp_usermode_test();
|
extern void jmp_usermode_test();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -420,9 +79,9 @@ void start() {
|
|||||||
|
|
||||||
uint32_t o;
|
uint32_t o;
|
||||||
asm("mov %%esp, %%eax" : "=a"(o) : :);
|
asm("mov %%esp, %%eax" : "=a"(o) : :);
|
||||||
printDword(o, (short *)&vga_text[80]);
|
printDword(o, (uint16_t *)&vga_text[80]);
|
||||||
asm("mov %%ebp, %%eax" : "=a"(o) : :);
|
asm("mov %%ebp, %%eax" : "=a"(o) : :);
|
||||||
printDword(o, (short *)&vga_text[160]);
|
printDword(o, (uint16_t *)&vga_text[160]);
|
||||||
|
|
||||||
//char c[] = "APIC support: ";
|
//char c[] = "APIC support: ";
|
||||||
//char apic;
|
//char apic;
|
||||||
@ -433,15 +92,14 @@ void start() {
|
|||||||
|
|
||||||
char sse_str[] = "SSE support: ";
|
char sse_str[] = "SSE support: ";
|
||||||
char sse;
|
char sse;
|
||||||
printByte(sse = check_sse(), (short*)&vga_text[80*4 + sizeof(sse_str) - 1]);
|
printByte(sse = check_sse(), (uint16_t*)&vga_text[80*4 + sizeof(sse_str) - 1]);
|
||||||
for (int i = 0; i < sizeof(sse_str); i++)
|
for (int i = 0; i < sizeof(sse_str); i++)
|
||||||
*(char *)&vga_text[i+(80*4)] = sse_str[i];
|
*(char *)&vga_text[i+(80*4)] = sse_str[i];
|
||||||
if (!sse) return;
|
if (!sse) return;
|
||||||
enable_sse();
|
enable_sse();
|
||||||
|
|
||||||
setup_interrupts();
|
setup_interrupts();
|
||||||
write_tss();
|
setup_tss();
|
||||||
flushTSS();
|
|
||||||
print_flags();
|
print_flags();
|
||||||
print_cr0();
|
print_cr0();
|
||||||
print_cr3();
|
print_cr3();
|
||||||
|
21
print.c
Normal file
21
print.c
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#include "print.h"
|
||||||
|
|
||||||
|
__attribute((__always_inline__))
|
||||||
|
char nibbleToHex(uint8_t n) {
|
||||||
|
return n > 9 ? (n - 10) + 'A' : n + '0';
|
||||||
|
}
|
||||||
|
__attribute((__always_inline__))
|
||||||
|
void printByte(uint8_t v, uint16_t *buff) {
|
||||||
|
*(char *)&buff[0] = nibbleToHex((v >> 4) & 0xF);
|
||||||
|
*(char *)&buff[1] = nibbleToHex(v & 0xF);
|
||||||
|
}
|
||||||
|
__attribute((__always_inline__))
|
||||||
|
void printWord(uint16_t v, uint16_t *buff) {
|
||||||
|
printByte(v >> 8, buff);
|
||||||
|
printByte(v, &buff[2]);
|
||||||
|
}
|
||||||
|
__attribute((__always_inline__))
|
||||||
|
void printDword(uint32_t v, uint16_t *buff) {
|
||||||
|
printWord(v >> 16, buff);
|
||||||
|
printWord(v, &buff[4]);
|
||||||
|
}
|
6
print.h
Normal file
6
print.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
void printByte(uint8_t v, uint16_t *buff);
|
||||||
|
void printWord(uint16_t v, uint16_t *buff);
|
||||||
|
void printDword(uint32_t v, uint16_t *buff);
|
46
tss.c
Normal file
46
tss.c
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
struct __attribute__((__packed__)) tss_entry_struct {
|
||||||
|
uint32_t prev_tss;
|
||||||
|
uint32_t esp0;
|
||||||
|
uint32_t ss0;
|
||||||
|
uint32_t esp1;
|
||||||
|
uint32_t ss1;
|
||||||
|
uint32_t esp2;
|
||||||
|
uint32_t ss2;
|
||||||
|
uint32_t cr3;
|
||||||
|
uint32_t eip;
|
||||||
|
uint32_t eflags;
|
||||||
|
uint32_t eax;
|
||||||
|
uint32_t ecx;
|
||||||
|
uint32_t edx;
|
||||||
|
uint32_t ebx;
|
||||||
|
uint32_t esp;
|
||||||
|
uint32_t ebp;
|
||||||
|
uint32_t esi;
|
||||||
|
uint32_t edi;
|
||||||
|
uint32_t es;
|
||||||
|
uint32_t cs;
|
||||||
|
uint32_t ss;
|
||||||
|
uint32_t ds;
|
||||||
|
uint32_t fs;
|
||||||
|
uint32_t gs;
|
||||||
|
uint32_t ldt;
|
||||||
|
uint32_t trap;
|
||||||
|
uint32_t iomap_base;
|
||||||
|
};
|
||||||
|
struct tss_entry_struct *tss_data;
|
||||||
|
void write_tss() {
|
||||||
|
tss_data = (struct tss_entry_struct *)0x20000;
|
||||||
|
for (int i = 0; i < 0x2080; i++)
|
||||||
|
((uint8_t*)tss_data)[i] = 0;
|
||||||
|
tss_data->ss0 = 0x10;
|
||||||
|
tss_data->esp0 = 0x400000;
|
||||||
|
tss_data->iomap_base = 0x80;
|
||||||
|
}
|
||||||
|
extern void flushTSS();
|
||||||
|
|
||||||
|
void setup_tss() {
|
||||||
|
write_tss();
|
||||||
|
flushTSS();
|
||||||
|
}
|
81
v86.nasm
Normal file
81
v86.nasm
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
[BITS 16]
|
||||||
|
real_hexprint:
|
||||||
|
xor cx, cx
|
||||||
|
mov bl, al
|
||||||
|
shr al, 4
|
||||||
|
jmp .donibble
|
||||||
|
.nibble2:
|
||||||
|
mov al, bl
|
||||||
|
inc cx
|
||||||
|
.donibble:
|
||||||
|
and al, 0x0F
|
||||||
|
cmp al, 0x0A
|
||||||
|
jl .noadjust
|
||||||
|
add al, 'A' - '0' - 10
|
||||||
|
.noadjust:
|
||||||
|
add al, '0'
|
||||||
|
mov ah, 0x1f
|
||||||
|
stosw
|
||||||
|
test cx, cx
|
||||||
|
jz .nibble2
|
||||||
|
ret
|
||||||
|
real_printword:
|
||||||
|
mov dx, ax
|
||||||
|
mov al, ah
|
||||||
|
call real_hexprint
|
||||||
|
mov ax, dx
|
||||||
|
call real_hexprint
|
||||||
|
ret
|
||||||
|
extern v86Code
|
||||||
|
v86Code:
|
||||||
|
mov ax, 0xb814
|
||||||
|
mov es, ax
|
||||||
|
mov di, 20
|
||||||
|
mov ax, sp
|
||||||
|
call real_printword
|
||||||
|
add di, 2
|
||||||
|
mov ax, ds
|
||||||
|
call real_printword
|
||||||
|
add di, 2
|
||||||
|
mov ax, cs
|
||||||
|
call real_printword
|
||||||
|
.loop:
|
||||||
|
inc byte [0]
|
||||||
|
;mov ax, 0x1111
|
||||||
|
;mov ds, ax
|
||||||
|
;mov ax, 0x2222
|
||||||
|
;mov es, ax
|
||||||
|
;mov ax, 0x3333
|
||||||
|
;mov fs, ax
|
||||||
|
;mov ax, 0x4444
|
||||||
|
;mov gs, ax
|
||||||
|
;mov ax, 0x5555
|
||||||
|
;mov ss, ax
|
||||||
|
;mov ax, 0x6666
|
||||||
|
;mov sp, ax
|
||||||
|
int 3
|
||||||
|
;jmp .loop
|
||||||
|
mov ax, 0x13
|
||||||
|
int 0x10
|
||||||
|
int 0x30 ; exit
|
||||||
|
jmp $
|
||||||
|
extern real_test
|
||||||
|
real_test:
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
jmp $
|
||||||
|
[BITS 32]
|
||||||
|
; extern void enter_v86(uint32_t ss, uint32_t esp, uint32_t cs, uint32_t eip);
|
||||||
|
global enter_v86
|
||||||
|
enter_v86:
|
||||||
|
mov ebp, esp ; save stack pointer
|
||||||
|
push dword [ebp+4] ; ss
|
||||||
|
push dword [ebp+8] ; esp
|
||||||
|
pushfd ; eflags
|
||||||
|
or dword [esp], (1 << 17) ; set VM flags
|
||||||
|
;or dword [esp], (3 << 12) ; IOPL 3
|
||||||
|
push dword [ebp+12] ; cs
|
||||||
|
push dword [ebp+16] ; eip
|
||||||
|
iret
|
||||||
|
|
Loading…
Reference in New Issue
Block a user