wok view ipxe/stuff/bootloader.S @ rev 20179

ipxe: update bootloader
author Pascal Bellard <pascal.bellard@slitaz.org>
date Sat Jan 27 12:56:10 2018 +0100 (2018-01-27)
parents
children 1421f93cc28a
line source
1 // Image/zImage & tiny bzImage linux kernel boot sector, (C) SliTaz, GPL2.
3 SYSSEG = 0x1000
4 INITSEG = 0x9000
5 SETUPSEG = 0x9020
6 setup_sects = 497
7 syssize = 500
8 cmd_line_ptr = 0x228
10 .text
11 .code16
12 .org 0
13 .globl _start
14 _start:
16 #define CODESZ 512 /* patched by installer */
18 #define BZIMAGE 0x207 /* setup version ; for bzImage < 512 Kb only */
20 /* some extra features */
21 #define EXE_SUPPORT real mode dos .exe file support
22 #define CMDLINE kernel cmdline support
23 #define VCPI VCPI 4.0 support
24 #define SHUTDOWNDOS shutdown DOS services
26 /* some contraints to reduce the code size */
27 //#define FLOPPY_1440K_ONLY 1.44M floppies support only -33
28 //#define FLOPPY_HAS_2_SIDES hardcoded heads count to 2 -13
29 //#define NO_CMDLINE_SHRINK remove heading spaces ? -6-20
30 //#define NO_CMDLINE_FILE remove @cmdline file support ? -20
31 #define NO_DOTS show progression dots ? -8
32 #ifndef BZIMAGE
33 //#defime NO_MINSETUP default setup (dos only) ? -4
34 //#define NO_CURSOR_DEFINITION -8
35 #endif
37 #ifdef EXE_SUPPORT
38 #define EXEADRS(x) (x+0xE0)
39 #define FLAT20(x) (x+16*INITSEG)
41 .macro trace_int19
42 pushl $4
43 popw %si
44 popw %ds
45 pushl (%si)
46 movl $step19+(INITSEG<<16), (%si)
47 pushfw
48 popw %ax
49 incb %ah # set TF
50 pushw %ax
51 popfw
52 ljmp *4*0x19-4(%si)
53 .endm
55 stacktop = 0x9E00 # in 0x8000 .. 0xA000
56 decw %bp // Magic number: MZ
57 popw %dx
58 jmp start // Bytes on last page of file
59 .word (CODESZ+511)/512 // Pages in file INSTALLER
60 .word 0 // Relocations
61 .word (end_header-_start)/16 // Size of header in paragraphs
62 .word 4096 // Minimum extra paragraphs needed
63 .word -1 // Maximum extra paragraphs needed
64 .word (CODESZ+15)/16 // Initial (relative) SS value INSTALLER
65 .word stacktop // Initial SP value
66 .word 0 // Checksum INSTALLER?
67 .word EXEADRS(comstart) // Initial IP value
68 .word 0xFFF0 // Initial (relative) CS value
69 // .word 0x001C // File address of relocation table
70 // .word 0,0,0 // Overlay number
71 #endif
72 start:
73 xorw %ax, %ax # %ax = 0
74 #ifdef BZIMAGE
75 zeroed = 14 # zeroed registers
76 #else
77 zeroed = 12 # zeroed registers
78 #endif
79 movw $zeroed/2, %cx # clear gdt + offset, %ds, limits
80 stacktop = 0x9E00 # in 0x8000 .. 0xA000 (+zeroed+12)
81 pushw $INITSEG
82 end_header:
83 cld # assume nothing
84 #if defined(BZIMAGE) && BZIMAGE >= 0x202
85 popw %es # %es contain INITSEG
86 movw %es, %di
87 #else
88 # cmdline offset at 0x22
89 movw $stacktop, %di # stacktop is an arbitrary value >=
90 # length of bootsect + length of
91 # setup + room for stack;
92 # 12 is disk parm size.
93 popw %es # %es contain INITSEG
94 #endif
95 pushw %es
96 popw %ss # %es = %ss = INITSEG
97 movw %di, %sp # put stack at INITSEG:stacktop-...
98 #ifdef EXE_SUPPORT
99 cwd # force %dx = 0 (floppy only)
100 #endif
102 # Many BIOS's default disk parameter tables will not recognize
103 # multi-sector reads beyond the maximum sector number specified
104 # in the default diskette parameter tables - this may mean 7
105 # sectors in some cases.
106 #
107 # Since single sector reads are slow and out of the question,
108 # we must take care of this by creating new parameter tables
109 # (for the first disk) in RAM. We can set the maximum sector
110 # count to 36 - the most we will encounter on an ED 2.88.
111 #
112 # High doesn't hurt. Low does. Let's use the max: 63
114 rep # don't worry about cld
115 stosw # already done above
116 popw %bx # offset = 0
117 popw %ds # %ds = 0
118 popw %fs # %fs = 0
120 movb setup_sects+0x7C00, %al # read bootsector + setup (%ds = 0)
121 incw %ax
123 ldsw 0x78(%bx), %si # %ds:%bx+0x78 is parameter table address
124 pushw %es
125 pushw %di
126 movb $6, %cl # copy 12 bytes
127 rep # don't worry about cld
128 movsw # already done above
129 pushw %ss
130 popw %ds # now %ds = %es = %ss = INITSEG
131 popl %fs:0x78(%bx) # update parameter table address
132 movb $63, 0x4-12(%di) # patch sector count, %di = stacktop
133 cli
135 xchg %ax, %di # sector count
136 popw %ax # limits = 0
137 incw %cx # cylinder 0, sector 1, clear Z
138 call read_first_sectors # read setup
140 # This routine loads the system at address LOADSEG, making sure
141 # no 64kB boundaries are crossed. We try to load it as fast as
142 # possible, loading whole tracks whenever we can.
144 #ifndef NO_DOTS
145 popw %bx # clear %bx
146 #endif
147 movw syssize, %di
148 decw %di
149 shrw $9-4, %di
150 incw %di
151 movw $SYSSEG, %cx
152 #ifdef BZIMAGE
153 push %cx
154 #endif
155 call read_sectorsCX
157 # This procedure turns off the floppy drive motor, so
158 # that we enter the kernel in a known state, and
159 # don't have to worry about it later.
161 kill_motor:
162 xchgw %ax, %di # reset FDC (%di < 128)
163 int $0x13
165 # After that (everything loaded), we jump to the setup-routine
166 # loaded directly after the bootblock:
167 # Segments are as follows: %ds = %ss = INITSEG
169 #ifdef BZIMAGE
170 popw %bx
171 popw %si // SYSSEG:0
172 movesys: // %bx = DS, %si
173 movw $16, %ax
174 mulw %bx
175 addw %si, %ax
176 adcw $0x9300, %dx // %dx:%ax src flat address
177 movw $9, %cx
178 zero1:
179 pushw $0 // 2E..1E
180 loop zero1
181 //pushl $0x93100000 // 1A: dest
182 pushw $0x9310
183 pushw %cx
184 pushw $-1 // 18
185 pushw %cx // 16
186 pushw %dx // src
187 pushw %ax
188 pushw $-1 // 10
189 movb $8, %cl
190 movw %cx, %bx // will move 8*64 = 512Kb
191 zero2:
192 pushw $0 // 0E..00
193 loop zero2
194 movw %sp, %si
195 pushw %ss
196 popw %es
197 pushw %es
198 popw %ds
199 syslp:
200 movb $0x80, %ch
201 movb $0x87, %ah
202 int $0x15
203 incb 0x14(%si)
204 incb 0x1C(%si)
205 decw %bx
206 jne syslp
207 #endif
208 jmp_setup:
209 ljmp $SETUPSEG, $0
211 #ifdef EXE_SUPPORT
212 #ifdef SHUTDOWNDOS
213 doiret:
214 iret
215 step19:
216 pushw %si
217 pushw %ds
218 movw %sp, %si
219 ldsw %ss:4(%si), %si
220 cmpw $0x19CD, (%si)
221 popw %ds
222 popw %si
223 jne doiret
224 xorw %si, %si
225 movw %si, %ds
226 pushw %cs
227 popw %ss
228 movw $stacktop-4-16, %sp
229 popl 4(%si)
230 popaw
231 #ifdef BZIMAGE
232 jmp movesys
233 #endif
234 #endif
235 #ifndef BZIMAGE
236 movesys: // %ax = SYSSEG, %bx = DS, %si
237 shrw $4, %si
238 addw %si, %bx
239 subw %ax, %bx
240 jnc forward
241 movb $0x90, %ah
242 ;decw %ax
243 forward:
244 movw %ax, %es
245 movw %ax, %di
246 addw %bx, %di
247 movw %di, %ds
248 sbbw %di, %di // %di = 0 : -1
249 cmc // C = 1 : 0
250 adcw %di, %ax
251 xorw %si, %si
252 xorw %di, %di
253 movb $0x10, %cl
254 cmpb %cl, %ah // move 512k
255 rep
256 movsb
257 jns forward
258 #ifndef NO_CURSOR_DEFINITION
259 movb $1, %ah
260 movb $0, %bh
261 movb $0x20, %ch // 0x2000
262 int $0x10
263 #endif
264 pushw %ss
265 popw %ds
266 jmp jmp_setup
267 #endif
268 comstart:
269 cld # assume nothing
270 pushw $INITSEG
271 popw %es
272 #ifdef CMDLINE
273 movw %sp, %di
274 movw $0x80, %si
275 lodsb
276 cbw
277 xchgw %ax, %cx
278 jcxz nocmdline
279 # if defined(BZIMAGE) && BZIMAGE >= 0x202
280 movw $INITSEG/16+stacktop/256, EXEADRS(cmd_line_ptr+1)
281 # else
282 movw $0xA33F, 0x7F(%si)
283 # endif
284 # ifndef NO_CMDLINE_SHRINK
285 skipspace:
286 lodsb
287 cmpb $0x20, %al
288 je skipspace
289 # ifndef NO_CMDLINE_FILE
290 movw %si,%dx
291 decw %si
292 subb $'@',%al
293 jne notafile
294 movb $0x3D,%ah
295 int $0x21
296 jc notafile
297 xchgw %ax,%bx
298 //movw %si,%dx // ~320 bytes max
299 movw $EXEADRS(notafile)-130,%cx
300 movb $0x3F,%ah
301 int $0x21
302 xchgw %ax,%cx
303 notafile:
304 # else
305 decw %si
306 # endif
307 # endif
308 rep
309 movsb
310 nocmdline:
311 orb EXEADRS(setup_sects), %ch
312 # ifndef NO_MINSETUP
313 # ifndef BZIMAGE
314 jnz setupok
315 mov $4, %ch
316 setupok:
317 # endif
318 # endif
319 #else
320 movb EXEADRS(setup_sects), %ch
321 #endif
322 movb $(512-(end_header-_start))/2, %cl
323 movw $0x100, %si
324 movw $end_header, %di
325 rep
326 movsw
327 movw $SYSSEG, %ax
328 movw %ds, %bx
329 pushw %es
330 popw %ss
331 #ifndef SHUTDOWNDOS
332 pushw %es
333 pushw $movesys
334 #endif
335 #ifdef VCPI
336 pushaw
337 smsww %ax
338 andb $1, %al
339 je isrm
340 movw $EXEADRS(gdt_vcpi),%si
341 movw $pagebuf-0x90000,%di // %es = 0x9000
342 movl $pagebuf+3,%es:0x1000(%di)
343 call_vcpi:
344 movb $0xDE,%ah // DE01, EBX = getiface(DS:SI, ES:DI)
345 int $0x67
346 movl $FLAT20(sw2pm_params),%esi
347 movb $0x0C,%al // DE0C switchpm(ESI)
348 cli
349 jmp call_vcpi
350 pm_code:
351 movl %cr0,%eax
352 andl $0x7FFFFFFE,%eax
353 movl %eax,%cr0
354 movl %eax,%cr3
355 isrm:
356 # ifdef SHUTDOWNDOS
357 trace_int19
358 # else
359 lssw %cs:EXEADRS(saved_ss_sp),%sp
360 popaw
361 retf
362 # endif
363 #else
364 # ifdef SHUTDOWNDOS
365 pushaw
366 trace_int19
367 # endif
368 retf
369 #endif
370 #endif
372 # read_sectors reads %di sectors into %es:0 buffer.
373 # %es:0 is updated to the next memory location.
374 # First, sectors are read sector by sector until
375 # sector per track count is known. Then they are
376 # read track by track.
377 # Assume no error on first track.
379 #ifdef FLOPPY_1440K_ONLY
380 #define FLOPPY_HAS_2_SIDES hardcore heads count to 2
381 #define FLOPPY_SECTORS 18 /* 18 sectors */
382 #else
383 #define FLOPPY_HEADS 2 /* 2 heads minimum */
384 #endif
386 return:
387 #ifndef NO_DOTS
388 movw $0xE2E,%ax
389 movb $7,%bl
390 int $0x10
391 #endif
392 ret
394 check_limits:
395 #ifndef FLOPPY_1440K_ONLY
396 popw %dx
397 cmpb %al, %cl # max sector known ?
398 ja next_head # no -> store it
399 #ifndef FLOPPY_HAS_2_SIDES
400 #ifdef FLOPPY_HEADS
401 cmpb $FLOPPY_HEADS, %dh # 2 heads minimum
402 jb check_cylinder
403 #endif
404 cmpb %ah, %dh # max head known ?
405 ja next_cylinder # no -> store it
406 check_cylinder:
407 #endif
408 #endif
409 pushaw
410 #ifndef FLOPPY_1440K_ONLY
411 cbw # %ah = 0
412 #endif
413 int $0x13 # reset controler
414 popaw
415 movb $1, %al # sector by sector...
416 read_sectorslp:
417 pushw %dx # some bios break dx...
418 #ifndef FLOPPY_1440K_ONLY
419 pushw %ax # limits
420 subb %cl, %al # sectors remaining in track
421 ja tolastsect
422 movb $1, %al # 1 sector mini
423 tolastsect:
424 #else
425 movb $FLOPPY_SECTORS+1, %al
426 subb %cl, %al # sectors remaining in track
427 #endif
428 cbw
429 cmpw %di, %ax
430 jb more1trk
431 movw %di, %ax # sectors to read
432 more1trk:
433 pushw %ax # save context
434 movb $2, %ah # cmd: read chs
435 int $0x13
436 #ifndef FLOPPY_1440K_ONLY
437 popw %dx # save %ax
438 popw %ax # limits
439 #else
440 popw %ax # restore context
441 popw %dx
442 #endif
443 jc check_limits
444 #ifndef FLOPPY_1440K_ONLY
445 xchgw %ax, %bp
446 addw %dx,%cx # next sector
447 movw %cx, %gs
448 movw %es, %cx
449 pushw %dx
450 shlw $5, %dx
451 addw %dx, %cx
452 popw %dx
453 subw %dx,%di # update sector counter
454 popw %dx
455 #else
456 addw %ax,%cx # next sector
457 movw %cx, %gs
458 movw %es, %cx
459 pushw %ax
460 shlw $5, %ax
461 addw %ax, %cx
462 popw %ax
463 subw %ax,%di # update sector counter
464 #endif
465 read_sectorsCX:
466 movw %cx, %es # next location
467 jz return
468 read_sectors:
469 movw %gs, %cx
470 #ifndef FLOPPY_1440K_ONLY
471 # al is last sector+1
472 # ah is last cylinder+1
473 xchgw %ax, %bp
474 #endif
475 #ifndef FLOPPY_1440K_ONLY
476 cmpb %al,%cl # reach sector limit ?
477 jne bdendlp
478 next_head:
479 movb %cl,%al
480 #else
481 cmpb $FLOPPY_SECTORS+1,%cl # reach sector limit ?
482 jne bdendlp
483 #endif
484 movb $1,%cl # first sector
485 #ifndef FLOPPY_HAS_2_SIDES
486 incb %dh # next head
487 cmpb %ah, %dh # reach head limit ?
488 jne bdendlp
489 next_cylinder:
490 movb %dh,%ah
491 movb $0,%dh # first head
492 #else
493 xorb %cl,%dh # next head
494 jne bdendlp # reach head limit ?
495 #endif
496 # NOTE : support 256 cylinders max
497 incb %ch # next cylinder
498 read_first_sectors:
499 bdendlp:
500 jmp read_sectorslp
502 #ifdef VCPI
503 pagebuf = 0x98000
504 tss = gdt_abs-40
505 gdt = gdt_abs-32
506 gdt_null = gdt_abs-32
507 gdt_vcpi = gdt_abs-24
508 gdt_vcpi2 = gdt_abs-16
509 gdt_vcpi3 = gdt_abs-8
510 gdt_abs:
511 .word 0xFFFF
512 .long 0x92000000
513 .byte 0xCF,0
514 gdt_code:
515 .word 0xFFFF
516 gdt_code_base:
517 .long 0x9A000000+FLAT20(0)
518 .byte 0x8F,0
519 gdt_tss:
520 .word 0x00FF
521 gdt_tss_base:
522 .long 0x89000000+FLAT20(tss)
523 .byte 0,0
524 gdtr:
525 gdt_lim:
526 .word 0xFFFF
527 gdt_base:
528 .long FLAT20(gdt)
529 sw2pm_params:
530 sw2pm_cr3:
531 .long pagebuf+0x1000
532 sw2pm_gdtr_ptr:
533 .long FLAT20(gdtr)
534 sw2pm_idtr_ptr:
535 .long FLAT20(idtr)
536 sw2pm_ldtr:
537 .word 0
538 sw2pm_tr:
539 SEL_TSS = gdt_tss-gdt_null
540 .word SEL_TSS
541 sw2pm_jumpaddr:
542 .long pm_code
543 SEL_CODE = gdt_code-gdt_null
544 .word SEL_CODE
545 idtr:
546 idt_lim:
547 .word 0x03FF
548 idt_base:
549 .long 0
550 # ifndef SHUTDOWNDOS
551 saved_ss_sp:
552 .word stacktop-4-16-4,INITSEG
553 # endif
554 #endif