; Copyright (C) 2008 Emmanuel Varoquaux ; ; This file is part of XOS. ; ; This program is free software: you can redistribute it and/or modify ; it under the terms of the GNU General Public License as published by ; the Free Software Foundation, either version 3 of the License, or ; (at your option) any later version. ; ; This program is distributed in the hope that it will be useful, ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; GNU General Public License for more details. ; ; You should have received a copy of the GNU General Public License ; along with this program. If not, see <http://www.gnu.org/licenses/>. ; Secteur de boot ; ; boot.bin est charge a l'adresse 0x7c00 par le BIOS. Le registre dl contient ; l'identifiant du lecteur de boot (le lecteur de disquette). ; ; Il charge un bloc de code 8086 supplementaire (setup), puis le systeme a ; l'adresse 0x10000 en utilisant les interruptions du BIOS. Il passe ensuite la ; main a setup. %define SYS_SEG 0x1000 ; segment de chargement du systeme %define SECTORS 18 ; nombre de secteurs par piste (disquette ; 1.44Mb) bits 16 org 0x0 jmp short start nop times 0x3e-$+$$ db 0 start: ; Initialisation des segments mov ax,0x07c0 mov ds,ax mov es,ax mov ss,ax ; Initialisation de la pile mov sp,0x4000 ; arbitraire, suffisamment grand pour ne pas ; risquer d'ecraser le code, mais inferieur a ; (0x10000-0x7c00) ; Ecriture d'un message mov bl,0x7 ; attribut mov cx,msg_len ; longueur mov bp,msg ; adresse call write_str ; ecriture call reset_drive ; Chargement de setup xor ax,ax ; es doit etre aligne sur 64Ko mov es,ax ; segment de destination mov cx,3 ; 3 essais try_load_setup: push cx mov ax,0x0200+SETUP_SECS ; service 02, nombre de secteurs mov cx,0x0002 ; piste 0, secteur 2 xor dh,dh ; tete 0 mov bx,0x7e00 ; offset de destination int 0x13 ; lecture des secteurs jnc ok_load_setup ; succes pop cx dec cx jz error_load_setup ; erreur call reset_drive jmp try_load_setup ; nouvel essai error_load_setup: jmp error ok_load_setup: add sp,2 ; Chargement du systeme ; On charge par pistes entieres load_system: mov ax,SYS_SECS shl ax,5 ; nombre de blocs de 16o a charger add ax,SYS_SEG ; premier segment libre cmp ax,0xa000 jb load_system_1 jmp error load_system_1: mov bx,SYS_SEG mov ax,SYS_SEG test ax,0x0fff ; es doit etre aligne sur 64Ko jnz error mov es,ax ; segment de destination xor bx,bx ; offset de destination read_loop: mov ax,es sub ax,SYS_SEG cmp ax,SYS_SECS<<5 ; a-t-on termine ? jnb ok_load_system ; oui mov ax,SECTORS sub ax,[sread] ; al = nombre de secteurs a lire dans la piste mov cx,ax shl cx,9 add cx,bx ; le tampon traverse une frontiere de 64Ko ? jnc read_loop_1 ; non je read_loop_1 ; non xor ax,ax ; oui: on reajuste al sub ax,bx shr ax,9 read_loop_1: call read_track ; lecture de al secteurs dans la piste courante jc error ; erreur mov cx,ax ; nombre de secteurs lus add ax,[sread] cmp ax,SECTORS jne read_loop_3 mov ax,1 ; face finie sub ax,[head] ; on change de tete jne read_loop_2 inc word [track] ; on change de piste read_loop_2: mov [head],ax xor ax,ax read_loop_3: mov [sread],ax shl cx,9 add bx,cx ; mise a jour de l'offset de destination jnc read_loop mov ax,es add ax,0x1000 mov es,ax xor bx,bx ; mise a jour de l'offset de destination jmp read_loop ok_load_system: call kill_motor ; arret du moteur mov bl,0x7 ; attribut mov cx,nl_len ; longueur mov ax,0x07c0 mov es,ax mov bp,nl ; adresse call write_str ; ecriture d'un passage a la ligne mov ax,SYS_SECS ; nombre de secteurs systeme charges jmp setup ; transfert de l'execution a setup ; Gestionnaire des erreurs de chargement du systeme. error: mov bl,0x7 ; attribut mov cx,error_msg_len ; longueur mov ax,0x07c0 mov es,ax mov bp,error_msg ; adresse call write_str ; ecriture d'un message d'erreur die: jmp die ; Ecrit une chaine de caracteres a la position du curseur. ; bl: attribut des caracteres ; cx: longueur de la chaine ; es:bp: adresse de la chaine write_str: push ax push bx push dx push cx mov ah,0x03 ; service 03 xor bh,bh ; page 0 int 0x10 ; lecture de la position du curseur mov ax,0x1301 ; service 13, mode 1 pop cx ; longueur de la chaine int 0x10 ; ecriture de la chaine pop dx pop bx pop ax ret ; Reinitialise le controleur de disquette. ; dl: lecteur reset_drive: push ax xor ah,ah ; service 00 int 0x13 ; reinitialisation du controleur jc error ; erreur pop ax ret ; Lit des secteurs sur la piste courante. ; al: nombre de secteurs a lire ; dl: lecteur ; es:bx: adresse du tampon de destination ; retour: ; ah: status ; al: nombre de secteurs lus ; cf: 0 en cas de succes, 1 en cas d'erreur read_track: push cx push dx mov cx,3 ; 3 essais try_read_track: push cx mov ah,0x02 ; service 02 mov ch,[track] ; piste mov cl,[sread] inc cl ; secteur mov dh,[head] ; tete int 0x13 ; lecture des secteurs jnc ok_read_track ; succes pop cx dec cx jz error_read_track ; erreur call reset_drive jmp try_read_track ; nouvel essai error_read_track: pop dx pop cx stc ret ok_read_track: add sp,2 pop dx pop cx ret ; Arrete le moteur du lecteur de disquette. kill_motor: push ax push dx xor al,al mov dx,0x3f2 out dx,al mov dx,0x372 out dx,al pop dx pop ax ret ; Messages msg db "Loading the kernel..." msg_len equ $-msg nl db 13,10 nl_len equ $-nl error_msg db " Failed to load the kernel.",13,10 error_msg_len equ $-error_msg ; Variables head dw 0 ; tete courante track dw 0 ; piste courante sread dw 1+SETUP_SECS ; nombre de secteurs lus dans la piste courante times 510-$+$$ db 0 ; Boot flag dw 0xaa55 setup: