real initial commit
This commit is contained in:
		
							
								
								
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
			
		||||
*.o
 | 
			
		||||
*.bin
 | 
			
		||||
*.lock
 | 
			
		||||
bx_enh_dbg.ini
 | 
			
		||||
							
								
								
									
										11
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
			
		||||
all:
 | 
			
		||||
	nasm boot.nasm -o boot.bin
 | 
			
		||||
	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
 | 
			
		||||
	#clang -target "i686-elf" -O2 -ffreestanding -m32 -march=i386 -fno-stack-protector -nostdlib -c -o kernel.o kernel.c
 | 
			
		||||
	gcc -Tlink.ld -m32 -ffreestanding -nostartfiles -nostdlib -o kernel.bin entry.o kernel.o
 | 
			
		||||
	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
 | 
			
		||||
virtdisk:
 | 
			
		||||
	dd bs=1M count=32 if=/dev/zero of=virtdisk.bin
 | 
			
		||||
	echo -n -e '\x55\xaa' | dd bs=1 seek=510 conv=notrunc of=virtdisk.bin
 | 
			
		||||
							
								
								
									
										54
									
								
								bochsrc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								bochsrc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,54 @@
 | 
			
		||||
# configuration file generated by Bochs
 | 
			
		||||
display_library: x, options="gui_debug"
 | 
			
		||||
#magic_break: enabled=1
 | 
			
		||||
plugin_ctrl: unmapped=true, biosdev=true, speaker=true, extfpuirq=true, parallel=true, serial=true, iodebug=true, pcidev=false, usb_uhci=false
 | 
			
		||||
config_interface: textconfig
 | 
			
		||||
display_library: x
 | 
			
		||||
memory: host=32, guest=32
 | 
			
		||||
romimage: file="/usr/share/bochs/BIOS-bochs-latest", address=0x00000000, options=none
 | 
			
		||||
vgaromimage: file="/usr/share/bochs/VGABIOS-lgpl-latest"
 | 
			
		||||
boot: disk
 | 
			
		||||
floppy_bootsig_check: disabled=0
 | 
			
		||||
floppya: type=none
 | 
			
		||||
# no floppyb
 | 
			
		||||
ata0: enabled=true, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
 | 
			
		||||
ata0-master: type=disk, path="virtdisk.bin", mode=flat, cylinders=2, heads=16, spt=63, sect_size=512, model="Generic 1234", biosdetect=auto, translation=auto
 | 
			
		||||
ata0-slave: type=none
 | 
			
		||||
ata1: enabled=true, ioaddr1=0x170, ioaddr2=0x370, irq=15
 | 
			
		||||
ata1-master: type=none
 | 
			
		||||
ata1-slave: type=none
 | 
			
		||||
ata2: enabled=false
 | 
			
		||||
ata3: enabled=false
 | 
			
		||||
optromimage1: file=none
 | 
			
		||||
optromimage2: file=none
 | 
			
		||||
optromimage3: file=none
 | 
			
		||||
optromimage4: file=none
 | 
			
		||||
optramimage1: file=none
 | 
			
		||||
optramimage2: file=none
 | 
			
		||||
optramimage3: file=none
 | 
			
		||||
optramimage4: file=none
 | 
			
		||||
pci: enabled=1, chipset=i440fx, slot1=none, slot2=none, slot3=none, slot4=none, slot5=none
 | 
			
		||||
vga: extension=vbe, update_freq=5, realtime=1, ddc=builtin
 | 
			
		||||
cpu: count=1:1:1, ips=4000000, quantum=16, model=core_duo_t2400_yonah, reset_on_triple_fault=1, cpuid_limit_winnt=0, ignore_bad_msrs=1, mwait_is_nop=0
 | 
			
		||||
print_timestamps: enabled=0
 | 
			
		||||
debugger_log: -
 | 
			
		||||
magic_break: enabled=0
 | 
			
		||||
port_e9_hack: enabled=0
 | 
			
		||||
private_colormap: enabled=0
 | 
			
		||||
clock: sync=none, time0=local, rtc_sync=0
 | 
			
		||||
# no cmosimage
 | 
			
		||||
log: -
 | 
			
		||||
logprefix: %t%e%d
 | 
			
		||||
debug: action=ignore
 | 
			
		||||
info: action=report
 | 
			
		||||
error: action=report
 | 
			
		||||
panic: action=ask
 | 
			
		||||
keyboard: type=mf, serial_delay=250, paste_delay=100000, user_shortcut=none
 | 
			
		||||
mouse: type=ps2, enabled=false, toggle=ctrl+mbutton
 | 
			
		||||
speaker: enabled=true, mode=system
 | 
			
		||||
parport1: enabled=true, file=none
 | 
			
		||||
parport2: enabled=false
 | 
			
		||||
com1: enabled=true, mode=null
 | 
			
		||||
com2: enabled=false
 | 
			
		||||
com3: enabled=false
 | 
			
		||||
com4: enabled=false
 | 
			
		||||
							
								
								
									
										31
									
								
								boot.nasm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								boot.nasm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
			
		||||
[ORG 0x7c00]
 | 
			
		||||
[BITS 16]
 | 
			
		||||
 | 
			
		||||
xor ax, ax
 | 
			
		||||
mov ds, ax
 | 
			
		||||
mov es, ax
 | 
			
		||||
mov ah, 0x42
 | 
			
		||||
mov si, addr_packet
 | 
			
		||||
int 0x13
 | 
			
		||||
jnc 0x8000
 | 
			
		||||
push 0xb800
 | 
			
		||||
pop es
 | 
			
		||||
xor di, di
 | 
			
		||||
mov si, string
 | 
			
		||||
mov cx, 10
 | 
			
		||||
mov ah, 0x7
 | 
			
		||||
err_print:
 | 
			
		||||
lodsb
 | 
			
		||||
stosw
 | 
			
		||||
loop err_print
 | 
			
		||||
hlt_loop:
 | 
			
		||||
hlt
 | 
			
		||||
jmp hlt_loop
 | 
			
		||||
 | 
			
		||||
string: db 'DISK ERROR'
 | 
			
		||||
 | 
			
		||||
addr_packet:
 | 
			
		||||
db 0x10, 0x00 ; size, reserved
 | 
			
		||||
dw 0x20 ; blocks
 | 
			
		||||
dd 0x8000 ; transfer buffer
 | 
			
		||||
dq 1 ; start block
 | 
			
		||||
							
								
								
									
										337
									
								
								entry.nasm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										337
									
								
								entry.nasm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,337 @@
 | 
			
		||||
[BITS 16]
 | 
			
		||||
 | 
			
		||||
global entry
 | 
			
		||||
entry:
 | 
			
		||||
cli             ; no interrupts
 | 
			
		||||
xor ax,ax
 | 
			
		||||
mov ds, ax
 | 
			
		||||
lgdt [gdt_desc]  ; load gdt register
 | 
			
		||||
mov eax, cr0    ; set pmode bit
 | 
			
		||||
or al, 1
 | 
			
		||||
mov cr0, eax
 | 
			
		||||
jmp 08h:Pmodecode
 | 
			
		||||
 | 
			
		||||
[BITS 32]
 | 
			
		||||
Pmodecode:
 | 
			
		||||
mov ax, 0x10 ; set up segments
 | 
			
		||||
mov ds, ax
 | 
			
		||||
mov es, ax
 | 
			
		||||
mov ss, ax
 | 
			
		||||
mov ebp, 0x400000
 | 
			
		||||
mov esp, ebp
 | 
			
		||||
mov eax, 0x1f001f00
 | 
			
		||||
mov ecx, (80*25)/2
 | 
			
		||||
mov edi, 0xb8000
 | 
			
		||||
rep stosd
 | 
			
		||||
call start
 | 
			
		||||
hlt_loop:
 | 
			
		||||
hlt
 | 
			
		||||
jmp hlt_loop
 | 
			
		||||
 | 
			
		||||
setup_paging:
 | 
			
		||||
mov ecx, 1024*3 ; 3K?
 | 
			
		||||
xor eax, eax
 | 
			
		||||
mov edi, 0x1000
 | 
			
		||||
rep stosd ; zero first 3K for some reason
 | 
			
		||||
mov edi, 0x4000
 | 
			
		||||
mov eax, 0x800007 ; 8MB + 7
 | 
			
		||||
std ; fill backwards
 | 
			
		||||
.fill:
 | 
			
		||||
stosd
 | 
			
		||||
sub eax, 0x1000
 | 
			
		||||
jge .fill
 | 
			
		||||
cld ; fix direction
 | 
			
		||||
mov dword [0x0000], 0x2000 + 7
 | 
			
		||||
mov dword [0x0004], 0x3000 + 7
 | 
			
		||||
mov eax, 0x1000
 | 
			
		||||
mov cr3, eax ; page dir start 0x1000
 | 
			
		||||
mov eax, cr0
 | 
			
		||||
or eax, 0x80000000
 | 
			
		||||
mov cr0, eax ; set paging bit
 | 
			
		||||
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:
 | 
			
		||||
mov dword [0xb8000], 0x0f000f00 | 'U' | 's' << 16
 | 
			
		||||
mov dword [0xb8004], 0x0f000f00 | 'e' | 'r' << 16
 | 
			
		||||
mov dword [0xb8008], 0x0f000f00 | 'm' | 'o' << 16
 | 
			
		||||
mov dword [0xb800C], 0x0f000f00 | 'd' | 'e' << 16
 | 
			
		||||
mov word [0xb8010], 0x0f00 | '!'
 | 
			
		||||
mov edi, 0xA0000
 | 
			
		||||
xor eax, eax
 | 
			
		||||
.loop:
 | 
			
		||||
mov cx, 320
 | 
			
		||||
rep stosb
 | 
			
		||||
inc al
 | 
			
		||||
cmp eax, 200
 | 
			
		||||
jl .loop
 | 
			
		||||
xor ebx, ebx
 | 
			
		||||
div bl
 | 
			
		||||
 | 
			
		||||
global jmp_usermode_test
 | 
			
		||||
jmp_usermode_test:
 | 
			
		||||
mov ax, 0x20 | 3
 | 
			
		||||
mov ds, ax
 | 
			
		||||
mov es, ax
 | 
			
		||||
mov fs, ax
 | 
			
		||||
mov gs, ax
 | 
			
		||||
mov eax, esp
 | 
			
		||||
push 0x20 | 3
 | 
			
		||||
push eax
 | 
			
		||||
pushfd
 | 
			
		||||
push 0x18 | 3
 | 
			
		||||
push user_test
 | 
			
		||||
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
 | 
			
		||||
flushTSS:
 | 
			
		||||
mov ax, 0x28
 | 
			
		||||
ltr ax
 | 
			
		||||
ret
 | 
			
		||||
 | 
			
		||||
extern tss_data
 | 
			
		||||
 | 
			
		||||
extern start
 | 
			
		||||
 | 
			
		||||
gdt_desc:
 | 
			
		||||
    dw gdt_end - gdt
 | 
			
		||||
    dd gdt
 | 
			
		||||
gdt:
 | 
			
		||||
gdt_null: dq 0
 | 
			
		||||
gdt_code: dw 0xFFFF, 0     ; bits 0-15 limit (4GB), bits 0-15 base address
 | 
			
		||||
          db 0             ; bits 16-23 base address
 | 
			
		||||
          db 10011010b     ; access byte
 | 
			
		||||
          db 11001111b     ; bits 16-19 limit (4GB), 4 bits flags
 | 
			
		||||
          db 0 ; bits 24-31 base address
 | 
			
		||||
gdt_data: dw 0xFFFF, 0     ; bits 0-15 limit (4GB), bits 0-15 base address
 | 
			
		||||
          db 0             ; bits 16-23 base address
 | 
			
		||||
          db 10010010b     ; access byte
 | 
			
		||||
          db 11001111b     ; bits 16-19 limit (4GB), 4 bits flags
 | 
			
		||||
          db 0 ; bits 24-31 base address
 | 
			
		||||
gdt_r3code: dw 0xFFFF, 0     ; bits 0-15 limit (4GB), bits 0-15 base address
 | 
			
		||||
          db 0             ; bits 16-23 base address
 | 
			
		||||
          db 0xFA     ; access byte
 | 
			
		||||
          db 11001111b     ; bits 16-19 limit (4GB), 4 bits flags
 | 
			
		||||
          db 0 ; bits 24-31 base address
 | 
			
		||||
gdt_r3data: dw 0xFFFF, 0     ; bits 0-15 limit (4GB), bits 0-15 base address
 | 
			
		||||
          db 0             ; bits 16-23 base address
 | 
			
		||||
          db 0xF2     ; access byte
 | 
			
		||||
          db 11001111b     ; bits 16-19 limit (4GB), 4 bits flags
 | 
			
		||||
          db 0 ; bits 24-31 base address
 | 
			
		||||
gdt_tss:  dw 0x2080, 0x0000;26*4, tss_data     ; bits 0-15 limit (4GB), bits 0-15 base address
 | 
			
		||||
          db 0x2             ; bits 16-23 base address
 | 
			
		||||
          db 0x89     ; access byte
 | 
			
		||||
          db 00000000b     ; bits 16-19 limit (4GB), 4 bits flags
 | 
			
		||||
          db 0 ; bits 24-31 base address
 | 
			
		||||
gdt_end:
 | 
			
		||||
							
								
								
									
										453
									
								
								kernel.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										453
									
								
								kernel.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,453 @@
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
typedef unsigned short word;
 | 
			
		||||
 | 
			
		||||
char nibbleToHex(char n) {
 | 
			
		||||
    return n > 9 ? (n - 10) + 'A' : n + '0';
 | 
			
		||||
}
 | 
			
		||||
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() {
 | 
			
		||||
    uint32_t eax, ebx, ecx, edx;
 | 
			
		||||
    asm("cpuid" : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx) : "a"(1));
 | 
			
		||||
    return (edx & (1 << 9)) != 0;
 | 
			
		||||
}
 | 
			
		||||
char check_sse() {
 | 
			
		||||
    uint32_t eax, ebx, ecx, edx;
 | 
			
		||||
    asm("cpuid" : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx) : "a"(1));
 | 
			
		||||
    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() {
 | 
			
		||||
    asm volatile(
 | 
			
		||||
        "mov %%cr0, %%eax\n"
 | 
			
		||||
        "and $0xFFFB, %%ax\n"
 | 
			
		||||
        "or $0x2, %%ax\n"
 | 
			
		||||
        "mov %%eax, %%cr0\n"
 | 
			
		||||
        "mov %%cr4, %%eax\n"
 | 
			
		||||
        "or $0x600, %%ax\n"
 | 
			
		||||
        "mov %%eax, %%cr4\n"
 | 
			
		||||
        : : : "%eax"
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void print_flags() {
 | 
			
		||||
    uint32_t flags;
 | 
			
		||||
    asm volatile("pushfd\npop %%eax":"=a"(flags));
 | 
			
		||||
    printDword(flags, 0xB8000 + (160*4) + 50);
 | 
			
		||||
}
 | 
			
		||||
void print_cr0() {
 | 
			
		||||
    uint32_t reg;
 | 
			
		||||
    asm volatile("mov %%cr0, %%eax":"=a"(reg));
 | 
			
		||||
    printDword(reg, 0xB8000 + (160*5) + 50);
 | 
			
		||||
}
 | 
			
		||||
void print_cr3() {
 | 
			
		||||
    uint32_t reg;
 | 
			
		||||
    asm volatile("mov %%cr3, %%eax":"=a"(reg));
 | 
			
		||||
    printDword(reg, 0xB8000 + (160*5) + 50 + 8*2 + 2);
 | 
			
		||||
}
 | 
			
		||||
void print_cr4() {
 | 
			
		||||
    uint32_t reg;
 | 
			
		||||
    asm volatile("mov %%cr4, %%eax":"=a"(reg));
 | 
			
		||||
    printDword(reg, 0xB8000 + (160*5) + 50 + 8*4 + 4);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extern void enter_v86(uint32_t ss, uint32_t esp, uint32_t cs, uint32_t eip);
 | 
			
		||||
extern void v86Code();
 | 
			
		||||
extern void flushTSS();
 | 
			
		||||
extern void jmp_usermode_test();
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
Real Mode Accessible (First MB)
 | 
			
		||||
 00000 -  02000 IVT
 | 
			
		||||
 01000 -  04000 Paging
 | 
			
		||||
 04000 -  07C00 Free
 | 
			
		||||
 07C00 -  08000 Boot
 | 
			
		||||
 08000 -  20000 Kernel Code
 | 
			
		||||
 20000 -  22080 TSS
 | 
			
		||||
 80000 -  90000 Real Mode Stack
 | 
			
		||||
 90000 -  A0000 Free
 | 
			
		||||
 A0000 -  FFFFF BIOS Area
 | 
			
		||||
Protected Only (1MB+)
 | 
			
		||||
100000 -        Free
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
void start() {
 | 
			
		||||
    word *vga_text = (word *)0xb8000;
 | 
			
		||||
    char h[] = "LuciaOS";
 | 
			
		||||
    for (int i = 0; i < sizeof(h); i++)
 | 
			
		||||
        *(char *)&vga_text[i] = h[i];
 | 
			
		||||
 | 
			
		||||
    uint32_t o;
 | 
			
		||||
    asm("mov %%esp, %%eax" : "=a"(o) : :);
 | 
			
		||||
    printDword(o, (short *)&vga_text[80]);
 | 
			
		||||
    asm("mov %%ebp, %%eax" : "=a"(o) : :);
 | 
			
		||||
    printDword(o, (short *)&vga_text[160]);
 | 
			
		||||
 | 
			
		||||
    //char c[] = "APIC support: ";
 | 
			
		||||
    //char apic;
 | 
			
		||||
    //printByte(apic = check_apic(), (short*)&vga_text[80*3 + sizeof(c) - 1]);
 | 
			
		||||
    //for (int i = 0; i < sizeof(c); i++)
 | 
			
		||||
    //    *(char *)&vga_text[i+(80*3)] = c[i];
 | 
			
		||||
    //if (!apic) return;
 | 
			
		||||
 | 
			
		||||
    char sse_str[] = "SSE support: ";
 | 
			
		||||
    char sse;
 | 
			
		||||
    printByte(sse = check_sse(), (short*)&vga_text[80*4 + sizeof(sse_str) - 1]);
 | 
			
		||||
    for (int i = 0; i < sizeof(sse_str); i++)
 | 
			
		||||
        *(char *)&vga_text[i+(80*4)] = sse_str[i];
 | 
			
		||||
    if (!sse) return;
 | 
			
		||||
    enable_sse();
 | 
			
		||||
 | 
			
		||||
    setup_interrupts();
 | 
			
		||||
    write_tss();
 | 
			
		||||
    flushTSS();
 | 
			
		||||
    print_flags();
 | 
			
		||||
    print_cr0();
 | 
			
		||||
    print_cr3();
 | 
			
		||||
    print_cr4();
 | 
			
		||||
    FARPTR v86_entry = i386LinearToFp(v86Code);
 | 
			
		||||
    enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry));
 | 
			
		||||
    //jmp_usermode_test();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user