wok annotate memtest/stuff/bootloader.S @ rev 19949

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