cos2000v2/boot/loader.asm

732 lines
15 KiB
NASM
Raw Blame History

[BITS 16]
[ORG 0x100]
SECTION .text
push cs
push cs
pop ds
pop es
mov si,msg0
call showstr
mov si,msg1
call showstr
call initfat
call ok
mov si,msg2
call showstr
mov si,System_File
call search
call ok
mov si,msg3
call showstr
call EnableA20
call ok
mov si,msg4
call showstr
mov eax,cs
shl eax,4
mov [GDT.Entry1+2],ax
mov [GDT.Entry2+2],ax
shr eax,16
mov [GDT.Entry1+4],al
mov [GDT.Entry2+4],al
mov eax,cs
shl eax,4
add eax,gdt0
mov [GDTR.Address],eax
lgdt [GDTR]
call ok
mov si,msg5
call showstr
cli
mov eax,cr0
or al,1
mov cr0,eax
jmp short $+2
mov bx,SYS_DATA_SEL
mov fs,bx
mov ds,bx
mov es,bx
mov gs,bx
and al,0FEh
mov cr0,eax
jmp short $+2
mov bx,cs
mov fs,bx
mov ds,bx
mov es,bx
mov gs,bx
sti
call ok
mov si,msg6
call showstr
mov ebx,0x300000
call load
call ok
mov si,msg7
call showstr
call initpe
call ok
mov si,msg8
call showstr
cli
mov al,0x80
out 0x70,al
mov eax,cr0
or al,1
mov cr0,eax
jmp SYS_CODE_SEL:GoPMode32
Boot_Error:
mov si,error
call showstr
xor ax,ax
int 16h
jmp 0xFFFF:0x0
ok:
push si
push cx
mov cl,67
call eol
mov si,okay
call showstr
pop cx
pop si
ret
;======================INITPE========================
;Initialise le PE de l'adresse EBX
;->
;<- Flag Carry si erreur
;=====================================================
initpe:
pusha
push es
xor ax,ax
mov es,ax
mov [begin],ebx
cmp word [es:ebx+mzheader.magic],"MZ" ; bien l'entete .exe dos ?
jne near errorpe
add ebx,[es:ebx+mzheader.lfanew] ; Pointe vers l'entete PE
cmp word [es:ebx+peheader.Signature],"PE" ; bien l'entete PE ?
jne near errorpe
cmp word [es:ebx+peheader.Signature+2],0 ; bien l'entete PE ?
jne near errorpe
mov [p_pe],ebx
mov esi,[es:ebx+peheader.ImageBase]
mov [base],esi
add esi,[es:ebx+peheader.AddressOfEntryPoint]
mov [entriepoint],esi
mov ax,[es:ebx+peheader.NumberOfSections]
add ebx,peheader.end
mov [p_sections],ebx
mov si,info1
call showstr
readsections:
mov si,info2
call showstr
mov esi,ebx
mov cx,8
call showfixstr
mov cl,17
call eol
mov edx,[es:ebx+sections.VirtualAddress]
add edx,[base]
mov cx,32
call ShowHex
mov cl,30
call eol
mov si,info3
call showstr
mov edx,[es:ebx+sections.VirtualSize]
mov cx,32
call ShowHex
mov si,info4
call showstr
mov edi,[es:ebx+sections.VirtualAddress]
add edi,[base]
cmp edi,0
je noload
push eax
push ecx
mov esi,[es:ebx+sections.PointerToRawData]
add esi,[begin]
mov ecx,[es:ebx+sections.SizeOfRawData]
shr cx,2
cmp cx,0
je zeroize
copietomem:
mov eax,[es:esi]
mov [es:edi],eax
add edi,4
add esi,4
dec cx
jnz copietomem
pop ecx
pop eax
jmp nextsymb
zeroize:
mov ecx,[es:ebx+sections.VirtualSize]
shr cx,2
mov eax,0
zerotomem:
mov [es:edi],eax
add edi,4
dec cx
jnz zerotomem
pop ecx
pop eax
jmp nextsymb
noload:
mov si,info5
call showstr
nextsymb:
mov si,return
call showstr
add ebx,sections.end
dec ax
jnz readsections
mov si,info6
call showstr
mov edx,[entriepoint]
mov cx,32
call ShowHex
clc
pop es
popa
ret
errorpe:
stc
pop es
popa
ret
entriepoint dd 0
begin dd 0
base dd 0
p_pe dd 0
p_sections dd 0
;==========SHOWHEX===========
;Affiche un nombre hexad<61>cimal EDX de taille CX apr<70>s le curseur
;-> AH=10, EDX un entier, CX la taille
;<-
;===========================================
ShowHex:
push ax
push bx
push cx
push edx
mov ax,cx
shr ax,2
sub cx,32
neg cx
shl edx,cl
xor cx,cx
inc cx
Hexaize:
rol edx,4
mov bx,dx
and bx,0fh
push ax
mov al,[cs:bx+Tab]
xor bx,bx
mov ah,0x09
mov bl,[cs:thecolor]
int 0x10
mov ah,0x0E
int 0x10
pop ax
dec al
jnz Hexaize
pop edx
pop cx
pop bx
pop ax
ret
Tab db '0123456789ABCDEF'
;======================EOL========================
;Va en colonne CX
;->
;<- Flag Carry si erreur
;=====================================================
eol:
pusha
mov bp,cx
mov ah,03
xor bx,bx
int 10h
mov ah,02
mov cx,bp
mov dl,cl
int 10h
popa
ret
;======================LOAD========================
;Charge le groupe en m<>moire en ebx
;->
;<- Flag Carry si erreur
;=====================================================
load:
push ax
push ebx
push ecx
push edx
push esi
push edi
push fs
xor edx,edx
xor ax,ax
mov fs,ax
mov si,The_Dot
mov dx,[Sectors_Size]
Resume_Loading:
cmp cx,0x0FF0
jae Finish_Loading
push cx
add cx,word [data]
mov edi,Buffer
call ReadSector
pop cx
jc near Boot_Error
call showstr
push esi
push ebx
push cx
mov esi,Buffer
mov cx,dx
shr cx,2
copie:
mov eax,[ds:esi]
mov [fs:ebx],eax
add ebx,4
add esi,4
dec cx
jnz copie
pop cx
pop ebx
pop esi
add ebx,edx
call NextFatGroup
jc near Boot_Error
jmp Resume_Loading
Finish_Loading:
pop fs
pop edi
pop esi
pop edx
pop ecx
pop ebx
pop ax
ret
;======================INITFAT========================
;Initialise les variables de la fat
;->
;<- Flag Carry si erreur
;=====================================================
initfat:
pusha
push ds
xor ax,ax
mov ds,ax
mov si,0x7C0B
mov di,bootsector
mov cx, 512
rep movsb
pop ds
mov cx,[Reserved_Sectors]
add cx,[Sectors_Hidden]
adc cx,[Sectors_Hidden+2]
mov bx,[Sectors_Per_Fat]
mov di,Fat_Buffer
push bx
push cx
readfat:
call ReadSector
jc Boot_Error
inc cx
add di,[Sectors_Size]
dec bx
jnz readfat
pop cx
pop bx
xor ax,ax
mov al,[Fats_Number]
mul bx
add cx,ax
mov [entries],cx
mov ax,32
mul word [Fits_Number]
div word [Sectors_Size]
add cx,ax
sub cx,2
mov word [data],cx
popa
ret
;======================SEARCH========================
;Recherche le groupe d'un fichier
;-> si nom du fichier
;<- Flag Carry si erreur CX
;=====================================================
search:
push bx
push dx
push di
mov cx,[entries]
mov di,Buffer
call ReadSector
jc Boot_Error
xor bx,bx
Next_Root_Entrie:
cmp byte [di],0
je Boot_Error
push si
push di
push cx
mov cx,11
rep cmpsb
pop cx
pop di
pop si
je Found
add di,32
add bx,32
inc dx
cmp dx,[Fits_Number]
ja Boot_Error
cmp bx,[Sectors_Size]
jb Next_Root_Entrie
inc cx
Found:
mov cx,[di+26]
pop di
pop dx
pop bx
ret
;======================SHOWSTR========================
;Affiche la chaine de caract<63>re point<6E> par ds:si <20> l'<27>cran
;-> DS, SI
;<- Flag Carry si erreur
;=====================================================
showstr:
pusha
xor bh,bh
xor cx,cx
inc cx
nextchar:
lodsb
or al,al
jz endshow
cmp al,' '
jb justchar
cmp al,'#'
jne nocolor
lodsb
sub al,'0'
shl al,3
mov [cs:thecolor],al
shr al,2
add [cs:thecolor],al
lodsb
sub al,'0'
add [cs:thecolor],al
jmp nextchar
nocolor:
xor bx,bx
mov ah,0x09
mov bl,[cs:thecolor]
int 0x10
justchar:
mov ah,0x0E
int 0x10
jmp nextchar
endshow:
popa
ret
;======================SHOWFIXEDSTR========================
;Affiche la chaine de caract<63>re point<6E> par esi <20> l'<27>cran pour CX caract<63>res
;-> DS, SI
;<- Flag Carry si erreur
;=====================================================
showfixstr:
pusha
push ds
xor ax,ax
mov ds,ax
xor bh,bh
mov dx,cx
xor cx,cx
inc cx
nextchars:
mov al,[ds:esi]
inc esi
or al,al
jz endshows
cmp al,' '
jb justchars
xor bx,bx
mov ah,0x09
mov bl,[cs:thecolor]
int 0x10
justchars:
mov ah,0x0E
int 0x10
dec dx
jnz nextchars
endshows:
pop ds
popa
ret
;====================READSECTOR=======================
;Lit le secteur logique LBA CX et le met en es:di
;-> CX (limit<69> <20> 65536 secteurs, soit 32 Mo avec secteur 512 octets)
;<- Flag Carry si erreur
;=====================================================
ReadSector:
pusha
mov ax,cx
xor dx,dx
div word [Sectors_Per_Track]
inc dl
mov bl,dl
xor dx,dx
div word [Heads_Number]
mov dh, [Boot_Drive]
xchg dl,dh
mov cx,ax
xchg cl,ch
shl cl,6
or cl, bl
mov bx,di
mov si, 4
mov al, 1
Read_Again:
mov ah, 2
int 0x13
jnc Read_Done
dec si
jnz Read_Again
Read_Done:
popa
ret
;===================NEXTFATGROUP======================
;Renvoie en CX le groupe qui succ<63>de dans la FAT le groupe CX
;-> CX
;<-
;=====================================================
NextFatGroup:
push bx
push dx
push di
mov ax,cx
mov bx,ax
and bx,0000000000000001b
shr ax,1
mov cx,3
mul cx
mov di,Fat_Buffer
add di,ax
cmp bx,0
jnz Even_Group
Odd_Group:
mov dx,[di]
and dx,0x0FFF
mov cx,dx
jmp Next_Group_Found
Even_Group:
mov dx,[di+1]
and dx,0xFFF0
shr dx,4
mov cx,dx
Next_Group_Found:
pop di
pop dx
pop bx
ret
;***********************EnableA20*******************************
;->
;<-
;Ouvre l'autoroute A20
;***************************************************************
EnableA20:
cli
call ClearKeybBuffer
call WaitKeybCommand
mov al,0xd1
out 0x64,al
call WaitKeybCommand
mov al,0xdf
out 0x60,al
call WaitKeybCommand
jmp A20Enabled
WaitKeybCommand:
in al,0x64
test al,0x02
jnz WaitKeybCommand
ret
ClearKeybBuffer:
in al,0x64
test al,0x01
jnz ReadKeyb
ret
ReadKeyb:
in al,0x60
jmp ClearKeybBuffer
A20Enabled:
sti
ret
GoPMode32:
[BITS 32]
mov ax,ALL_DATA_SEL
mov es,ax
mov gs,ax
mov fs,ax
mov ss,ax
mov ds,ax
mov esp,0x3fffff
push KERNEL_SEL
push dword [cs:entriepoint]
retf
; jmp KERNEL_SEL:0x401020
section .data
thecolor db 0x07
msg0 db '#12-=< Lancement du Chargeur PE >=-',0x0A,0x0D,0x0A,0x0D,0
msg1 db '#07Initialisation de la FAT',0
msg2 db '#07Recherche du systeme',0
msg3 db '#07Activation adressage 24 bits',0
msg4 db '#07Chargement des descripteurs',0
msg5 db '#07Passage en mode Flat real',0
msg6 db '#07Chargement du systeme',0
msg7 db '#07Mise en place image PE',0
msg8 db '#07Passage en mode protege',0
msg9 db '#07Execution du noyau',0
info1 db 0x0A,0x0D,'#08Sections :',0x0A,0x0D,0
info2 db ' -',0
info3 db ' (',0
info4 db ') ',0
info5 db ' #12Non projete#08',0
info6 db 'Point entree en ',0
return db 0x0A,0x0D,0
okay db ' #15[ #10OK #15]',0x0A,0x0D,0
error db ' #15[#12Erreur#15]',0x0A,0x0D,0x0A,0x0D,' <Appuyez une touche pour redemarrer>',0
The_Dot db '.',0
System_File db "SYSTEM SYS"
entries dw 0
data dw 0
xy dw 0
GDTR:
.Size: dw GDT_END
.Address: dd 0
gdt0 equ $ ; null entry
GDT:
.Entry0: dw 0 ; limit 15:0
dw 0 ; base 15:0
db 0 ; base 23:16
db 0 ; type
db 0 ; limit 19:16, flags
db 0 ; base 31:24
SYS_CODE_SEL equ $-gdt0 ; code segment descriptor
.Entry1: dw 0xFFFF
dw 0x0 ; base
db 0x0 ; base
db 0x9A ; present, ring 0, code, non-conforming, readable
db 0xCF ; 32 bit
db 0
SYS_DATA_SEL equ $-gdt0 ; data segment descriptor
.Entry2: dw 0xFFFF
dw 0x0 ; base
db 0x0 ; base
db 0x92 ; present, ring 0, data, expand-up, writable
db 0xCF ; 32 bit
db 0
ALL_DATA_SEL equ $-gdt0 ; 4meg data segment descriptor
.Entry3: dw 0xFFFF
dw 0x0 ; base
db 0x0 ; base
db 0x92 ; present, ring 0, data, expand-up, writable
db 0xCF ; 4k pages, 32 bit
db 0
KERNEL_SEL equ $-gdt0 ; 4g code segment descriptor
.Entry4: dw 0xffff
dw 0x0 ; base
db 0x0 ; base
db 0x9A ; present, ring 0, code, non-conforming, readable
db 0xCF ; 4k pages, 32 bit
db 0
GDT_END equ $-gdt0 -1
bootsector equ $
Sectors_Size dw 0 ;Nombre d'octets/secteur
Sectors_Per_Cluster db 0 ;Nombre de secteurs/cluster
Reserved_Sectors dw 0 ;Nombre de secteurs r<>serv<72>
Fats_Number db 0 ;Nombre de copies de la FAT
Fits_Number dw 0 ;Taille du r<>pertoire racine
Sectors_Per_Disk dw 0 ;Nombre secteurs du volume si < 32 Mo
Media_Descriptor db 0 ;Descripteur de m<>dia
Sectors_Per_Fat dw 0 ;Nombre secteurs/FAT
Sectors_Per_Track dw 0 ;Nombre secteurs/piste
Heads_Number dw 0 ;Nombre de tete de lecture/<2F>criture
Sectors_Hidden dd 0 ;Nombre de secteurs cach<63>s
Sectors_Per_Disk2 dd 0 ;Nombre secteurs du volume si > 32 Mo
Boot_Drive db 0 ;Lecteur de d<>marrage
Reserved db 0 ;NA (pour NT seulement)
Extended_Boot_ID db 0 ;Signature Boot <20>tendu 29h
Buffer equ $
Fat_Buffer equ $+512
SECTION .bss
%include "pe.h"