%include "asm.inc"
%define STUB_STAT _stub_stat
BITS 32
GLOBAL entry_point
GLOBAL __exit
GLOBAL __fpu_family
GLOBAL __cpu_family
GLOBAL __cpu_model
GLOBAL __cpu_steppingID
GLOBAL __cpu_feature
GLOBAL __cpu_vendor
GLOBAL __cr4
EXTERN _start
EXTERN STUB_STAT
EXTERN end_datas
EXTERN end_bsss
SECTION .data
temp dw 0
__fpu_family db 0
__cpu_family db 3
__cpu_model db 0
__cpu_steppingID db 0
__cpu_feature dd 0
__cpu_vendor_ db 'unknown',0,0,0,0,0,0
__cpu_vendor dd __cpu_vendor_
__cr4 dd 0
saved_ss_esp dd 0
dw 0
saved_gdt dw 0
dd 0
SECTION .text
;
; questo e` l'indirizzo che viene chiamato dal loader.
; la paginazione e` gia` attiva, occhio pero` che per risparmiare
; memoria ho messo il pde e i pte nella memoria video :)
;
; secondo il draft del 10/09/197 il kernel dovrebbe essere caricato
; a 512Mb, e la memoria kernel e` riservata fino a 1Gb.
; quindi ci sono 512Mb di spazio per il kernel, dovrebbero essere
; sufficiente per tutti ... [come disse l'amico Bill per i 640K del dos]
;
; la versione 0.6 dello stub comunque mappa solo i primi 4Mb a partire
; dall'indirizzo virtuale base del kernel, e poi mappa il primo Mb 1:1.
;
;
; i selettori sono :
; 30h punta allo stub (256 bytes)
; 38h dati (limite 4G)
; 40h codice (4G)
; 48h TSS _TEMPORANEO_ (non deve essere + richiamato!)
;
; DS = ES = SS = dati [30h]
; FS = stub selector GS = ?
;
; TR=48h, ldt=0, idt=0
;
; esp = stack dello stub, poco meno di 1K disponibile ... magari usero`
; un po' di memoria video anche per questo :)
;
; tutti i flags sono stati azzerati (DF,IF,..)
;
;-----
; la versione 0.61 dello stub mappa i primi 12Mb di memoria fisica, e 4 kernel
; inoltre l'indirizzo del kernel e` cambiato, ora e` 3Gb, la memoria da
; 1Gb fino a 3Gb e` disponibile. la memoria < 1Gb e` riservata per altri scopi
entry_point:
;
; salva lo stack
;
mov dword [saved_ss_esp],esp
mov word [saved_ss_esp+4],ss
;
; salva gdt
;
sgdt [saved_gdt]
;
; azzera bss
;
mov edi,end_datas
mov ecx,end_bsss
xor eax,eax
sub ecx,edi
rep stosb
;
; copia stub_stat
;
xor esi,esi
cmp word [fs:esi],'V0' ; confronta magic (versione)
mov al,0xff
jne __exit
mov cx,[fs:esi+2] ; legge dimensione da trasferire
add esi,4
mov edi,STUB_STAT
.copy
mov al,[fs:esi]
inc esi
mov [edi],al
inc edi
loop .copy,cx
mov fs,cx ; azzera fs e gs
mov gs,cx
call cpu_info
call fpu_info
cmp byte [__fpu_family],0
setne al
or byte [__cpu_feature],al
call set_cr
mov bx,0xF8F0
mov cl,3
call pic_setup
call _start
__exit:
; eax = exit
cli
mov ebp,eax
mov bx,0x7008
mov cl,1
call pic_setup
mov bx,KERNEL_DS
mov ds,bx
; cmp dword [__cr4],0
; je .nocr4
; xor ebx,ebx
; mov cr4,ebx
.nocr4
lgdt [saved_gdt] ; DS deve sempre essere 30h !!
lss esp, [saved_ss_esp]
mov eax,ebp
retf
;
; in: copia il bit %1 di edx alla posizione %2 in ebx
;
;
%macro testbt 2
xor ecx,ecx
bt edx,%1
rcl ecx,%2+1
or ebx,ecx
%endm
set_cr:
;
; setup per cr4 (registro ebx)
;
mov edx,[__cpu_feature]
xor ebx,ebx
testbt 1,0 ; VM86 Mode Ex
testbt 1,1 ; PVI
testbt 2,3 ; Debug Extension
testbt 3,4 ; Page Size extension
testbt 13,7 ; Page Global
test ebx,ebx
jz .nocr4
mov cr4,ebx
mov [__cr4],ebx
.nocr4
;
; setup per cr0
;
mov ebx,0x80000001
testbt 0,1
cmp byte [__cpu_family],4
jb .end
je .486
or ebx,50020h ; AM WP NE
.486
or ebx,50000h ; AM WP
.end
mov cr0,ebx
ret
cpu_info:
pushfd
pop eax
mov eax,ecx
xor eax,0x40000
push eax
popfd
pushfd
pop eax
xor eax,ecx
and eax,0x40000
jz .end
mov byte [__cpu_family],4 ; 486
mov eax,ecx
xor eax,0x200000
push eax
popfd
pushfd
pop eax
xor eax,ecx
jz .end
push ecx ; 486DX4/Pentium+
popfd
xor eax,eax
cpuid
mov [__cpu_vendor_],ebx
mov [__cpu_vendor_+4],edx
mov [__cpu_vendor_+8],ecx
test eax,eax
jz .end
mov eax,1
cpuid
mov cl,al
and cl,0x0f
mov [__cpu_steppingID],al
shr al,4
mov [__cpu_model],al
mov cl,ah
and cl,0x0f
mov [__cpu_family],cl
mov [__cpu_feature],edx
.end
ret
fpu_info:
clts
fninit
mov word [temp],0x5a5a
fstsw [temp]
mov ax,[temp]
cmp al,0
jnz .end
mov byte [__fpu_family],2
mov eax,cr0
shr eax,5
jnc .end
inc byte [__fpu_family]
.end
ret
;
; BL = PIC #1 vect
; BH = PIC #2 vect
; CL = 1 -> standard, 3 -> auto EOI
%macro delay 0
dw 00ebh
dw 00ebh
%endm
pic_setup:
mov al,0x11 ;init command
out 0x20,al
delay
out 0xa0,al
mov ax,bx ; set vector
out 0x21,al
xchg al,ah
delay
out 0xa1,al
mov al,4
out 0x21,al ; irq 2 = cascade
mov al,2
delay
out 0xa1,al ; irq 9 ->irq2
mov al,cl ; mode control, 1 = standard, 3 auto EOI
out 0x21,al
delay
out 0xa1,al
;
; keyboard reset
;
delay
in al,60h
delay
or al,80h
out 60h,al
delay
and al,7fh
out 60h,al
ret