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

slitaz-base-files: up (270)
author Aleksej Bobylev <al.bobylev@gmail.com>
date Thu Apr 30 02:11:11 2015 +0300 (2015-04-30)
parents d038b033c321
children 5797509d0229
rev   line source
pascal@15188 1 SYSSEG = 0x1000
pascal@15188 2 INITSEG = 0x9000
pascal@15188 3 SETUPSEG = 0x9020
pascal@15188 4
pascal@15188 5 .text
pascal@15188 6 .code16
pascal@15188 7 .org 0
pascal@15188 8 .globl _start
pascal@15188 9 _start:
pascal@15188 10
pascal@15188 11 #define CODESZ 512
pascal@15188 12
pascal@15188 13 /* some extra features */
pascal@15188 14 #define EXE_SUPPORT real mode dos .exe file support
pascal@15188 15 #define CMDLINE 0x9E00
pascal@15188 16 #define HELP store help message for /? argument
pascal@15188 17 #define CHECK_REALMODE does not support vm86
pascal@15188 18
pascal@15188 19 /* some contraints to reduce the size */
pascal@15188 20 //#define FLOPPY_1440K_ONLY 1.44M floppies support only
pascal@15188 21 #define NO_CURSOR_DEFINITION
pascal@15188 22
pascal@15188 23 #ifdef EXE_SUPPORT
pascal@15188 24 #define EXEADRS(x) x+0xE0
pascal@15188 25 stacktop = 0x9E00 # in 0x8000 .. 0xA000
pascal@15188 26 decw %bp // Magic number: MZ
pascal@15188 27 popw %dx
pascal@15188 28 jmp start // Bytes on last page of file
pascal@15188 29 .word (CODESZ+511)/512 // Pages in file
pascal@15188 30 .word 0 // Relocations
pascal@15188 31 .word (end_header-_start)/16 // Size of header in paragraphs
pascal@15188 32 .word 4096 // Minimum extra paragraphs needed
pascal@15188 33 .word -1 // Maximum extra paragraphs needed
pascal@15188 34 .word (CODESZ+15)/16 // Initial (relative) SS value
pascal@15188 35 .word stacktop // Initial SP value
pascal@15188 36 .word 0 // Checksum
pascal@15188 37 .word EXEADRS(comstart) // Initial IP value
pascal@15188 38 .word 0xFFF0 // Initial (relative) CS value
pascal@15188 39 // .word 0x001C // File address of relocation table
pascal@15188 40 // .word 0,0,0 // Overlay number
pascal@15188 41 .ascii "(SliTaz)"
pascal@15188 42 end_header:
pascal@15188 43 comstart:
pascal@15470 44 cld # assume nothing
pascal@15188 45 #ifdef CMDLINE
pascal@15470 46 movw $stacktop, %di
pascal@15471 47 #else
pascal@15188 48 #undef HELP
pascal@15188 49 #endif
pascal@15188 50 pushw $INITSEG
pascal@15188 51 popw %es
pascal@15188 52 #ifdef CMDLINE
pascal@15188 53 movw $0x80, %si
pascal@15188 54 lodsb
pascal@15188 55 cbw
pascal@15188 56 xchgw %ax, %cx
pascal@15188 57 jcxz nocmdline
pascal@15470 58 movw $0xA33F, 0x7F(%si)
pascal@15188 59 skipspace:
pascal@15188 60 lodsb
pascal@15188 61 cmpb $0x20, %al
pascal@15188 62 je skipspace
pascal@15188 63 decw %si
pascal@15188 64 rep
pascal@15188 65 movsb
pascal@15188 66 # ifdef HELP
pascal@15188 67 # define PUTS
pascal@15188 68 movw $EXEADRS(helpmsg), %si
pascal@15485 69 cmpb $'/'+1, %al
pascal@15476 70 # ifdef CHECK_REALMODE
pascal@15485 71 js jsputs
pascal@15476 72 # else
pascal@15485 73 js puts
pascal@15476 74 # endif
pascal@15188 75 # endif
pascal@15188 76 nocmdline:
pascal@15188 77 #endif
pascal@15472 78 movw $SYSSEG, %ax
pascal@15188 79 #ifdef CHECK_REALMODE
pascal@15188 80 #define PUTS
pascal@15188 81 movw $EXEADRS(realmode_expected), %si
pascal@15188 82 // bits 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
pascal@15188 83 // flags 0 NT IOPL OF DF IF TF SF ZF 0 AF 0 PF 1 CF
pascal@15472 84 //movb $0x10, %ah // DF = IF = TF = 0
pascal@15188 85 pushw %ax
pascal@15188 86 popfw // < 286 : flags[12..15] are forced 1
pascal@15188 87 pushfw // = 286 : flags[12..15] are forced 0
pascal@15469 88 popw %dx // > 286 : only flags[15] is forced 0
pascal@15485 89 cmpb %ah, %dh // test Fx and 0x cases
pascal@15485 90 jsputs:
pascal@15485 91 js puts // S= not 386+
pascal@15472 92 smsww %dx
pascal@15472 93 shrw $1, %dx
pascal@15472 94 jc puts
pascal@17223 95 //movw syssize-realmode_expected(%si), %bp
pascal@17223 96 .byte 0x8B, 0x6C, syssize-realmode_expected
pascal@17223 97 //movb setup_sects-realmode_expected(%si), %ch
pascal@17223 98 .byte 0x8A, 0x6C, setup_sects-realmode_expected
pascal@17223 99 #else
pascal@17223 100 movw EXEADRS(syssize), %bp
pascal@17223 101 movb EXEADRS(setup_sects), %ch
pascal@15188 102 #endif
pascal@17223 103 movb $(512-(end_header-_start))/2, %cl
pascal@15188 104 movw $0x100, %si
pascal@15188 105 movw $end_header, %di
pascal@15188 106 rep
pascal@15188 107 movsw
pascal@15188 108 ljmp $INITSEG, $movesys
pascal@15188 109 start:
pascal@15188 110 pushw %dx
pascal@15188 111 #else
pascal@15188 112 #undef HELP
pascal@15188 113 #undef CMDLINE
pascal@15188 114 #undef CHECK_REALMODE
pascal@15188 115 #endif
pascal@15188 116 cld # assume nothing
pascal@15188 117 stacktop = 0x9E00 # in 0x8000 .. 0xA000
pascal@15188 118 zeroed = 12 # zeroed registers
pascal@15188 119 movw $stacktop-12-zeroed, %di # stacktop is an arbitrary value >=
pascal@15188 120 # length of bootsect + length of
pascal@15188 121 # setup + room for stack;
pascal@15188 122 # 12 is disk parm size.
pascal@15188 123 pushw $INITSEG
pascal@15188 124 popw %ss # %ss contain INITSEG
pascal@15188 125 movw %di, %sp # put stack at INITSEG:stacktop-...
pascal@15188 126
pascal@15188 127 # Many BIOS's default disk parameter tables will not recognize
pascal@15188 128 # multi-sector reads beyond the maximum sector number specified
pascal@15188 129 # in the default diskette parameter tables - this may mean 7
pascal@15188 130 # sectors in some cases.
pascal@15188 131 #
pascal@15188 132 # Since single sector reads are slow and out of the question,
pascal@15188 133 # we must take care of this by creating new parameter tables
pascal@15188 134 # (for the first disk) in RAM. We can set the maximum sector
pascal@15188 135 # count to 36 - the most we will encounter on an ED 2.88.
pascal@15188 136 #
pascal@15188 137 # High doesn't hurt. Low does. Let's use the max: 63
pascal@15188 138
pascal@15188 139 pushw %ss
pascal@15188 140 popw %es # %es = %ss = INITSEG
pascal@15188 141 xorw %ax, %ax # %ax = 0
pascal@15472 142 #ifdef EXE_SUPPORT
pascal@15472 143 cwd # %dx = 0
pascal@15472 144 #endif
pascal@15188 145 movw $zeroed/2, %cx # clear gdt + offset, %ds, limits
pascal@15188 146 rep # don't worry about cld
pascal@15188 147 stosw # already done above
pascal@15188 148 popw %bx # offset = 0
pascal@15188 149 popw %ds # %ds = 0
pascal@15188 150 popw %fs # %fs = 0
pascal@15188 151
pascal@15188 152 movb setup_sects+0x7C00, %al # read bootsector + setup (%ds = 0)
pascal@15188 153 incw %ax
pascal@15188 154
pascal@15188 155 ldsw 0x78(%bx), %si # %ds:%bx+0x78 is parameter table address
pascal@15188 156 pushw %es
pascal@15188 157 pushw %di
pascal@15188 158 movb $6, %cl # copy 12 bytes
pascal@15188 159 rep # don't worry about cld
pascal@15188 160 movsw # already done above
pascal@15188 161 pushw %ss
pascal@15188 162 popw %ds # now %ds = %es = %ss = INITSEG
pascal@15188 163 popl %fs:0x78(%bx) # update parameter table address
pascal@15188 164 movb $63, 0x4-12(%di) # patch sector count, %di = stacktop
pascal@15188 165 cli
pascal@15188 166
pascal@15188 167 xchg %ax, %di # sector count
pascal@15188 168 popw %ax # limits = 0
pascal@15188 169 incw %cx # cylinder 0, sector 1, clear Z
pascal@15188 170 call read_first_sectors # read setup
pascal@15188 171
pascal@15188 172 # This routine loads the system at address LOADSEG, making sure
pascal@15188 173 # no 64kB boundaries are crossed. We try to load it as fast as
pascal@15188 174 # possible, loading whole tracks whenever we can.
pascal@15188 175
pascal@15188 176 popw %bx # clear %bx
pascal@15188 177 movw syssize, %di
pascal@17223 178 decw %di
pascal@15188 179 shrw $9-4, %di
pascal@17223 180 incw %di
pascal@15188 181 movw $SYSSEG, %cx
pascal@15188 182 call read_sectorsCX
pascal@15188 183
pascal@15188 184 # This procedure turns off the floppy drive motor, so
pascal@15188 185 # that we enter the kernel in a known state, and
pascal@15188 186 # don't have to worry about it later.
pascal@15188 187
pascal@15188 188 kill_motor:
pascal@15188 189 xchgw %ax, %di # reset FDC (%di < 128)
pascal@15188 190 int $0x13
pascal@15188 191
pascal@15188 192 # After that (everything loaded), we jump to the setup-routine
pascal@15188 193 # loaded directly after the bootblock:
pascal@15188 194 # Segments are as follows: %ds = %ss = INITSEG
pascal@15188 195
pascal@15188 196 jmp_setup:
pascal@15188 197 ljmp $SETUPSEG, $0
pascal@15188 198
pascal@15188 199 #ifdef PUTS
pascal@15188 200 #define PUTC
pascal@15472 201 putslp:
pascal@15472 202 call putc
pascal@15188 203 puts:
pascal@15188 204 lodsb
pascal@15188 205 orb %al, %al
pascal@15472 206 jne putslp
pascal@15480 207 int $0x20 // dos exit
pascal@15188 208 #endif
pascal@15188 209 #ifdef EXE_SUPPORT
pascal@17223 210 movesys: // %ax = SYSSEG
pascal@15188 211 pushw %es
pascal@15188 212 popw %ss
pascal@15188 213 movw %ds, %bx
pascal@17223 214 subw %ax, %bx
pascal@15188 215 jnc forward
pascal@15188 216 addw %bp, %ax
pascal@15188 217 forward:
pascal@15188 218 movw %ax, %es
pascal@17223 219 movw %ax, %dx
pascal@17223 220 addw %bx, %dx
pascal@17223 221 movw %dx, %ds
pascal@17223 222 sbbw %dx, %dx // %dx = 0 : -1
pascal@17223 223 cmc // C = 1 : 0
pascal@17223 224 adcw %dx, %ax
pascal@15188 225 xorw %di, %di
pascal@15188 226 movb $8, %cl
pascal@15472 227 pushw %si
pascal@15188 228 rep
pascal@15188 229 movsw
pascal@15472 230 popw %si
pascal@15188 231 decw %bp
pascal@15188 232 jns forward
pascal@15188 233 #ifndef NO_CURSOR_DEFINITION
pascal@15188 234 movb $1, %ah
pascal@15188 235 movb $0, %bh
pascal@15188 236 movb $0x20, %ch // 0x2000
pascal@15188 237 int $0x10
pascal@15188 238 #endif
pascal@15188 239 pushw %ss
pascal@15188 240 popw %ds
pascal@15188 241 jmp jmp_setup
pascal@15188 242 #endif
pascal@15188 243 putcdot:
pascal@15188 244 #ifdef PUTC
pascal@15188 245 movb $0x2E, %al
pascal@15188 246 putc:
pascal@15188 247 movb $0xE, %ah
pascal@15188 248 movw $7, %bx
pascal@15188 249 int $0x10
pascal@15188 250 #endif
pascal@15188 251 ret
pascal@15188 252
pascal@15188 253
pascal@15188 254 # read_sectors reads %di sectors into %es:0 buffer.
pascal@15188 255 # %es:0 is updated to the next memory location.
pascal@15188 256 # First, sectors are read sector by sector until
pascal@15188 257 # sector per track count is known. Then they are
pascal@15188 258 # read track by track.
pascal@15188 259 # Assume no error on first track.
pascal@15188 260
pascal@15188 261 #ifdef FLOPPY_1440K_ONLY
pascal@15188 262 #define FLOPPY_HEADS 2 /* 2 heads */
pascal@15188 263 #define FLOPPY_SECTORS 18 /* 18 sectors */
pascal@15188 264 #else
pascal@15188 265 #define FLOPPY_HEADS 2 /* 2 heads minimum */
pascal@15188 266 #define FLOPPY_SECTORS 9 /* 9 sectors minimum */
pascal@15188 267 #endif
pascal@15188 268
pascal@15188 269 check_limits:
pascal@15188 270 #ifndef FLOPPY_1440K_ONLY
pascal@15188 271 popw %dx
pascal@15188 272 #ifdef FLOPPY_SECTORS
pascal@15188 273 cmpb $FLOPPY_SECTORS+1, %cl # minimum sector count
pascal@15188 274 jb check_head
pascal@15188 275 #endif
pascal@15188 276 cmpb %al, %cl # max sector known ?
pascal@15188 277 ja next_head # no -> store it
pascal@15188 278 check_head:
pascal@15188 279 #ifdef FLOPPY_HEADS
pascal@15188 280 cmpb $FLOPPY_HEADS, %dh # 2 heads minimum
pascal@15188 281 jb check_cylinder
pascal@15188 282 #endif
pascal@15188 283 cmpb %ah, %dh # max head known ?
pascal@15188 284 ja next_cylinder # no -> store it
pascal@15188 285 check_cylinder:
pascal@15188 286 #endif
pascal@15188 287 pushaw
pascal@15188 288 #ifndef FLOPPY_1440K_ONLY
pascal@15188 289 cbw # %ah = 0
pascal@15188 290 #endif
pascal@15188 291 int $0x13 # reset controler
pascal@15188 292 popaw
pascal@15188 293 movb $1, %al # sector by sector...
pascal@15188 294 read_sectorslp:
pascal@15188 295 pushw %dx # some bios break dx...
pascal@15188 296 #ifndef FLOPPY_1440K_ONLY
pascal@15188 297 pushw %ax # limits
pascal@15188 298 subb %cl, %al # sectors remaining in track
pascal@15188 299 ja tolastsect
pascal@15188 300 movb $1, %al # 1 sector mini
pascal@15188 301 tolastsect:
pascal@15188 302 #else
pascal@15188 303 mov $FLOPPY_SECTORS+1, %al
pascal@15188 304 subb %cl, %al # sectors remaining in track
pascal@15188 305 #endif
pascal@15188 306 cbw
pascal@15188 307 cmpw %di, %ax
pascal@15188 308 jb more1trk
pascal@15188 309 movw %di, %ax # sectors to read
pascal@15188 310 more1trk:
pascal@15188 311 pushw %ax # save context
pascal@15188 312 movb $2, %ah # cmd: read chs
pascal@15188 313 int $0x13
pascal@15188 314 #ifndef FLOPPY_1440K_ONLY
pascal@15188 315 popw %dx # save %ax
pascal@15188 316 popw %ax # limits
pascal@15188 317 #else
pascal@15188 318 popw %ax # restore context
pascal@15188 319 popw %dx
pascal@15188 320 #endif
pascal@15188 321 jc check_limits
pascal@15188 322 #ifndef FLOPPY_1440K_ONLY
pascal@15188 323 xchgw %ax, %bp
pascal@15188 324 addw %dx,%cx # next sector
pascal@15188 325 movw %cx, %gs
pascal@15188 326 movw %es, %cx
pascal@15188 327 pushw %dx
pascal@15188 328 shlw $5, %dx
pascal@15188 329 addw %dx, %cx
pascal@15188 330 popw %dx
pascal@15188 331 subw %dx,%di # update sector counter
pascal@15188 332 popw %dx
pascal@15188 333 read_sectorsCX:
pascal@15188 334 movw %cx, %es # next location
pascal@15188 335 jz putcdot
pascal@15188 336 #else
pascal@15188 337 addw %ax,%cx # next sector
pascal@15188 338 movw %cx, %gs
pascal@15188 339 movw %es, %cx
pascal@15188 340 pushw %ax
pascal@15188 341 shlw $5, %ax
pascal@15188 342 addw %ax, %cx
pascal@15188 343 popw %ax
pascal@15188 344 subw %ax,%di # update sector counter
pascal@15188 345 read_sectorsCX:
pascal@15188 346 movw %cx, %es # next location
pascal@15188 347 jz putcdot
pascal@15188 348 #endif
pascal@15188 349 read_sectors:
pascal@15188 350 movw %gs, %cx
pascal@15188 351 #ifndef FLOPPY_1440K_ONLY
pascal@15188 352 # al is last sector+1
pascal@15188 353 # ah is last cylinder+1
pascal@15188 354 xchgw %ax, %bp
pascal@15188 355 #endif
pascal@15188 356 #ifndef FLOPPY_1440K_ONLY
pascal@15188 357 cmpb %al,%cl # reach sector limit ?
pascal@15188 358 jne bdendlp
pascal@15188 359 next_head:
pascal@15188 360 movb %cl,%al
pascal@15188 361 #else
pascal@15188 362 cmpb $FLOPPY_SECTORS+1,%cl # reach sector limit ?
pascal@15188 363 jne bdendlp
pascal@15188 364 #endif
pascal@15188 365 incb %dh # next head
pascal@15188 366 movb $1,%cl # first sector
pascal@15188 367 #ifndef FLOPPY_1440K_ONLY
pascal@15188 368 cmpb %ah, %dh # reach head limit ?
pascal@15188 369 jne bdendlp
pascal@15188 370 next_cylinder:
pascal@15188 371 movb %dh,%ah
pascal@15188 372 #else
pascal@15188 373 cmpb %cl,%dh # reach head limit ?
pascal@15188 374 je bdendlp
pascal@15188 375 #endif
pascal@15188 376 # NOTE : support 256 cylinders max
pascal@15188 377 incb %ch # next cylinder
pascal@15188 378 read_first_sectors:
pascal@15188 379 movb $0,%dh # first head
pascal@15188 380 bdendlp:
pascal@15188 381 jmp read_sectorslp
pascal@15188 382
pascal@15188 383 #ifdef HELP
pascal@15188 384 helpmsg:
pascal@15188 385 .ascii "No help available."
pascal@15188 386 .byte 13,10
pascal@15188 387 .byte 0
pascal@15188 388 #endif
pascal@17223 389 #ifdef CHECK_REALMODE
pascal@17223 390 .org 475
pascal@17223 391 realmode_expected:
pascal@17223 392 helpend:
pascal@17223 393 .ascii "386 real mode only."
pascal@17223 394 .byte 13,10,0
pascal@17223 395 #endif
pascal@15188 396 .org 497
pascal@17223 397 setup_sects:
pascal@17223 398 .byte 0
pascal@17223 399 .org 500
pascal@17223 400 syssize:
pascal@17223 401 .word 0
pascal@17223 402