Diff markup
001 001
002 /* 002 /*
003 * @(#) $Id: bootsect.S,v 1.5 2004/03/25 09:53 !! 003 * @(#) $Id: bootsect.S,v 1.12 2005/08/13 13:47:31 d2 Exp $
004 * Description : Bootsecteur en syntaxe AT&T 004 * Description : Bootsecteur en syntaxe AT&T
005 * Auteurs : Thomas Petazzoni & Fabrice Gautie 005 * Auteurs : Thomas Petazzoni & Fabrice Gautier & Emmanuel Marty
006 * Jerome Petazzoni & Bernard Cassag 006 * Jerome Petazzoni & Bernard Cassagne & coffeeman
007 * David Decotigny !! 007 * David Decotigny (SOS integration for kernel size detection)
>> 008 * Christopher Goyet (RAM size determination through BIOS int 15H)
008 * Bug reports to kos-misc@enix.org 009 * Bug reports to kos-misc@enix.org
009 */ 010 */
010 011
011 /* 012 /*
012 * But global de ce bootsecteur : 013 * But global de ce bootsecteur :
013 * 014 *
014 * - Initialiser la becane 015 * - Initialiser la becane
015 * - Charger le kernel 016 * - Charger le kernel
016 * - Passer en mode protege 017 * - Passer en mode protege
017 * - Executer le kernel 018 * - Executer le kernel
018 * 019 *
019 * Taille restante : Je vous rappelle qu'un bo 020 * Taille restante : Je vous rappelle qu'un bootsecteur ne peut faire
020 * qu'au maximum 512 octets dont 2 octets obli 021 * qu'au maximum 512 octets dont 2 octets obligatoires 0xAA55. Sur
021 * les 510 octets reellement utilisables, il r 022 * les 510 octets reellement utilisables, il reste 3 octets dispo (60
022 * si on decide d'enlever le BPB un jour) !!! 023 * si on decide d'enlever le BPB un jour) !!!
023 * 024 *
024 * thomas_petazzoni : - detection des codes d 025 * thomas_petazzoni : - detection des codes d'erreurs de chargement
025 * David_Decotigny : - Passage en GNU as 026 * David_Decotigny : - Passage en GNU as
026 * David_Decotigny : - Chargement du noyau a 027 * David_Decotigny : - Chargement du noyau au-dela du 1er Mega (taille
027 * max = 0x9e000 octets 028 * max = 0x9e000 octets = 632ko), pour avoir le
028 * meme noyau sous grub 029 * meme noyau sous grub et avec le bootsecteur
029 */ 030 */
030 031
031 /* 032 /*
032 * Sequence d'operations : 033 * Sequence d'operations :
033 * - Le BIOS charge le bootsect en 0x7c00 (BO 034 * - Le BIOS charge le bootsect en 0x7c00 (BOOT_ADRESS). On choisit
034 * la representation 0x7c0:0000 pour que le 035 * la representation 0x7c0:0000 pour que le .org 0 reste valide
035 * - Le bootsect se deplace de lui-meme en 0x 036 * - Le bootsect se deplace de lui-meme en 0x9f000 (COPY_ADRESS). On
036 * choisit la representation 0x9f00:0000 po 037 * choisit la representation 0x9f00:0000 pour que le .org 0 reste
037 * valide 038 * valide
038 * - Le bootsect verifie que le processeur es 039 * - Le bootsect verifie que le processeur est du type 386+
039 * - Il charge le noyau depuis la disquette e 040 * - Il charge le noyau depuis la disquette en memoire a partir de
040 * 0x1000 (LOAD_ADRESS). Le noyau peut au m !! 041 * 0x1000 (LOAD_ADRESS). La place dispo est donc 0x9f000 - 0x1000 , soit
041 * SECTORS_TO_LOAD secteurs !! 042 * 0x9E000, soit encore 1264 secteurs de 512 octets
042 * - Il passe en pmode flat (apres ouverture 043 * - Il passe en pmode flat (apres ouverture a20)
043 * - Il recopie le noyau (situe en LOAD_ADRES 044 * - Il recopie le noyau (situe en LOAD_ADRESS) vers son adresse
044 * finale (FINAL_ADDRESS = 2Mo). La recopie 045 * finale (FINAL_ADDRESS = 2Mo). La recopie se fait sur tout l'espace
045 * LOAD_ADRESS ---> COPY_ADRESS, c'est a di 046 * LOAD_ADRESS ---> COPY_ADRESS, c'est a dire sur 0x9e000 octets =
046 * 632ko. Le noyau peut donc au max faire 6 047 * 632ko. Le noyau peut donc au max faire 632ko. Le nombre max de
047 * secteurs de disquette qu'on peut charger 048 * secteurs de disquette qu'on peut charger est donc 1264
048 */ 049 */
049 050
050 051
051 /* La taille de la pile */ 052 /* La taille de la pile */
052 #define BOOT_STACK_SIZE 0x4000 053 #define BOOT_STACK_SIZE 0x4000
053 054
054 .file "bootsect.S" 055 .file "bootsect.S"
055 056
056 /* Tout est place dans une seule secti 057 /* Tout est place dans une seule section */
057 .section ".bootsect" 058 .section ".bootsect"
058 059
059 /* L'essentiel du bootsector (sauf les 060 /* L'essentiel du bootsector (sauf les 1eres instructions)
060 sont a un offset 0. On fait en sort 061 sont a un offset 0. On fait en sorte que le compilo soit
061 d'accord la-dessus. Quand on a des 062 d'accord la-dessus. Quand on a des adresse realm exotiques
062 (0x7c00, 0x9f000, ...), on s'arrang 063 (0x7c00, 0x9f000, ...), on s'arrange toujours pour avoir un
063 offset de 0 => on choisira le segme 064 offset de 0 => on choisira le segment adapte (0x7c0,
064 0x9f00, ...). Il ne faut pas oublie 065 0x9f00, ...). Il ne faut pas oublier le ld -Ttext 0 */
065 .org 0 066 .org 0
066 067
067 /* Pour que gas genere du 16bits, afin 068 /* Pour que gas genere du 16bits, afin que ca marche en realm */
068 .code16 069 .code16
069 070
070 #define SECTORS_TO_LOAD 128 /* 64 ko */ /* MAX <<
071 <<
072 /* 071 /*
073 * Parametres de la disquette. Comme c'est chi 072 * Parametres de la disquette. Comme c'est chiant de faire une
074 * procedure de detection auto, et que ca pren 073 * procedure de detection auto, et que ca prend de la place, on fait
075 * ca "a la main". Par exemple, une DD 720 Ko 074 * ca "a la main". Par exemple, une DD 720 Ko a 9 secteurs/piste, une
076 * 1.44 Mo a 18 secteurs/pistes 075 * 1.44 Mo a 18 secteurs/pistes
077 */ 076 */
078 #define CYLS 80 077 #define CYLS 80
079 #define HEADS 1 078 #define HEADS 1
080 #define SECTS 18 079 #define SECTS 18
081 080
082 #define BOOT_ADRESS 0x07C00 /* Adre 081 #define BOOT_ADRESS 0x07C00 /* Adresse de demarrage (lineaire) */
083 #define BOOT_SEG (BOOT_ADRESS>>4) /* Segm 082 #define BOOT_SEG (BOOT_ADRESS>>4) /* Segment de Boot */
084 #define BOOT_SIZE 512 /* Tail 083 #define BOOT_SIZE 512 /* Taille bu bootsecteur */
085 #define COPY_ADRESS 0x9F000 /* La o 084 #define COPY_ADRESS 0x9F000 /* La ou on va copier le
086 boot 085 bootsecteur (lineaire) */
087 #define COPY_SEG (COPY_ADRESS>>4) /* Segm 086 #define COPY_SEG (COPY_ADRESS>>4) /* Segment de la ou on va
088 copi 087 copier le bootsecteur */
089 #define LOAD_ADRESS 0x01000 /* 1er 088 #define LOAD_ADRESS 0x01000 /* 1er chargement du systeme */
090 #define LOAD_SEG (LOAD_ADRESS>>4) /* Segm 089 #define LOAD_SEG (LOAD_ADRESS>>4) /* Segment du 1er chargement du */
091 #define MAX_KERN_LEN COPY_ADRESS-LOAD_ADRESS / !! 090 #define MAX_KERN_LEN (COPY_ADRESS-LOAD_ADRESS) /* Taille noyau maxi */
>> 091 #define MAX_KERN_SECTS ((MAX_KERN_LEN + 511) >> 9) /* Nbre de secteurs maxi */
092 092
093 /* IMPORTANT : Cette valeur DOIT etre identiqu 093 /* IMPORTANT : Cette valeur DOIT etre identique a l'adresse presente
094 dans kos.lds ! */ !! 094 dans sos.lds ! */
095 #define FINAL_ADDRESS 0x200000 /* Adre 095 #define FINAL_ADDRESS 0x200000 /* Adresse finale (physique de 0 a 4G)
096 ou e 096 ou est charge le noyau */
097 097
098 #define OP16 .byte 0x66 ; 098 #define OP16 .byte 0x66 ;
099 #define OP32 .byte 0x66 ; 099 #define OP32 .byte 0x66 ;
100 100
101 /* 101 /*
102 * Procedure qui vide le buffer clavier. 102 * Procedure qui vide le buffer clavier.
103 */ 103 */
104 #define WAITKB \ 104 #define WAITKB \
105 1: ;\ 105 1: ;\
106 .word 0xeb ;\ 106 .word 0xeb ;\
107 .word 0xeb ;\ 107 .word 0xeb ;\
108 inb $0x64, %al ;\ 108 inb $0x64, %al ;\
109 andb $0x2, %al ;\ 109 andb $0x2, %al ;\
110 jnz 1b 110 jnz 1b
111 111
112 /* Le point d'entree dans le bootsect 112 /* Le point d'entree dans le bootsect */
113 .globl _bsect 113 .globl _bsect
114 _bsect: 114 _bsect:
115 115
116 /* 116 /*
117 * La portion qui suit est situee a un 117 * La portion qui suit est situee a un offset 0x7c00 en
118 * memoire. Attention donc aux referen 118 * memoire. Attention donc aux references memoire dans cette
119 * partie. On choisit de rester en off 119 * partie. On choisit de rester en offset 0 (.org 0), mais on
120 * charge correctement les segments a 120 * charge correctement les segments a 0x7c0.
121 */ 121 */
122 122
123 movw $BOOT_SEG, %ax /* le bootsecteur 123 movw $BOOT_SEG, %ax /* le bootsecteur est a 0x7C00 en lineaire */
124 movw %ax, %ds /* on le copie a l' 124 movw %ax, %ds /* on le copie a l'adresse COPY_ADRESS */
125 xorw %si, %si /* comme cette adre 125 xorw %si, %si /* comme cette adresse est la plus haute de la mem */
126 xorw %di, %di /* on pourra charge 126 xorw %di, %di /* on pourra charger un kernel + gros */
127 movw $(BOOT_SIZE>>1), %cx 127 movw $(BOOT_SIZE>>1), %cx
128 movw $COPY_SEG, %ax 128 movw $COPY_SEG, %ax
129 movw %ax, %es 129 movw %ax, %es
130 cld 130 cld
131 rep ; movsw 131 rep ; movsw
132 132
133 /* on continue a executer le bootsecte 133 /* on continue a executer le bootsecteur, mais maintenant a
134 partir de 0x9F000, qu'on represente 134 partir de 0x9F000, qu'on represente sous la forme
135 0x9f00:offset */ 135 0x9f00:offset */
136 ljmp $COPY_SEG, $here 136 ljmp $COPY_SEG, $here
137 137
138 /* 138 /*
139 * A partir de maintenant, on est a un 139 * A partir de maintenant, on est a un offset 0 en memoire
140 * (segment 0x9f00), conformement a ce 140 * (segment 0x9f00), conformement a ce que veut le compilo.
141 */ 141 */
142 here: 142 here:
143 movw %ax, %ds 143 movw %ax, %ds
144 144
145 /* Petite pile temporaire (1k - 3.84k 145 /* Petite pile temporaire (1k - 3.84k en RAM ; les adresses 0-1k
146 correspondent au vecteur d'interrup 146 correspondent au vecteur d'interruptions). */
147 movw %ax, %ss 147 movw %ax, %ss
148 movw $(LOAD_ADRESS - 0x10), %sp 148 movw $(LOAD_ADRESS - 0x10), %sp
149 149
150 /* Efface l'ecran */ 150 /* Efface l'ecran */
151 movb $0x0, %ah 151 movb $0x0, %ah
152 movb $0x3, %al 152 movb $0x3, %al
153 int $0x10 !! 153 int $0x10
>> 154
>> 155 /* Verifie que le noyau n'est pas trop gros a charger */
>> 156 cmpw $(MAX_KERN_SECTS), (load_size)
>> 157 jb sizeOk
>> 158 movw $toobig, %si
>> 159 call message
>> 160 call halt
>> 161
>> 162 sizeOk:
>> 163 /* Recupere la taille de la RAM */
>> 164 mov $0xE801, %ax
>> 165 int $0x15
>> 166 movw %ax, (memsize1)
>> 167 movw %bx, (memsize2)
154 168
155 /* Affiche les messages d'attente */ 169 /* Affiche les messages d'attente */
156 movw $loadkern, %si 170 movw $loadkern, %si
157 call message 171 call message
158 movw $check, %si 172 movw $check, %si
159 call message 173 call message
160 174
161 check386: 175 check386:
162 /* 176 /*
163 * la attention, plus complexe : on te 177 * la attention, plus complexe : on teste si le proc est un
164 * 386+ pour cela, on va essayer de mo 178 * 386+ pour cela, on va essayer de modifier les bits 12 ? 14
165 * du registre E-flag si la modificati 179 * du registre E-flag si la modification reste, alors le proc
166 * est un 386+, sinon, c'est =< 286 180 * est un 386+, sinon, c'est =< 286
167 * 181 *
168 * Merci a Emmanuel Marty pour la comp 182 * Merci a Emmanuel Marty pour la compatibilite avec les 386
169 * "pre-jurassique" 183 * "pre-jurassique"
170 */ 184 */
171 185
172 pushf /* on sauvegarde le E-Flag */ 186 pushf /* on sauvegarde le E-Flag */
173 movb $0x70, %ah 187 movb $0x70, %ah
174 pushw %ax 188 pushw %ax
175 popf 189 popf
176 pushf 190 pushf
177 popw %ax 191 popw %ax
178 orb %ah, %ah 192 orb %ah, %ah
179 je no386 /* si la modif n'est pas val 193 je no386 /* si la modif n'est pas valable, alors on saute a
180 no386 */ 194 no386 */
181 popf /* on les restaure ? la fin 195 popf /* on les restaure ? la fin ... */
182 196
183 /* Message de confirmation de 386+ et 197 /* Message de confirmation de 386+ et d'attente */
184 movw $found386, %si 198 movw $found386, %si
185 call message 199 call message
186 movw $loading, %si 200 movw $loading, %si
187 call message 201 call message
188 202
189 /* Copie du noyau disquette => RAM a partir de 203 /* Copie du noyau disquette => RAM a partir de 0x1000
190 L'adresse de destination est définie par es 204 L'adresse de destination est définie par es:0, où es vaut
191 initialement 0x100 (ie correspond alors à l 205 initialement 0x100 (ie correspond alors à l'adresse 256*16, soit 4
192 ko). Chaque itération incrémente ce registr 206 ko). Chaque itération incrémente ce registre es de 32, ce qui
193 correspond à un bond de 32*16 en mémoire, s 207 correspond à un bond de 32*16 en mémoire, soit la taille d'un
194 secteur. De cette façon, puisqu'on joue sur 208 secteur. De cette façon, puisqu'on joue sur les segments plutôt que
195 sur les offsets, la taille du noyau n'est p 209 sur les offsets, la taille du noyau n'est pas limitée à 64 ko. Elle
196 est limitée par contre à la taille de la mé 210 est limitée par contre à la taille de la mémoire disponible sous
197 les 1Mo, \ie 640 ko (0x9f000 - 0x1000). */ 211 les 1Mo, \ie 640 ko (0x9f000 - 0x1000). */
198 copyKernel: 212 copyKernel:
199 /* Chargement du noyau en LOAD_SEG:0 * 213 /* Chargement du noyau en LOAD_SEG:0 */
200 /* 3 iterateurs : 214 /* 3 iterateurs :
201 - load_size : le nbre de secte 215 - load_size : le nbre de secteurs a charger
202 - cl : le secteur ou on en est 216 - cl : le secteur ou on en est pour le
203 cylindre en cours (<= SECTS) 217 cylindre en cours (<= SECTS)
204 - dh : la tete en cours (0/1) 218 - dh : la tete en cours (0/1)
205 */ 219 */
206 movb $0, %dl 220 movb $0, %dl
207 movw $LOAD_SEG, %ax 221 movw $LOAD_SEG, %ax
208 movw %ax, %es 222 movw %ax, %es
209 223
210 xorw %bx, %bx 224 xorw %bx, %bx
211 xorw %dx, %dx 225 xorw %dx, %dx
212 movw $1, %cx /* premier secteur * 226 movw $1, %cx /* premier secteur */
213 227
214 .nextsector: /* prochain secteur * 228 .nextsector: /* prochain secteur */
215 incb %cl /* en incrementant CL 229 incb %cl /* en incrementant CL */
216 cmpb $SECTS, %cl /* si CL =< SECTS (=n 230 cmpb $SECTS, %cl /* si CL =< SECTS (=nbre de secteurs/pistes)
217 alors on charge */ 231 alors on charge */
218 jbe .sector 232 jbe .sector
219 movb $1, %cl /* sinon on revient a 233 movb $1, %cl /* sinon on revient au secteur 1 */
220 incb %dh /* mais sur l'autre t 234 incb %dh /* mais sur l'autre tete */
221 cmpb $1, %dh /* on recompare, si D 235 cmpb $1, %dh /* on recompare, si DH =< 1 */
222 je .sector /* on charge */ 236 je .sector /* on charge */
223 movb $0, %dh /* sinon on repasse a 237 movb $0, %dh /* sinon on repasse a la tete 0 */
224 incb %ch /* mais on change de 238 incb %ch /* mais on change de cylindre */
225 239
226 .sector: 240 .sector:
227 pushw %es 241 pushw %es
228 movw $0x0201, %ax /* service 0x2, char 242 movw $0x0201, %ax /* service 0x2, chargement 0x1 seecteur */
229 int $0x13 /* Go ! */ 243 int $0x13 /* Go ! */
230 jc halt /* erreur */ 244 jc halt /* erreur */
231 popw %ax 245 popw %ax
232 addw $32, %ax /* on a charge un se 246 addw $32, %ax /* on a charge un secteur, donc on doit
233 charger 512 bytes 247 charger 512 bytes plus loin */
234 movw %ax, %es /* on avance donc le 248 movw %ax, %es /* on avance donc le segment du buffer de
235 32bytes, ie 1 sec 249 32bytes, ie 1 secteur en RAM (car 32*16=512) */
236 250
237 movw $(0x0E*256+'.'), %ax /* affiche u 251 movw $(0x0E*256+'.'), %ax /* affiche un point */
238 int $0x10 252 int $0x10
239 253
240 decw (load_size) /* et on repart p 254 decw (load_size) /* et on repart pour le prochain secteur
241 tant qu'on n'a pa 255 tant qu'on n'a pas fini ! */
242 jnz .nextsector 256 jnz .nextsector
243 257
244 after: 258 after:
245 movw $0x03f2, %dx 259 movw $0x03f2, %dx
246 inb %dx, %al /* stoppe le moteur */ 260 inb %dx, %al /* stoppe le moteur */
247 andb $0x0f, %al 261 andb $0x0f, %al
248 outb %al, %dx 262 outb %al, %dx
249 263
250 cli /* on interdit les i 264 cli /* on interdit les interruptions */
251 265
252 fincopie: 266 fincopie:
253 pushw %cs 267 pushw %cs
254 popw %ds 268 popw %ds
255 269
256 /* on ouvre la porte A20 */ 270 /* on ouvre la porte A20 */
257 WAITKB /* on vide le buffer 271 WAITKB /* on vide le buffer */
258 movb $0xd1, %al /* on met a jour le po 272 movb $0xd1, %al /* on met a jour le port */
259 outb %al, $0x64 273 outb %al, $0x64
260 WAITKB 274 WAITKB
261 movb $0xdf, %al /* bit 2 = ouverture/f 275 movb $0xdf, %al /* bit 2 = ouverture/fermeture */
262 outb %al, $0x60 276 outb %al, $0x60
263 277
264 /* 278 /*
265 * init gdt 279 * init gdt
266 */ 280 */
267 InitGDT: 281 InitGDT:
268 /* Préparation du flat mode */ 282 /* Préparation du flat mode */
269 lgdt gdtr 283 lgdt gdtr
270 284
271 GoPMode: 285 GoPMode:
272 /* Passage en mode protégé */ 286 /* Passage en mode protégé */
273 movl %cr0, %eax 287 movl %cr0, %eax
274 orb $1, %al /* set PE bit to 1 */ 288 orb $1, %al /* set PE bit to 1 */
275 movl %eax, %cr0 289 movl %eax, %cr0
276 290
277 /* we are not yet in Pmode jump 'in' p 291 /* we are not yet in Pmode jump 'in' pmode clearing prefetch
278 * queue and loading a new selector */ 292 * queue and loading a new selector */
279 movw $0x10, %ax 293 movw $0x10, %ax
280 movw %ax, %ds 294 movw %ax, %ds
281 movw %ax, %es 295 movw %ax, %es
282 movw %ax, %fs 296 movw %ax, %fs
283 movw %ax, %gs 297 movw %ax, %gs
284 298
285 /* 299 /*
286 * Code 32 bits ============================== 300 * Code 32 bits ============================================================
287 */ 301 */
288 .code32 302 .code32
289 303
290 JumpToHere32: /* Se deplace a l'endroit actuel 304 JumpToHere32: /* Se deplace a l'endroit actuel, en passant en 32bits
291 et en utilisant la gdt, et vi 305 et en utilisant la gdt, et vide la prefetch queue */
292 .byte 0x66 /* Prefixe 32bits : en real 306 .byte 0x66 /* Prefixe 32bits : en realite, jusqu'au jmp, on est
293 encore en 16 bits */ 307 encore en 16 bits */
294 ljmp $0x8, $(COPY_ADRESS+(Here32)) 308 ljmp $0x8, $(COPY_ADRESS+(Here32))
295 Here32: 309 Here32:
296 /* Et voila : On est en 32 bits vrai * 310 /* Et voila : On est en 32 bits vrai */
297 311
298 MoveKernelToFinalAddr: /* Deplace le noyau (en 312 MoveKernelToFinalAddr: /* Deplace le noyau (en LOAD_ADDRESS) vers sa
299 destination finale ( 313 destination finale (FINAL_ADDRESS) */
300 movl $0x10, %eax 314 movl $0x10, %eax
301 movl %eax, %ds /* Seg Src = DSeg */ 315 movl %eax, %ds /* Seg Src = DSeg */
302 movl %eax, %es /* Sed Dest = DSeg */ 316 movl %eax, %es /* Sed Dest = DSeg */
303 cld 317 cld
304 movl $LOAD_ADRESS, %esi /* On comme 318 movl $LOAD_ADRESS, %esi /* On commence la copie au debut du noyau */
305 movl $FINAL_ADDRESS, %edi /* On copie 319 movl $FINAL_ADDRESS, %edi /* On copie vers cette adresse */
306 movl $MAX_KERN_LEN, %ecx /* Taille r 320 movl $MAX_KERN_LEN, %ecx /* Taille recopie */
307 shrl $2, %ecx 321 shrl $2, %ecx
308 rep 322 rep
309 movsl 323 movsl
310 324
311 LaunchKernel: 325 LaunchKernel:
312 /* Met en place une pile au niveau du 326 /* Met en place une pile au niveau du symbole "stack" */
313 movl %eax, %ss 327 movl %eax, %ss
314 movl $(stack + BOOT_STACK_SIZE), %ebp 328 movl $(stack + BOOT_STACK_SIZE), %ebp
315 movl %ebp, %esp 329 movl %ebp, %esp
>> 330
>> 331 /* passe les arguments a sos */
>> 332 xor %eax, %eax
>> 333 xor %ebx, %ebx
>> 334 movw (COPY_ADRESS+(memsize2)), %ax /*eax = num de block de 64KB apres 16MB*/
>> 335 movw (COPY_ADRESS+(memsize1)), %bx /*ebx = num de block de 1KB entre 1MB et 16MB*/
>> 336 movl $0x40, %ecx /*ecx=64 */
>> 337 mul %ecx
>> 338 add %ebx, %eax
>> 339 pushl %eax /* valeur de addr */
>> 340 pushl $0x42244224 /* valeur de magic pour indiquer qu'on a pousse
>> 341 la taille de la RAM sur la pile */
>> 342 pushl $0 /* normalement call fait un push eip, mais la on a un jmp*/
316 343
317 /* Saut vers le noyau. La GDT est en p 344 /* Saut vers le noyau. La GDT est en place (flat mode), les
318 * selecteurs aussi, a20 est ouverte, 345 * selecteurs aussi, a20 est ouverte, et les interruptions sont
319 * cli + pas de idt. Le PIC n'est pas 346 * cli + pas de idt. Le PIC n'est pas programme */
320 ljmp $0x8, $sos_main 347 ljmp $0x8, $sos_main
321 348
322 /* 349 /*
323 * Utilities ================================= 350 * Utilities ============================================================
324 */ 351 */
325 .code16 352 .code16
326 353
327 message: 354 message:
328 lodsb /* charge ds:si dans 355 lodsb /* charge ds:si dans al et incremente si */
329 orb %al, %al /* si al = 0 */ 356 orb %al, %al /* si al = 0 */
330 jz 1f 357 jz 1f
331 movb $0x0e, %ah /* service 0Eh (affi 358 movb $0x0e, %ah /* service 0Eh (affichage d'un caractere) */
332 movw $0x0007, %bx /* Parametres : blan 359 movw $0x0007, %bx /* Parametres : blanc sur fond noir */
333 int $0x10 /* Appel de l'inter 360 int $0x10 /* Appel de l'interruption 10h */
334 jmp message /* On repart au débu 361 jmp message /* On repart au début ... */
335 1: ret /* si la chaine est 362 1: ret /* si la chaine est finie alors on retourne
336 dans la fonction 363 dans la fonction appelante */
337 364
338 halt: 365 halt:
339 pushw %cs 366 pushw %cs
340 popw %es 367 popw %es
341 movw $haltmsg, %si 368 movw $haltmsg, %si
342 call message 369 call message
343 cli 370 cli
344 1: jmp 1b 371 1: jmp 1b
345 ret 372 ret
346 373
347 no386: 374 no386:
348 movw $need386, %si 375 movw $need386, %si
349 call message 376 call message
350 call halt 377 call halt
351 378
352 /* 379 /*
353 * GDT 380 * GDT
354 */ 381 */
355 382
356 gdt: 383 gdt:
357 gdtr: 384 gdtr:
358 NULL_Desc: 385 NULL_Desc:
359 .word (EndGDT)-(gdt)-1 /* Taille GDT * 386 .word (EndGDT)-(gdt)-1 /* Taille GDT */
360 .long (gdt)+COPY_ADRESS 387 .long (gdt)+COPY_ADRESS
361 unused: 388 unused:
362 .word 0 389 .word 0
363 390
364 CS_Desc: /* 0x8 */ 391 CS_Desc: /* 0x8 */
365 .word 0xFFFF, 0 392 .word 0xFFFF, 0
366 .byte 0, 0x9B, 0xCF, 0 393 .byte 0, 0x9B, 0xCF, 0
367 394
368 DS_Desc: /* 0x10 */ 395 DS_Desc: /* 0x10 */
369 .word 0xFFFF, 0 396 .word 0xFFFF, 0
370 .byte 0, 0x93, 0xCF, 0 397 .byte 0, 0x93, 0xCF, 0
371 398
372 EndGDT: 399 EndGDT:
373 400
374 /* quelques messages */ 401 /* quelques messages */
375 402
376 loadkern: .string "-= S O S =- : The Sim !! 403 loadkern: .string "This is SOS\r\n"
377 check: .string "Checking for a 386+ p !! 404 toobig: .string "Image too big\r\n"
>> 405 check: .string "Checking 386+ processor... "
378 found386: .string " [OK]\r\n" 406 found386: .string " [OK]\r\n"
379 need386: .string " [FAILED]\r\n" 407 need386: .string " [FAILED]\r\n"
380 diskerror: .string "Disk Error\r\n" 408 diskerror: .string "Disk Error\r\n"
381 loading: .string "Loading... " 409 loading: .string "Loading... "
382 haltmsg: .string "System Halted\r\n" 410 haltmsg: .string "System Halted\r\n"
383 411
>> 412 /* Variables pour stocker la taille de la RAM (int 0x15) */
>> 413 memsize1: .long 0
>> 414 memsize2: .long 0
>> 415
384 /*** Les code/données du boot secteur se termi 416 /*** Les code/données du boot secteur se terminent ICI. le marqueur de
385 * fin (aa55) est ajouté automatiquement par l 417 * fin (aa55) est ajouté automatiquement par le script ld
386 * sos_bsect.lds ***/ 418 * sos_bsect.lds ***/
387 419
388 /* La pile de 16k qu'on utilise au niveau de L 420 /* La pile de 16k qu'on utilise au niveau de LaunchKernel se trouve
389 declaree avec le noyau, dans sa section ".b !! 421 declaree avec le noyau, dans sa section ".init_stack", cad HORS du boot
390 secteur ! (sinon ca depasserait 512B, forcé 422 secteur ! (sinon ca depasserait 512B, forcément). On aurait pu la
391 définir directement dans le sos_bsect.lds, 423 définir directement dans le sos_bsect.lds, ou dans un fichier .c
392 auxiliaire pour plus de clarté */ 424 auxiliaire pour plus de clarté */
393 .comm stack, BOOT_STACK_SIZE !! 425 /* Here is the stack */
>> 426 .section ".init_stack", "aw", @nobits
>> 427 .p2align 4
>> 428 .size stack, BOOT_STACK_SIZE
>> 429 stack:
>> 430 .space BOOT_STACK_SIZE
>> 431
>> 432 /* Some data characterizing the stack addresses */
>> 433 .data
>> 434 .globl bootstrap_stack_bottom
>> 435 bootstrap_stack_bottom: .long stack
>> 436
>> 437 .globl bootstrap_stack_size
>> 438 bootstrap_stack_size: .long BOOT_STACK_SIZE