;/*******************************************************************************/ ;/* COS2000 - Compatible Operating System - LGPL v3 - Hordé Nicolas */ ;/* */ [BITS 16] [ORG 0x0] SECTION .text push cs push cs pop ds pop es mov si,msg0 call showstr ;Projection de la FAT12 en mémoire mov si,msg1 call showstr call initfat call ok ;Recherche du système mov si,msg2 call showstr mov si,System_File call search call ok ;Activation du BUS A20 mov si,msg3 call showstr call EnableA20 call ok ;Chargement d'une GDT pour le mode FLAT REAL 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 ;Passage en mode FLAT REAL 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 ;Chargement du noyau en 0x30000 mov si,msg6 call showstr mov ebx,0x300000 call load call ok ;Chargement du fichier PE mov si,msg7 call showstr call initpe call ok ;suite: ;mov cx,suite ;call debug mov si,msg8 call showstr cli ;Passage en mode protégé mov al,0x80 out 0x70,al mov eax,cr0 or al,1 mov cr0,eax ;Exécution du code 32 bits 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+ELFheader.Magic],0x457F ; bien l'entete .elf ? jne near errorelf cmp word [es:ebx+ELFheader.Magic+2],"LF" ; bien l'entete .elf ? jne near errorelf cmp byte [es:ebx+ELFheader.Computertype],0x1 ; type ok ? jne near errorelf cmp byte [es:ebx+ELFheader.Endianness],0x1 ; type ok ? jne near errorelf cmp byte [es:ebx+ELFheader.Original],0x1 ; type ok ? jne near errorelf cmp byte [es:ebx+ELFheader.OS],0x0 ; type ok ? jne near errorelf cmp byte [es:ebx+ELFheader.ABI],0x0 ; type ok ? jne near errorelf cmp byte [es:ebx+ELFheader.Dummy],0x0 ; type ok ? jne near errorelf mov si,info1 call showstr mov esi,[es:ebx+ELFheader.Entrypoint] mov [entriepoint],esi mov esi,[es:ebx+ELFheader.Offsetprogram] add esi,ebx mov [offsetheader],esi mov esi,[es:ebx+ELFheader.Offsetsection] add esi,ebx mov [offsetsection],esi mov cx,[es:ebx+ELFheader.Nbprogram] mov [cs:nbprogram],cx mov cx,[es:ebx+ELFheader.Nbsection] mov [cs:nbsection],cx xor eax,eax mov ax,[es:ebx+ELFheader.Index] xor edx,edx mov dx,[es:ebx+ELFheader.Sizesection] mul edx add eax,esi mov eax,[es:eax+Sections.Offset] add eax,ebx mov [cs:symbol],eax xor eax,eax add ax,[es:ebx+ELFheader.Sizesection] add esi,eax sections: mov edi,esi cmp dword [es:edi+Sections.Type],0x00 jz nothing mov esi,info2 call showstr push ds push es pop ds mov esi,[es:edi+Sections.Name] add esi,[cs:symbol] call showstr pop ds mov esi,info3 call showstr mov edx,[es:edi+Sections.Offset] push cx mov cx,32 call ShowHex pop cx mov esi,info4 call showstr mov edx,[es:edi+Sections.Size] push cx mov cx,32 call ShowHex pop cx mov esi,info5 call showstr mov edx,[es:edi+Sections.Vadress] push cx mov cx,32 call ShowHex pop cx and dword [es:edi+Sections.Flags],SF_ALLOC jne itsok mov esi,info6 call showstr jmp itsok2 itsok: mov esi,info10 call showstr call copy2mem cmp dword [es:edi+Sections.Type],ST_NOBITS jne itsok2 mov esi,info9 call showstr mov esi,info10 call showstr call zero2mem itsok2: push cx xor cx,cx mov edx,[es:edi+Sections.Align] mov esi,info8 call showstr nextpower: cmp edx,0 je powerok cmp edx,1 je powerok cmp cx,32 je powerok inc cx shr edx,1 jnc nextpower powerok: mov edx,ecx mov cx,4 call ShowHex pop cx call showrtn mov esi,edi nothing: add esi,eax dec cx jnz sections mov esi,info7 call showstr mov edx,[cs:entriepoint] mov cx,32 call ShowHex clc pop es popa ret errorelf: stc pop es popa ret ;==========DEBUG=========== ;CX adresse ;->CX ;<- ;========================== debug: mov esi,info11 call showstr xor edx,edx mov dx,cs shl edx,4 add edx,ecx mov cx,32 call ShowHex infini: jmp infini ;==========COPY2MEM=========== ;Copie de es:esi vers es:edi ;->ES:ESI ES:EDI CX ;<- Flag ;============================= copy2mem: push eax push esi push edi push ecx mov esi,[es:edi+Sections.Offset] add esi,[cs:begin] mov ecx,[es:edi+Sections.Size] shr ecx,2 inc ecx mov edi,[es:edi+Sections.Vadress] copietomem: mov eax,[es:esi] mov [es:edi],eax add edi,4 add esi,4 dec ecx jnz copietomem pop ecx pop edi pop esi pop eax ret ;==========ZERO2MEM=========== ;Remise à zero de es:edi ;->ES:EDI CX ;<- Flag ;============================= zero2mem: push eax push esi push edi push ecx mov esi,[es:edi+Sections.Offset] add esi,[cs:begin] mov ecx,[es:edi+Sections.Size] shr ecx,2 inc ecx mov edi,[es:edi+Sections.Vadress] mov eax,0 zerotomem: mov [es:edi],eax add edi,4 dec ecx jnz zerotomem pop ecx pop edi pop esi pop eax ret begin dd 0 entriepoint dd 0 offsetheader dd 0 offsetsection dd 0 nbprogram dw 0 nbsection dw 0 symbol dd 0 ;==========SHOWHEX=========== ;Affiche un nombre hexadécimal EDX de taille CX aprés le curseur ;-> EDX un entier, CX la taille ;<- ;============================ ShowHex: push ax push bx push cx push edx push si 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 mov si,ax mov al,[cs:bx+Tab] xor bx,bx mov ah,0x09 mov bl,[cs:thecolor] int 0x10 mov ah,0x0E int 0x10 mov ax,si dec al jnz Hexaize pop si 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 pour le groupe CX ;-> CX ;<- 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,32 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+32] pop di pop dx pop bx ret ;============SHOWRTN============ ;Affiche la chaine de caractère return ;-> ;<- Flag Carry si erreur ;=============================== showrtn: push ds push ax push esi mov esi,return mov ax,cs mov ds,ax call showstr pop esi pop ax pop ds ret ;==============SHOWSTR============= ;Affiche la chaine de caractère pointé par ds:esi à l'écran ;-> DS, ESI ;<- Flag Carry si erreur ;================================== showstr: pushad xor bh,bh nextchar: mov al,[ds:esi] inc esi or al,al jz endshow cmp al,' ' jb justchar cmp al,'#' jne nocolor mov al,[ds:esi] inc esi sub al,'0' shl al,3 mov [cs:thecolor],al shr al,2 add [cs:thecolor],al mov al,[ds:esi] inc esi sub al,'0' add [cs:thecolor],al jmp nextchar nocolor: cmp al,'@' jne nocolor2 mov al,[ds:esi] inc esi sub al,'0' shl al,3 mov cl,al shr al,2 add cl,al mov al,[ds:esi] inc esi sub cl,'0' add cl,al call eol jmp nextchar nocolor2: xor bx,bx mov ah,0x09 mov bl,[cs:thecolor] xor cx,cx inc cx int 0x10 justchar: mov ah,0x0E int 0x10 jmp nextchar endshow: popad ret ;==========READSECTOR============ ;Lit le secteur logique LBA CX et le met en es:di ;-> CX (limité à 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ède dans la FAT le groupe CX ;-> 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 ;================================= ;CODE 32 bits mode protégé ;================================= GoPMode32: [BITS 32] ;Initialisation des selecteurs 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] ;Execution du système retf section .data thecolor db 0x07 msg0 db '#12@20-=< Lancement du Chargeur ELF >=-',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 format ELF',0 msg8 db '#07Passage en mode protege',0 info1 db 0x0A,0x0D,'Format ELF i386 reconnu, #08Sections :',0x0A,0x0D,0 info2 db ' ',0 info3 db '@12 | ',0 info4 db ' - ',0 info5 db ' -> ',0 info6 db '@35#12NON ALLOUE #08',0 info7 db 'Point entree en ',0 info8 db '@48 2**',0 info9 db '@15#12 VIDE #08',0 info10 db '@70MEM',0 info11 db 0x0A,0x0D,'#12Arret debug en ',0 return db 0x0A,0x0D,0 okay db ' #15[ #10OK #15]',0x0A,0x0D,0 error db ' #15[#12Erreur#15]',0x0A,0x0D,0x0A,0x0D,' ',0 The_Dot db '.',0 System_File db "As",0,"y",0,"s",0,"t",0,"e",0,0x0F,0,0xB8,"m",0,".",0,"s",0,"y",0,"s",0,0,0,0,0,0xFF,0xFF,0xFF,0xFF 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é 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/écriture Sectors_Hidden dd 0 ;Nombre de secteurs caché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 étendu 29h Buffer equ $ Fat_Buffer equ $+512 SECTION .bss %include "elf.h"