wok-current annotate gpxe/stuff/prefix.u @ rev 3125

Up: ntpclient (2007_365) + disable DEBUG
author Eric Joseph-Alexandre <erjo@slitaz.org>
date Tue May 19 15:28:24 2009 +0200 (2009-05-19)
parents a9ff8c135e36
children
rev   line source
pascal@955 1 --- gpxe-0.9.3/src/arch/i386/prefix/lkrnprefix.S
pascal@955 2 +++ gpxe-0.9.3/src/arch/i386/prefix/lkrnprefix.S
pascal@960 3 @@ -3,6 +3,7 @@
pascal@960 4
pascal@960 5 Authors: Gary Byers (gb@thinguin.org)
pascal@960 6 Marty Connor (mdc@thinguin.org)
pascal@960 7 + Pascal Bellard (pascal.bellard@slitaz.org)
pascal@960 8
pascal@960 9 This software may be used and distributed according to the terms
pascal@960 10 of the GNU Public License (GPL), incorporated herein by reference.
pascal@960 11 @@ -50,40 +51,351 @@
pascal@955 12 .arch i386
pascal@955 13 .org 0
pascal@955 14 .section ".prefix", "ax", @progbits
pascal@955 15 -/*
pascal@955 16 - This is a minimal boot sector. If anyone tries to execute it (e.g., if
pascal@955 17 - a .lilo file is dd'ed to a floppy), print an error message.
pascal@955 18 -*/
pascal@955 19
pascal@955 20 -bootsector:
pascal@955 21 - jmp $BOOTSEG, $1f /* reload cs:ip to match relocation addr */
pascal@955 22 -1:
pascal@955 23 - movw $0x2000, %di /* 0x2000 is arbitrary value >= length
pascal@955 24 - of bootsect + room for stack */
pascal@955 25 + call here
pascal@955 26 +here:
pascal@955 27 + pop %ax
pascal@955 28 + cmpw $0x103, %ax /* COM entry point is cs:0x100 */
pascal@955 29 + jne bootsector
pascal@955 30 +
pascal@955 31 +/* We need a real mode stack that won't be stomped on by Etherboot
pascal@955 32 + which starts at 0x20000. Choose something that's sufficiently high,
pascal@955 33 + but not in DOC territory. Note that we couldn't do this in a real
pascal@955 34 + .com program since stack variables are in the same segment as the
pascal@955 35 + code and data, but this isn't really a .com program, it just looks
pascal@955 36 + like one to make DOS load it into memory. It still has the 64kB
pascal@955 37 + limitation of .com files though. */
pascal@955 38 +#define STACK_SEG 0x7000
pascal@955 39 +#define STACK_SIZE 0x4000
pascal@955 40 + /* Set up temporary stack */
pascal@955 41 + movw $STACK_SEG, %ax
pascal@955 42 + movw %ax, %ss
pascal@955 43 + movw $STACK_SIZE, %sp
pascal@955 44 +
pascal@955 45 + /* Calculate segment address of image start */
pascal@955 46 + pushw %cs
pascal@955 47 + popw %ax
pascal@960 48 + addw $(0x100/16), %ax /* Adjust cs */
pascal@960 49 + pushw %ax
pascal@955 50 + jmp go_setup_code
pascal@955 51 +
pascal@955 52 +bootsector:
pascal@955 53 + jmp $BOOTSEG, $go /* reload cs:ip to match relocation addr */
pascal@955 54 +go:
pascal@955 55 + movw $0x2000-12, %di /* 0x2000 is arbitrary value >= length */
pascal@955 56 + /* of bootsect + room for stack + 12 for */
pascal@955 57 + /* saved disk parm block */
pascal@955 58
pascal@955 59 movw $BOOTSEG, %ax
pascal@955 60 movw %ax,%ds
pascal@955 61 movw %ax,%es
pascal@955 62 -
pascal@955 63 - cli
pascal@955 64 - movw %ax, %ss /* put stack at BOOTSEG:0x2000. */
pascal@955 65 + movw %ax,%ss /* put stack at initial position */
pascal@955 66 movw %di,%sp
pascal@955 67 - sti
pascal@955 68
pascal@955 69 - movw $why_end-why, %cx
pascal@955 70 - movw $why, %si
pascal@955 71 +/* Many BIOS's default disk parameter tables will not recognize multi-sector
pascal@955 72 + * reads beyond the maximum sector number specified in the default diskette
pascal@955 73 + * parameter tables - this may mean 7 sectors in some cases.
pascal@955 74 + *
pascal@955 75 + * Since single sector reads are slow and out of the question, we must take care
pascal@955 76 + * of this by creating new parameter tables (for the first disk) in RAM. We
pascal@955 77 + * will set the maximum sector count to 36 - the most we will encounter on an
pascal@955 78 + * ED 2.88. High doesn't hurt. Low does.
pascal@955 79 + *
pascal@955 80 + * Segments are as follows: ds=es=ss=cs - BOOTSEG
pascal@955 81 + */
pascal@960 82 +
pascal@955 83 + xorw %cx,%cx
pascal@955 84 + movw %cx,%es /* access segment 0 */
pascal@955 85 + movw $0x78, %bx /* 0:bx is parameter table address */
pascal@955 86 + pushw %ds /* save ds */
pascal@955 87 +/* 0:bx is parameter table address */
pascal@955 88 + ldsw %es:(%bx),%si /* loads ds and si */
pascal@955 89 +
pascal@955 90 + movw %ax,%es /* ax is BOOTSECT (loaded above) */
pascal@955 91 + movb $6, %cl /* copy 12 bytes */
pascal@955 92 + cld
pascal@955 93 + pushw %di /* keep a copy for later */
pascal@955 94 + rep
pascal@955 95 + movsw /* ds:si is source, es:di is dest */
pascal@955 96 + popw %di
pascal@955 97 +
pascal@955 98 + movb $36,%es:4(%di)
pascal@955 99 +
pascal@955 100 + movw %cx,%ds /* access segment 0 */
pascal@955 101 + xchgw %di,(%bx)
pascal@955 102 + movw %es,%si
pascal@955 103 + xchgw %si,2(%bx)
pascal@955 104 + popw %ds /* restore ds */
pascal@955 105 + movw %di, dpoff /* save old parameters */
pascal@955 106 + movw %si, dpseg /* to restore just before finishing */
pascal@955 107 + pushw %ds
pascal@955 108 + popw %es /* reload es */
pascal@955 109 +
pascal@955 110 +/* Note that es is already set up. Also cx is 0 from rep movsw above. */
pascal@955 111 +
pascal@955 112 + xorb %ah,%ah /* reset FDC */
pascal@955 113 + xorb %dl,%dl
pascal@955 114 + int $0x13
pascal@955 115 +
pascal@955 116 +/* Get disk drive parameters, specifically number of sectors/track.
pascal@955 117 + *
pascal@955 118 + * It seems that there is no BIOS call to get the number of sectors. Guess
pascal@955 119 + * 36 sectors if sector 36 can be read, 18 sectors if sector 18 can be read,
pascal@955 120 + * 15 if sector 15 can be read. Otherwise guess 9.
pascal@955 121 + */
pascal@960 122
pascal@960 123 - movw $0x0007, %bx /* page 0, attribute 7 (normal) */
pascal@960 124 - movb $0x0e, %ah /* write char, tty mode */
pascal@960 125 -prloop:
pascal@955 126 + movw $disksizes, %si /* table of sizes to try */
pascal@955 127 +
pascal@955 128 +probe_loop:
pascal@955 129 lodsb
pascal@955 130 + orb %al, %al
pascal@955 131 + je got_sectors /* if all else fails, try 9 */
pascal@955 132 + cbtw /* extend to word */
pascal@955 133 + movw %ax, sectors
pascal@955 134 + xchgw %cx,%ax /* cx = track and sector */
pascal@955 135 + xorw %dx,%dx /* drive 0, head 0 */
pascal@955 136 + movw $0x0200, %bx /* address after boot sector */
pascal@955 137 + /* (512 bytes from origin, es = cs) */
pascal@955 138 + movw $0x0201, %ax /* service 2, 1 sector */
pascal@955 139 + int $0x13
pascal@955 140 + jc probe_loop /* try next value */
pascal@955 141 +
pascal@955 142 +got_sectors:
pascal@955 143 + movw $msg1end-msg1, %cx
pascal@955 144 + movw $msg1, %si
pascal@955 145 + call print_str
pascal@955 146 +
pascal@955 147 +/* ok, we've written the Loading... message, now we want to load the system */
pascal@955 148 +
pascal@955 149 + movw $SYSSEG, %ax
pascal@955 150 + movw %ax,%es /* segment of SYSSEG<<4 */
pascal@955 151 + pushw %es
pascal@955 152 + call read_it
pascal@955 153 +
pascal@955 154 +/* This turns off the floppy drive motor, so that we enter the kernel in a
pascal@955 155 + * known state, and don't have to worry about it later.
pascal@955 156 + */
pascal@955 157 + movw $0x3f2, %dx
pascal@955 158 + xorb %al,%al
pascal@955 159 + outb %al,%dx
pascal@955 160 +
pascal@955 161 + call print_nl
pascal@955 162 + pop %es /* = SYSSEG */
pascal@955 163 +sigok:
pascal@955 164 +
pascal@955 165 +/* Restore original disk parameters */
pascal@955 166 + movw $0x78, %bx
pascal@955 167 + movw dpoff, %di
pascal@955 168 + movw dpseg, %si
pascal@955 169 + xorw %ax,%ax
pascal@955 170 + movw %ax,%ds
pascal@955 171 + movw %di,(%bx)
pascal@955 172 + movw %si,2(%bx)
pascal@955 173 +
pascal@960 174 + /* Everything now loaded. %es = SYSSEG, so %es:0000 points to
pascal@960 175 + * start of loaded image.
pascal@960 176 + */
pascal@955 177 +
pascal@960 178 + /* Jump to loaded copy */
pascal@960 179 + ljmp $SYSSEG, $run_etherboot
pascal@955 180 +
pascal@960 181 +endseg: .word SYSSEG + _load_size_pgh
pascal@960 182 + .section ".zinfo.fixup", "a" /* Compressor fixup information */
pascal@960 183 + .ascii "SUBW"
pascal@960 184 + .long endseg
pascal@960 185 + .long 16
pascal@960 186 + .long 0
pascal@960 187 + .previous
pascal@960 188 +
pascal@955 189 +/* This routine loads the system at address SYSSEG<<4, making sure no 64kB
pascal@955 190 + * boundaries are crossed. We try to load it as fast as possible, loading whole
pascal@955 191 + * tracks whenever we can.
pascal@955 192 + *
pascal@955 193 + * in: es - starting address segment (normally SYSSEG)
pascal@955 194 + */
pascal@955 195 +read_it:
pascal@955 196 + movw $0,sread /* read whole image incl boot sector */
pascal@955 197 + movw %es,%ax
pascal@955 198 + testw $0x0fff, %ax
pascal@955 199 +die: jne die /* es must be at 64kB boundary */
pascal@955 200 + xorw %bx,%bx /* bx is starting address within segment */
pascal@955 201 +rp_read:
pascal@955 202 + movw %es,%ax
pascal@955 203 + movw %bx,%dx
pascal@955 204 + movb $4, %cl
pascal@955 205 + shrw %cl,%dx /* bx is always divisible by 16 */
pascal@955 206 + addw %dx,%ax
pascal@960 207 + cmpw syssize, %ax /* have we loaded all yet? */
pascal@955 208 + jb ok1_read
pascal@955 209 + ret
pascal@955 210 +ok1_read:
pascal@955 211 + movw sectors, %ax
pascal@955 212 + subw sread, %ax
pascal@955 213 + movw %ax,%cx
pascal@955 214 + shlw $9, %cx /* 80186 opcode */
pascal@955 215 + addw %bx,%cx
pascal@955 216 + jnc ok2_read
pascal@955 217 + je ok2_read
pascal@955 218 + xorw %ax,%ax
pascal@955 219 + subw %bx,%ax
pascal@955 220 + shrw $9, %ax /* 80186 opcode */
pascal@955 221 +ok2_read:
pascal@955 222 + call read_track
pascal@955 223 + movw %ax,%cx
pascal@955 224 + addw sread, %ax
pascal@955 225 + cmpw sectors, %ax
pascal@955 226 + jne ok3_read
pascal@955 227 + movw $1, %ax
pascal@955 228 + subw head, %ax
pascal@955 229 + jne ok4_read
pascal@955 230 + incw track
pascal@955 231 +ok4_read:
pascal@955 232 + movw %ax, head
pascal@955 233 + xorw %ax,%ax
pascal@955 234 +ok3_read:
pascal@955 235 + movw %ax, sread
pascal@955 236 + shlw $9, %cx /* 80186 opcode */
pascal@955 237 + addw %cx,%bx
pascal@955 238 + jnc rp_read
pascal@955 239 + movw %es,%ax
pascal@955 240 + addb $0x10, %ah
pascal@955 241 + movw %ax,%es
pascal@955 242 + xorw %bx,%bx
pascal@955 243 + jmp rp_read
pascal@955 244 +
pascal@955 245 +read_track:
pascal@955 246 + pusha /* 80186 opcode */
pascal@955 247 + pushw %ax
pascal@955 248 + pushw %bx
pascal@955 249 + pushw %bp /* just in case the BIOS is buggy */
pascal@955 250 + movb $0x2e, %al /* 0x2e = . */
pascal@955 251 + call print_char
pascal@955 252 + popw %bp
pascal@955 253 + popw %bx
pascal@955 254 + popw %ax
pascal@955 255 +
pascal@955 256 + movw sread, %cx
pascal@955 257 + incw %cx
pascal@955 258 + movb track, %ch
pascal@955 259 + movw $0x0100, %dx
pascal@955 260 + andb head, %dh
pascal@955 261 + movb $2, %ah
pascal@955 262 +
pascal@955 263 + pushw %dx /* save for error dump */
pascal@955 264 + pushw %cx
pascal@955 265 + pushw %bx
pascal@955 266 + pushw %ax
pascal@955 267 +
pascal@955 268 + int $0x13
pascal@955 269 + jc bad_rt
pascal@955 270 + addw $8, %sp
pascal@955 271 + popa /* 80186 opcode */
pascal@955 272 + ret
pascal@955 273 +
pascal@955 274 +bad_rt: pushw %ax /* save error code */
pascal@955 275 + call print_all /* ah = error, al = read */
pascal@955 276 +
pascal@955 277 + xorb %ah,%ah
pascal@955 278 + xorb %dl,%dl
pascal@955 279 + int $0x13
pascal@955 280 +
pascal@955 281 + addw $10, %sp
pascal@955 282 + popa /* 80186 opcode */
pascal@955 283 + jmp read_track
pascal@955 284 +
pascal@955 285 +/* print_all is for debugging purposes. It will print out all of the registers.
pascal@955 286 + * The assumption is that this is called from a routine, with a stack frame like
pascal@955 287 + * dx
pascal@955 288 + * cx
pascal@955 289 + * bx
pascal@955 290 + * ax
pascal@955 291 + * error
pascal@955 292 + * ret <- sp
pascal@955 293 + */
pascal@955 294 +
pascal@955 295 +print_all:
pascal@955 296 + call print_nl /* nl for readability */
pascal@955 297 + /* print_nl update ah and bx */
pascal@955 298 + movw $5, %cx /* error code + 4 registers */
pascal@955 299 + movw %sp,%bp
pascal@955 300 +
pascal@955 301 +print_loop:
pascal@955 302 + pushw %cx /* save count left */
pascal@955 303 +
pascal@955 304 + cmpb $5, %cl
pascal@955 305 + jae no_reg /* see if register name is needed */
pascal@955 306 +
pascal@955 307 + movb $0x5+0x41-1, %al
pascal@955 308 + subb %cl,%al
pascal@955 309 + int $0x10
pascal@955 310 +
pascal@955 311 + movb $0x58, %al /* 'X' */
pascal@955 312 int $0x10
pascal@955 313 +
pascal@955 314 + movb $0x3A, %al /* ':' */
pascal@955 315 + int $0x10
pascal@955 316 +
pascal@955 317 +no_reg:
pascal@955 318 + addw $2, %bp /* next register */
pascal@955 319 + call print_hex /* print it */
pascal@955 320 + movb $0x20, %al /* print a space */
pascal@955 321 + int $0x10
pascal@955 322 + popw %cx
pascal@955 323 + loop print_loop
pascal@955 324 + /* nl for readability */
pascal@955 325 +print_nl:
pascal@955 326 + movb $0xd, %al /* CR */
pascal@955 327 + call print_char
pascal@955 328 + movb $0xa, %al /* LF */
pascal@955 329 + jmp print_char
pascal@955 330 +
pascal@955 331 +
pascal@955 332 +print_str:
pascal@955 333 +prloop:
pascal@955 334 + lodsb
pascal@955 335 + call print_char
pascal@955 336 loop prloop
pascal@955 337 -freeze: jmp freeze
pascal@955 338 + ret
pascal@960 339
pascal@960 340 -why: .ascii "This image cannot be loaded from a floppy disk.\r\n"
pascal@960 341 -why_end:
pascal@955 342 +/* print_hex prints the word pointed to by ss:bp in hexadecimal. */
pascal@960 343
pascal@955 344 +print_hex:
pascal@955 345 + movw (%bp),%dx /* load word into dx */
pascal@955 346 + movb $4, %cl
pascal@955 347 + call print_2digits
pascal@955 348 +print_2digits:
pascal@955 349 + call print_digit
pascal@955 350 +/* fall through */
pascal@955 351 +print_digit:
pascal@955 352 + rol %cl,%dx /* rotate to use lowest 4 bits */
pascal@955 353 + movb $0x0f, %al /* mask for nybble */
pascal@955 354 + andb %dl,%al
pascal@955 355 + addb $0x90, %al /* convert al to ascii hex */
pascal@955 356 + daa /* (four instructions) */
pascal@955 357 + adcb $0x40, %al
pascal@955 358 + daa
pascal@955 359 +print_char:
pascal@955 360 + movb $0x0e, %ah /* write char, tty mode */
pascal@955 361 + movw $0x0007, %bx /* page 0, attribute 7 (normal) */
pascal@955 362 + int $0x10
pascal@955 363 + ret
pascal@955 364 +
pascal@955 365 +sread: .word 0 /* sectors read of current track */
pascal@955 366 +head: .word 0 /* current head */
pascal@955 367 +track: .word 0 /* current track */
pascal@955 368 +
pascal@955 369 +sectors:
pascal@955 370 + .word 0
pascal@960 371 +
pascal@955 372 +dpseg: .word 0
pascal@955 373 +dpoff: .word 0
pascal@960 374 +
pascal@955 375 +disksizes:
pascal@955 376 + .byte 36,18,15,9,0
pascal@955 377 +
pascal@955 378 +msg1:
pascal@955 379 + .ascii "Loading ROM image"
pascal@955 380 +msg1end:
pascal@955 381
pascal@955 382 .org 497
pascal@955 383 setup_sects:
pascal@960 384 @@ -106,13 +418,6 @@
pascal@960 385
pascal@960 386 .org 512
pascal@960 387
pascal@960 388 - .section ".zinfo.fixup", "a" /* Compressor fixup information */
pascal@960 389 - .ascii "SUBW"
pascal@960 390 - .long syssize
pascal@960 391 - .long 16
pascal@960 392 - .long 0
pascal@960 393 - .previous
pascal@960 394 -
pascal@960 395 /*
pascal@960 396 We're now at the beginning of the second sector of the image -
pascal@960 397 where the setup code goes.
pascal@960 398 @@ -123,14 +428,18 @@
pascal@955 399 executing the Etherboot image that's loaded at SYSSEG:0 and
pascal@955 400 whose entry point is SYSSEG:0.
pascal@955 401 */
pascal@955 402 -setup_code:
pascal@955 403 +setup_code:
pascal@960 404 + pushw $(SYSSEG-(PREFIXSIZE/16))
pascal@955 405 /* Etherboot expects to be contiguous in memory once loaded.
pascal@955 406 * LILO doesn't do this, but since we don't need any
pascal@955 407 * information that's left in the prefix, it doesn't matter:
pascal@955 408 * we just have to ensure that %cs:0000 is where the start of
pascal@955 409 * the Etherboot image *would* be.
pascal@955 410 */
pascal@955 411 - ljmp $(SYSSEG-(PREFIXSIZE/16)), $run_etherboot
pascal@955 412 +go_setup_code:
pascal@955 413 + pushw $run_etherboot
pascal@955 414 + /* Calculated lcall to _start with %cs:0000 = image start */
pascal@955 415 + lret
pascal@955 416
pascal@955 417
pascal@955 418 .org PREFIXSIZE
pascal@960 419 @@ -140,6 +449,10 @@
pascal@960 420 run_etherboot:
pascal@960 421 call install
pascal@960 422
pascal@960 423 + /* Set up real-mode stack */
pascal@960 424 + movw %bx, %ss
pascal@960 425 + movw $_estack16, %sp
pascal@960 426 +
pascal@960 427 /* Jump to .text16 segment */
pascal@960 428 pushw %ax
pascal@960 429 pushw $1f