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