wok-stable diff 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 |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gpxe/stuff/prefix.u Fri Jun 27 20:38:59 2008 +0000 1.3 @@ -0,0 +1,393 @@ 1.4 +--- gpxe-0.9.3/src/arch/i386/prefix/lkrnprefix.S 1.5 ++++ gpxe-0.9.3/src/arch/i386/prefix/lkrnprefix.S 1.6 +@@ -50,40 +50,343 @@ 1.7 + .arch i386 1.8 + .org 0 1.9 + .section ".prefix", "ax", @progbits 1.10 +-/* 1.11 +- This is a minimal boot sector. If anyone tries to execute it (e.g., if 1.12 +- a .lilo file is dd'ed to a floppy), print an error message. 1.13 +-*/ 1.14 + 1.15 +-bootsector: 1.16 +- jmp $BOOTSEG, $1f /* reload cs:ip to match relocation addr */ 1.17 +-1: 1.18 +- movw $0x2000, %di /* 0x2000 is arbitrary value >= length 1.19 +- of bootsect + room for stack */ 1.20 ++ call here 1.21 ++here: 1.22 ++ pop %ax 1.23 ++ cmpw $0x103, %ax /* COM entry point is cs:0x100 */ 1.24 ++ jne bootsector 1.25 ++ 1.26 ++/* We need a real mode stack that won't be stomped on by Etherboot 1.27 ++ which starts at 0x20000. Choose something that's sufficiently high, 1.28 ++ but not in DOC territory. Note that we couldn't do this in a real 1.29 ++ .com program since stack variables are in the same segment as the 1.30 ++ code and data, but this isn't really a .com program, it just looks 1.31 ++ like one to make DOS load it into memory. It still has the 64kB 1.32 ++ limitation of .com files though. */ 1.33 ++#define STACK_SEG 0x7000 1.34 ++#define STACK_SIZE 0x4000 1.35 ++ /* Set up temporary stack */ 1.36 ++ movw $STACK_SEG, %ax 1.37 ++ movw %ax, %ss 1.38 ++ movw $STACK_SIZE, %sp 1.39 ++ 1.40 ++ /* Calculate segment address of image start */ 1.41 ++ pushw %cs 1.42 ++ popw %ax 1.43 ++ addw $(0x100/16), %ax 1.44 ++ jmp go_setup_code 1.45 ++ 1.46 ++bootsector: 1.47 ++ jmp $BOOTSEG, $go /* reload cs:ip to match relocation addr */ 1.48 ++go: 1.49 ++ movw $0x2000-12, %di /* 0x2000 is arbitrary value >= length */ 1.50 ++ /* of bootsect + room for stack + 12 for */ 1.51 ++ /* saved disk parm block */ 1.52 + 1.53 + movw $BOOTSEG, %ax 1.54 + movw %ax,%ds 1.55 + movw %ax,%es 1.56 +- 1.57 +- cli 1.58 +- movw %ax, %ss /* put stack at BOOTSEG:0x2000. */ 1.59 ++ movw %ax,%ss /* put stack at initial position */ 1.60 + movw %di,%sp 1.61 +- sti 1.62 + 1.63 +- movw $why_end-why, %cx 1.64 +- movw $why, %si 1.65 ++/* Many BIOS's default disk parameter tables will not recognize multi-sector 1.66 ++ * reads beyond the maximum sector number specified in the default diskette 1.67 ++ * parameter tables - this may mean 7 sectors in some cases. 1.68 ++ * 1.69 ++ * Since single sector reads are slow and out of the question, we must take care 1.70 ++ * of this by creating new parameter tables (for the first disk) in RAM. We 1.71 ++ * will set the maximum sector count to 36 - the most we will encounter on an 1.72 ++ * ED 2.88. High doesn't hurt. Low does. 1.73 ++ * 1.74 ++ * Segments are as follows: ds=es=ss=cs - BOOTSEG 1.75 ++ */ 1.76 + 1.77 +- movw $0x0007, %bx /* page 0, attribute 7 (normal) */ 1.78 +- movb $0x0e, %ah /* write char, tty mode */ 1.79 +-prloop: 1.80 ++ xorw %cx,%cx 1.81 ++ movw %cx,%es /* access segment 0 */ 1.82 ++ movw $0x78, %bx /* 0:bx is parameter table address */ 1.83 ++ pushw %ds /* save ds */ 1.84 ++/* 0:bx is parameter table address */ 1.85 ++ ldsw %es:(%bx),%si /* loads ds and si */ 1.86 ++ 1.87 ++ movw %ax,%es /* ax is BOOTSECT (loaded above) */ 1.88 ++ movb $6, %cl /* copy 12 bytes */ 1.89 ++ cld 1.90 ++ pushw %di /* keep a copy for later */ 1.91 ++ rep 1.92 ++ movsw /* ds:si is source, es:di is dest */ 1.93 ++ popw %di 1.94 ++ 1.95 ++ movb $36,%es:4(%di) 1.96 ++ 1.97 ++ movw %cx,%ds /* access segment 0 */ 1.98 ++ xchgw %di,(%bx) 1.99 ++ movw %es,%si 1.100 ++ xchgw %si,2(%bx) 1.101 ++ popw %ds /* restore ds */ 1.102 ++ movw %di, dpoff /* save old parameters */ 1.103 ++ movw %si, dpseg /* to restore just before finishing */ 1.104 ++ pushw %ds 1.105 ++ popw %es /* reload es */ 1.106 ++ 1.107 ++/* Note that es is already set up. Also cx is 0 from rep movsw above. */ 1.108 ++ 1.109 ++ xorb %ah,%ah /* reset FDC */ 1.110 ++ xorb %dl,%dl 1.111 ++ int $0x13 1.112 ++ 1.113 ++/* Get disk drive parameters, specifically number of sectors/track. 1.114 ++ * 1.115 ++ * It seems that there is no BIOS call to get the number of sectors. Guess 1.116 ++ * 36 sectors if sector 36 can be read, 18 sectors if sector 18 can be read, 1.117 ++ * 15 if sector 15 can be read. Otherwise guess 9. 1.118 ++ */ 1.119 ++ 1.120 ++ movw $disksizes, %si /* table of sizes to try */ 1.121 ++ 1.122 ++probe_loop: 1.123 + lodsb 1.124 ++ orb %al, %al 1.125 ++ je got_sectors /* if all else fails, try 9 */ 1.126 ++ cbtw /* extend to word */ 1.127 ++ movw %ax, sectors 1.128 ++ xchgw %cx,%ax /* cx = track and sector */ 1.129 ++ xorw %dx,%dx /* drive 0, head 0 */ 1.130 ++ movw $0x0200, %bx /* address after boot sector */ 1.131 ++ /* (512 bytes from origin, es = cs) */ 1.132 ++ movw $0x0201, %ax /* service 2, 1 sector */ 1.133 ++ int $0x13 1.134 ++ jc probe_loop /* try next value */ 1.135 ++ 1.136 ++got_sectors: 1.137 ++ movw $msg1end-msg1, %cx 1.138 ++ movw $msg1, %si 1.139 ++ call print_str 1.140 ++ 1.141 ++/* ok, we've written the Loading... message, now we want to load the system */ 1.142 ++ 1.143 ++ pushw %es /* = ds */ 1.144 ++ movw $SYSSEG, %ax 1.145 ++ movw %ax,%es /* segment of SYSSEG<<4 */ 1.146 ++ pushw %es 1.147 ++ call read_it 1.148 ++ 1.149 ++/* This turns off the floppy drive motor, so that we enter the kernel in a 1.150 ++ * known state, and don't have to worry about it later. 1.151 ++ */ 1.152 ++ movw $0x3f2, %dx 1.153 ++ xorb %al,%al 1.154 ++ outb %al,%dx 1.155 ++ 1.156 ++ call print_nl 1.157 ++ pop %es /* = SYSSEG */ 1.158 ++ pop %es /* balance push/pop es */ 1.159 ++sigok: 1.160 ++ 1.161 ++/* Restore original disk parameters */ 1.162 ++ movw $0x78, %bx 1.163 ++ movw dpoff, %di 1.164 ++ movw dpseg, %si 1.165 ++ xorw %ax,%ax 1.166 ++ movw %ax,%ds 1.167 ++ movw %di,(%bx) 1.168 ++ movw %si,2(%bx) 1.169 ++ 1.170 ++/* after that (everything loaded), we call to the .ROM file loaded. */ 1.171 ++ 1.172 ++ movw $SYSSEG, %ax 1.173 ++ jmp go_setup_code 1.174 ++ 1.175 ++/* This routine loads the system at address SYSSEG<<4, making sure no 64kB 1.176 ++ * boundaries are crossed. We try to load it as fast as possible, loading whole 1.177 ++ * tracks whenever we can. 1.178 ++ * 1.179 ++ * in: es - starting address segment (normally SYSSEG) 1.180 ++ */ 1.181 ++read_it: 1.182 ++ movw $0,sread /* read whole image incl boot sector */ 1.183 ++ movw %es,%ax 1.184 ++ testw $0x0fff, %ax 1.185 ++die: jne die /* es must be at 64kB boundary */ 1.186 ++ xorw %bx,%bx /* bx is starting address within segment */ 1.187 ++rp_read: 1.188 ++ movw %es,%ax 1.189 ++ movw %bx,%dx 1.190 ++ movb $4, %cl 1.191 ++ shrw %cl,%dx /* bx is always divisible by 16 */ 1.192 ++ addw %dx,%ax 1.193 ++.equ SYSSIZE, _load_size_pgh - 32 1.194 ++ cmpw $SYSSEG+SYSSIZE, %ax /* have we loaded all yet? */ 1.195 ++ jb ok1_read 1.196 ++ ret 1.197 ++ok1_read: 1.198 ++ movw sectors, %ax 1.199 ++ subw sread, %ax 1.200 ++ movw %ax,%cx 1.201 ++ shlw $9, %cx /* 80186 opcode */ 1.202 ++ addw %bx,%cx 1.203 ++ jnc ok2_read 1.204 ++ je ok2_read 1.205 ++ xorw %ax,%ax 1.206 ++ subw %bx,%ax 1.207 ++ shrw $9, %ax /* 80186 opcode */ 1.208 ++ok2_read: 1.209 ++ call read_track 1.210 ++ movw %ax,%cx 1.211 ++ addw sread, %ax 1.212 ++ cmpw sectors, %ax 1.213 ++ jne ok3_read 1.214 ++ movw $1, %ax 1.215 ++ subw head, %ax 1.216 ++ jne ok4_read 1.217 ++ incw track 1.218 ++ok4_read: 1.219 ++ movw %ax, head 1.220 ++ xorw %ax,%ax 1.221 ++ok3_read: 1.222 ++ movw %ax, sread 1.223 ++ shlw $9, %cx /* 80186 opcode */ 1.224 ++ addw %cx,%bx 1.225 ++ jnc rp_read 1.226 ++ movw %es,%ax 1.227 ++ addb $0x10, %ah 1.228 ++ movw %ax,%es 1.229 ++ xorw %bx,%bx 1.230 ++ jmp rp_read 1.231 ++ 1.232 ++read_track: 1.233 ++ pusha /* 80186 opcode */ 1.234 ++ pushw %ax 1.235 ++ pushw %bx 1.236 ++ pushw %bp /* just in case the BIOS is buggy */ 1.237 ++ movb $0x2e, %al /* 0x2e = . */ 1.238 ++ call print_char 1.239 ++ popw %bp 1.240 ++ popw %bx 1.241 ++ popw %ax 1.242 ++ 1.243 ++ movw sread, %cx 1.244 ++ incw %cx 1.245 ++ movb track, %ch 1.246 ++ movw $0x0100, %dx 1.247 ++ andb head, %dh 1.248 ++ movb $2, %ah 1.249 ++ 1.250 ++ pushw %dx /* save for error dump */ 1.251 ++ pushw %cx 1.252 ++ pushw %bx 1.253 ++ pushw %ax 1.254 ++ 1.255 ++ int $0x13 1.256 ++ jc bad_rt 1.257 ++ addw $8, %sp 1.258 ++ popa /* 80186 opcode */ 1.259 ++ ret 1.260 ++ 1.261 ++bad_rt: pushw %ax /* save error code */ 1.262 ++ call print_all /* ah = error, al = read */ 1.263 ++ 1.264 ++ xorb %ah,%ah 1.265 ++ xorb %dl,%dl 1.266 ++ int $0x13 1.267 ++ 1.268 ++ addw $10, %sp 1.269 ++ popa /* 80186 opcode */ 1.270 ++ jmp read_track 1.271 ++ 1.272 ++/* print_all is for debugging purposes. It will print out all of the registers. 1.273 ++ * The assumption is that this is called from a routine, with a stack frame like 1.274 ++ * dx 1.275 ++ * cx 1.276 ++ * bx 1.277 ++ * ax 1.278 ++ * error 1.279 ++ * ret <- sp 1.280 ++ */ 1.281 ++ 1.282 ++print_all: 1.283 ++ call print_nl /* nl for readability */ 1.284 ++ /* print_nl update ah and bx */ 1.285 ++ movw $5, %cx /* error code + 4 registers */ 1.286 ++ movw %sp,%bp 1.287 ++ 1.288 ++print_loop: 1.289 ++ pushw %cx /* save count left */ 1.290 ++ 1.291 ++ cmpb $5, %cl 1.292 ++ jae no_reg /* see if register name is needed */ 1.293 ++ 1.294 ++ movb $0x5+0x41-1, %al 1.295 ++ subb %cl,%al 1.296 ++ int $0x10 1.297 ++ 1.298 ++ movb $0x58, %al /* 'X' */ 1.299 + int $0x10 1.300 ++ 1.301 ++ movb $0x3A, %al /* ':' */ 1.302 ++ int $0x10 1.303 ++ 1.304 ++no_reg: 1.305 ++ addw $2, %bp /* next register */ 1.306 ++ call print_hex /* print it */ 1.307 ++ movb $0x20, %al /* print a space */ 1.308 ++ int $0x10 1.309 ++ popw %cx 1.310 ++ loop print_loop 1.311 ++ /* nl for readability */ 1.312 ++print_nl: 1.313 ++ movb $0xd, %al /* CR */ 1.314 ++ call print_char 1.315 ++ movb $0xa, %al /* LF */ 1.316 ++ jmp print_char 1.317 ++ 1.318 ++ 1.319 ++print_str: 1.320 ++prloop: 1.321 ++ lodsb 1.322 ++ call print_char 1.323 + loop prloop 1.324 +-freeze: jmp freeze 1.325 ++ ret 1.326 ++ 1.327 ++/* print_hex prints the word pointed to by ss:bp in hexadecimal. */ 1.328 ++ 1.329 ++print_hex: 1.330 ++ movw (%bp),%dx /* load word into dx */ 1.331 ++ movb $4, %cl 1.332 ++ call print_2digits 1.333 ++print_2digits: 1.334 ++ call print_digit 1.335 ++/* fall through */ 1.336 ++print_digit: 1.337 ++ rol %cl,%dx /* rotate to use lowest 4 bits */ 1.338 ++ movb $0x0f, %al /* mask for nybble */ 1.339 ++ andb %dl,%al 1.340 ++ addb $0x90, %al /* convert al to ascii hex */ 1.341 ++ daa /* (four instructions) */ 1.342 ++ adcb $0x40, %al 1.343 ++ daa 1.344 ++print_char: 1.345 ++ movb $0x0e, %ah /* write char, tty mode */ 1.346 ++ movw $0x0007, %bx /* page 0, attribute 7 (normal) */ 1.347 ++ int $0x10 1.348 ++ ret 1.349 ++ 1.350 ++sread: .word 0 /* sectors read of current track */ 1.351 ++head: .word 0 /* current head */ 1.352 ++track: .word 0 /* current track */ 1.353 ++ 1.354 ++sectors: 1.355 ++ .word 0 1.356 + 1.357 +-why: .ascii "This image cannot be loaded from a floppy disk.\r\n" 1.358 +-why_end: 1.359 ++dpseg: .word 0 1.360 ++dpoff: .word 0 1.361 + 1.362 ++disksizes: 1.363 ++ .byte 36,18,15,9,0 1.364 ++ 1.365 ++msg1: 1.366 ++ .ascii "Loading ROM image" 1.367 ++msg1end: 1.368 + 1.369 + .org 497 1.370 + setup_sects: 1.371 +@@ -123,14 +426,23 @@ 1.372 + executing the Etherboot image that's loaded at SYSSEG:0 and 1.373 + whose entry point is SYSSEG:0. 1.374 + */ 1.375 +-setup_code: 1.376 ++setup_code: 1.377 ++ movw $(SYSSEG-(PREFIXSIZE/16)), %ax 1.378 + /* Etherboot expects to be contiguous in memory once loaded. 1.379 + * LILO doesn't do this, but since we don't need any 1.380 + * information that's left in the prefix, it doesn't matter: 1.381 + * we just have to ensure that %cs:0000 is where the start of 1.382 + * the Etherboot image *would* be. 1.383 + */ 1.384 +- ljmp $(SYSSEG-(PREFIXSIZE/16)), $run_etherboot 1.385 ++go_setup_code: 1.386 ++ xorw %cx, %cx 1.387 ++ pushw %cx 1.388 ++ pushw %cx /* No parameters to preserve for exit path */ 1.389 ++ pushw %cx /* Use prefix exit path mechanism */ 1.390 ++ pushw %ax 1.391 ++ pushw $run_etherboot 1.392 ++ /* Calculated lcall to _start with %cs:0000 = image start */ 1.393 ++ lret 1.394 + 1.395 + 1.396 + .org PREFIXSIZE