View of xos/boot/boot.asm


XOS | Parent Directory | View | Download

; 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: