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

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