wok-next diff etherboot/stuff/patches/etherboot-prefix.u @ rev 20661
Unification of the patch system
author | Aleksej Bobylev <al.bobylev@gmail.com> |
---|---|
date | Thu May 10 21:12:00 2018 +0300 (2018-05-10) |
parents | etherboot/stuff/etherboot-prefix.u@4a87a0aa0476 |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/etherboot/stuff/patches/etherboot-prefix.u Thu May 10 21:12:00 2018 +0300 1.3 @@ -0,0 +1,859 @@ 1.4 +--- etherboot-5.4.3/src/arch/i386/prefix/liloprefix.S 1.5 ++++ etherboot-5.4.3/src/arch/i386/prefix/liloprefix.S 1.6 +@@ -1,92 +1,377 @@ 1.7 +-/* 1.8 +- Copyright (C) 2000, Entity Cyber, Inc. 1.9 +- 1.10 +- Authors: Gary Byers (gb@thinguin.org) 1.11 +- Marty Connor (mdc@thinguin.org) 1.12 +- 1.13 +- This software may be used and distributed according to the terms 1.14 +- of the GNU Public License (GPL), incorporated herein by reference. 1.15 +- 1.16 +- Description: 1.17 +- 1.18 +- This is just a little bit of code and data that can get prepended 1.19 +- to an Etherboot ROM image in order to allow LILO to load the 1.20 +- result as if it were a Linux kernel image. 1.21 +- 1.22 +- A real Linux kernel image consists of a one-sector boot loader 1.23 +- (to load the image from a floppy disk), followed a few sectors 1.24 +- of setup code, followed by the kernel code itself. There's 1.25 +- a table in the first sector (starting at offset 497) that indicates 1.26 +- how many sectors of setup code follow the first sector and which 1.27 +- contains some other parameters that aren't interesting in this 1.28 +- case. 1.29 +- 1.30 +- When LILO loads the sectors that comprise a kernel image, it doesn't 1.31 +- execute the code in the first sector (since that code would try to 1.32 +- load the image from a floppy disk.) The code in the first sector 1.33 +- below doesn't expect to get executed (and prints an error message 1.34 +- if it ever -is- executed.) LILO's only interested in knowing the 1.35 +- number of setup sectors advertised in the table (at offset 497 in 1.36 +- the first sector.) 1.37 +- 1.38 +- Etherboot doesn't require much in the way of setup code. 1.39 +- Historically, the Linux kernel required at least 4 sectors of 1.40 +- setup code. Current versions of LILO look at the byte at 1.41 +- offset 497 in the first sector to indicate how many sectors 1.42 +- of setup code are contained in the image. 1.43 +- 1.44 +-*/ 1.45 ++/* SYS_SIZE is the number of clicks (16 bytes) to be loaded. For Etherboot 1.46 ++ * purposes, we need to load everything but the boot sector itself, i.e. 32 1.47 ++ * clicks less than the size of the entire (verbatim) image. The image size 1.48 ++ * is practically limited only by the available base memory size. 1.49 ++ */ 1.50 ++.globl SYSSIZE 1.51 ++.equ SYSSIZE, _verbatim_size_pgh - 32 1.52 ++ 1.53 ++/* floppyload.S Copyright (C) 1991, 1992 Linus Torvalds 1.54 ++ * modified by Drew Eckhardt 1.55 ++ * modified by Bruce Evans (bde) 1.56 ++ * 1.57 ++ * floppyprefix.S is loaded at 0x0000:0x7c00 by the bios-startup routines. 1.58 ++ * 1.59 ++ * It then loads the system at SYSSEG<<4, using BIOS interrupts. 1.60 ++ * 1.61 ++ * The loader has been made as simple as possible, and continuous read errors 1.62 ++ * will result in a unbreakable loop. Reboot by hand. It loads pretty fast by 1.63 ++ * getting whole tracks at a time whenever possible. 1.64 ++ */ 1.65 + 1.66 + #define SETUPSECS 4 /* Minimal nr of setup-sectors */ 1.67 + #define PREFIXSIZE ((SETUPSECS+1)*512) 1.68 + #define PREFIXPGH (PREFIXSIZE / 16 ) 1.69 +-#define BOOTSEG 0x07C0 /* original address of boot-sector */ 1.70 + #define INITSEG 0x9000 /* we move boot here - out of the way */ 1.71 + #define SETUPSEG 0x9020 /* setup starts here */ 1.72 +-#define SYSSEG 0x1000 /* system loaded at 0x10000 (65536). */ 1.73 + 1.74 +- .text 1.75 +- .code16 1.76 +- .arch i386 1.77 +- .org 0 1.78 +- .section ".prefix", "ax", @progbits 1.79 + .globl _prefix 1.80 + _prefix: 1.81 ++.equ BOOTSEG, 0x07C0 /* original address of boot-sector */ 1.82 + 1.83 +-/* 1.84 +- This is a minimal boot sector. If anyone tries to execute it (e.g., if 1.85 +- a .lilo file is dd'ed to a floppy), print an error message. 1.86 +-*/ 1.87 ++.equ SYSSEG, 0x1000 /* system loaded at SYSSEG<<4 */ 1.88 ++ 1.89 ++ .org 0 1.90 ++ .arch i386 1.91 ++ .text 1.92 ++ .section ".prefix", "ax", @progbits 1.93 ++ .code16 1.94 ++ 1.95 ++ call here 1.96 ++here: 1.97 ++ pop %ax 1.98 ++ cmpw $0x103, %ax /* COM entry point is cs:0x100 */ 1.99 ++ jne bootsector 1.100 ++ 1.101 ++/* We need a real mode stack that won't be stomped on by Etherboot 1.102 ++ which starts at 0x20000. Choose something that's sufficiently high, 1.103 ++ but not in DOC territory. Note that we couldn't do this in a real 1.104 ++ .com program since stack variables are in the same segment as the 1.105 ++ code and data, but this isn't really a .com program, it just looks 1.106 ++ like one to make DOS load it into memory. It still has the 64kB 1.107 ++ limitation of .com files though. */ 1.108 ++#define STACK_SEG 0x7000 1.109 ++#define STACK_SIZE 0x4000 1.110 ++ /* Set up temporary stack */ 1.111 ++ movw $STACK_SEG, %ax 1.112 ++ movw %ax, %ss 1.113 ++ movw $STACK_SIZE, %sp 1.114 ++ 1.115 ++ /* Calculate segment address of image start */ 1.116 ++ pushw %cs 1.117 ++ popw %ax 1.118 ++ addw $(0x100/16), %ax 1.119 ++ jmp go_setup_code 1.120 + 1.121 +-bootsector: 1.122 +- jmp $BOOTSEG, $go - _prefix /* reload cs:ip to match relocation addr */ 1.123 ++bootsector: 1.124 ++ jmp $BOOTSEG, $go /* reload cs:ip to match relocation addr */ 1.125 + go: 1.126 +- movw $0x2000, %di /* 0x2000 is arbitrary value >= length 1.127 +- of bootsect + room for stack */ 1.128 ++ movw $0x2000-12, %di /* 0x2000 is arbitrary value >= length */ 1.129 ++ /* of bootsect + room for stack + 12 for */ 1.130 ++ /* saved disk parm block */ 1.131 + 1.132 + movw $BOOTSEG, %ax 1.133 + movw %ax,%ds 1.134 + movw %ax,%es 1.135 +- 1.136 +- cli 1.137 +- movw %ax, %ss /* put stack at BOOTSEG:0x2000. */ 1.138 ++ movw %ax,%ss /* put stack at initial position */ 1.139 + movw %di,%sp 1.140 +- sti 1.141 + 1.142 +- movw $why_end-why, %cx 1.143 +- movw $why - _prefix, %si 1.144 ++/* Many BIOS's default disk parameter tables will not recognize multi-sector 1.145 ++ * reads beyond the maximum sector number specified in the default diskette 1.146 ++ * parameter tables - this may mean 7 sectors in some cases. 1.147 ++ * 1.148 ++ * Since single sector reads are slow and out of the question, we must take care 1.149 ++ * of this by creating new parameter tables (for the first disk) in RAM. We 1.150 ++ * will set the maximum sector count to 36 - the most we will encounter on an 1.151 ++ * ED 2.88. High doesn't hurt. Low does. 1.152 ++ * 1.153 ++ * Segments are as follows: ds=es=ss=cs - BOOTSEG 1.154 ++ */ 1.155 ++ 1.156 ++ xorw %cx,%cx 1.157 ++ movw %cx,%es /* access segment 0 */ 1.158 ++ movw $0x78, %bx /* 0:bx is parameter table address */ 1.159 ++ pushw %ds /* save ds */ 1.160 ++/* 0:bx is parameter table address */ 1.161 ++ ldsw %es:(%bx),%si /* loads ds and si */ 1.162 ++ 1.163 ++ movw %ax,%es /* ax is BOOTSECT (loaded above) */ 1.164 ++ movb $6, %cl /* copy 12 bytes */ 1.165 ++ cld 1.166 ++ pushw %di /* keep a copy for later */ 1.167 ++ rep 1.168 ++ movsw /* ds:si is source, es:di is dest */ 1.169 ++ popw %di 1.170 ++ 1.171 ++ movb $36,%es:4(%di) 1.172 ++ 1.173 ++ movw %cx,%ds /* access segment 0 */ 1.174 ++ xchgw %di,(%bx) 1.175 ++ movw %es,%si 1.176 ++ xchgw %si,2(%bx) 1.177 ++ popw %ds /* restore ds */ 1.178 ++ movw %di, dpoff /* save old parameters */ 1.179 ++ movw %si, dpseg /* to restore just before finishing */ 1.180 ++ pushw %ds 1.181 ++ popw %es /* reload es */ 1.182 ++ 1.183 ++/* Note that es is already set up. Also cx is 0 from rep movsw above. */ 1.184 ++ 1.185 ++ xorb %ah,%ah /* reset FDC */ 1.186 ++ xorb %dl,%dl 1.187 ++ int $0x13 1.188 ++ 1.189 ++/* Get disk drive parameters, specifically number of sectors/track. 1.190 ++ * 1.191 ++ * It seems that there is no BIOS call to get the number of sectors. Guess 1.192 ++ * 36 sectors if sector 36 can be read, 18 sectors if sector 18 can be read, 1.193 ++ * 15 if sector 15 can be read. Otherwise guess 9. 1.194 ++ */ 1.195 + 1.196 +- movw $0x0007, %bx /* page 0, attribute 7 (normal) */ 1.197 +- movb $0x0e, %ah /* write char, tty mode */ 1.198 +-prloop: 1.199 ++ movw $disksizes, %si /* table of sizes to try */ 1.200 ++ 1.201 ++probe_loop: 1.202 + lodsb 1.203 ++ orb %al, %al 1.204 ++ je got_sectors /* if all else fails, try 9 */ 1.205 ++ cbtw /* extend to word */ 1.206 ++ movw %ax, sectors 1.207 ++ xchgw %cx,%ax /* cx = track and sector */ 1.208 ++ xorw %dx,%dx /* drive 0, head 0 */ 1.209 ++ movw $0x0200, %bx /* address after boot sector */ 1.210 ++ /* (512 bytes from origin, es = cs) */ 1.211 ++ movw $0x0201, %ax /* service 2, 1 sector */ 1.212 ++ int $0x13 1.213 ++ jc probe_loop /* try next value */ 1.214 ++ 1.215 ++got_sectors: 1.216 ++ movw $msg1end-msg1, %cx 1.217 ++ movw $msg1, %si 1.218 ++ call print_str 1.219 ++ 1.220 ++/* ok, we've written the Loading... message, now we want to load the system */ 1.221 ++ 1.222 ++ pushw %es /* = ds */ 1.223 ++ movw $SYSSEG, %ax 1.224 ++ movw %ax,%es /* segment of SYSSEG<<4 */ 1.225 ++ pushw %es 1.226 ++ call read_it 1.227 ++ 1.228 ++/* This turns off the floppy drive motor, so that we enter the kernel in a 1.229 ++ * known state, and don't have to worry about it later. 1.230 ++ */ 1.231 ++ movw $0x3f2, %dx 1.232 ++ xorb %al,%al 1.233 ++ outb %al,%dx 1.234 ++ 1.235 ++ call print_nl 1.236 ++ pop %es /* = SYSSEG */ 1.237 ++ pop %es /* balance push/pop es */ 1.238 ++sigok: 1.239 ++ 1.240 ++/* Restore original disk parameters */ 1.241 ++ movw $0x78, %bx 1.242 ++ movw dpoff, %di 1.243 ++ movw dpseg, %si 1.244 ++ xorw %ax,%ax 1.245 ++ movw %ax,%ds 1.246 ++ movw %di,(%bx) 1.247 ++ movw %si,2(%bx) 1.248 ++ 1.249 ++/* after that (everything loaded), we call to the .ROM file loaded. */ 1.250 ++ 1.251 ++ movw $SYSSEG, %ax 1.252 ++ jmp go_setup_code 1.253 ++ 1.254 ++/* This routine loads the system at address SYSSEG<<4, making sure no 64kB 1.255 ++ * boundaries are crossed. We try to load it as fast as possible, loading whole 1.256 ++ * tracks whenever we can. 1.257 ++ * 1.258 ++ * in: es - starting address segment (normally SYSSEG) 1.259 ++ */ 1.260 ++read_it: 1.261 ++ movw $0,sread /* read whole image incl boot sector */ 1.262 ++ movw %es,%ax 1.263 ++ testw $0x0fff, %ax 1.264 ++die: jne die /* es must be at 64kB boundary */ 1.265 ++ xorw %bx,%bx /* bx is starting address within segment */ 1.266 ++rp_read: 1.267 ++ movw %es,%ax 1.268 ++ movw %bx,%dx 1.269 ++ movb $4, %cl 1.270 ++ shrw %cl,%dx /* bx is always divisible by 16 */ 1.271 ++ addw %dx,%ax 1.272 ++ cmpw $SYSSEG+SYSSIZE, %ax /* have we loaded all yet? */ 1.273 ++ jb ok1_read 1.274 ++ ret 1.275 ++ok1_read: 1.276 ++ movw sectors, %ax 1.277 ++ subw sread, %ax 1.278 ++ movw %ax,%cx 1.279 ++ shlw $9, %cx /* 80186 opcode */ 1.280 ++ addw %bx,%cx 1.281 ++ jnc ok2_read 1.282 ++ je ok2_read 1.283 ++ xorw %ax,%ax 1.284 ++ subw %bx,%ax 1.285 ++ shrw $9, %ax /* 80186 opcode */ 1.286 ++ok2_read: 1.287 ++ call read_track 1.288 ++ movw %ax,%cx 1.289 ++ addw sread, %ax 1.290 ++ cmpw sectors, %ax 1.291 ++ jne ok3_read 1.292 ++ movw $1, %ax 1.293 ++ subw head, %ax 1.294 ++ jne ok4_read 1.295 ++ incw track 1.296 ++ok4_read: 1.297 ++ movw %ax, head 1.298 ++ xorw %ax,%ax 1.299 ++ok3_read: 1.300 ++ movw %ax, sread 1.301 ++ shlw $9, %cx /* 80186 opcode */ 1.302 ++ addw %cx,%bx 1.303 ++ jnc rp_read 1.304 ++ movw %es,%ax 1.305 ++ addb $0x10, %ah 1.306 ++ movw %ax,%es 1.307 ++ xorw %bx,%bx 1.308 ++ jmp rp_read 1.309 ++ 1.310 ++read_track: 1.311 ++ pusha /* 80186 opcode */ 1.312 ++ pushw %ax 1.313 ++ pushw %bx 1.314 ++ pushw %bp /* just in case the BIOS is buggy */ 1.315 ++ movb $0x2e, %al /* 0x2e = . */ 1.316 ++ call print_char 1.317 ++ popw %bp 1.318 ++ popw %bx 1.319 ++ popw %ax 1.320 ++ 1.321 ++ movw sread, %cx 1.322 ++ incw %cx 1.323 ++ movb track, %ch 1.324 ++ movw $0x0100, %dx 1.325 ++ andb head, %dh 1.326 ++ movb $2, %ah 1.327 ++ 1.328 ++ pushw %dx /* save for error dump */ 1.329 ++ pushw %cx 1.330 ++ pushw %bx 1.331 ++ pushw %ax 1.332 ++ 1.333 ++ int $0x13 1.334 ++ jc bad_rt 1.335 ++ addw $8, %sp 1.336 ++ popa /* 80186 opcode */ 1.337 ++ ret 1.338 ++ 1.339 ++bad_rt: pushw %ax /* save error code */ 1.340 ++ call print_all /* ah = error, al = read */ 1.341 ++ 1.342 ++ xorb %ah,%ah 1.343 ++ xorb %dl,%dl 1.344 ++ int $0x13 1.345 ++ 1.346 ++ addw $10, %sp 1.347 ++ popa /* 80186 opcode */ 1.348 ++ jmp read_track 1.349 ++ 1.350 ++/* print_all is for debugging purposes. It will print out all of the registers. 1.351 ++ * The assumption is that this is called from a routine, with a stack frame like 1.352 ++ * dx 1.353 ++ * cx 1.354 ++ * bx 1.355 ++ * ax 1.356 ++ * error 1.357 ++ * ret <- sp 1.358 ++ */ 1.359 ++ 1.360 ++print_all: 1.361 ++ call print_nl /* nl for readability */ 1.362 ++ /* print_nl update ah and bx */ 1.363 ++ movw $5, %cx /* error code + 4 registers */ 1.364 ++ movw %sp,%bp 1.365 ++ 1.366 ++print_loop: 1.367 ++ pushw %cx /* save count left */ 1.368 ++ 1.369 ++ cmpb $5, %cl 1.370 ++ jae no_reg /* see if register name is needed */ 1.371 ++ 1.372 ++ movb $0x5+0x41-1, %al 1.373 ++ subb %cl,%al 1.374 ++ int $0x10 1.375 ++ 1.376 ++ movb $0x58, %al /* 'X' */ 1.377 ++ int $0x10 1.378 ++ 1.379 ++ movb $0x3A, %al /* ':' */ 1.380 ++ int $0x10 1.381 ++ 1.382 ++no_reg: 1.383 ++ addw $2, %bp /* next register */ 1.384 ++ call print_hex /* print it */ 1.385 ++ movb $0x20, %al /* print a space */ 1.386 + int $0x10 1.387 ++ popw %cx 1.388 ++ loop print_loop 1.389 ++ /* nl for readability */ 1.390 ++print_nl: 1.391 ++ movb $0xd, %al /* CR */ 1.392 ++ call print_char 1.393 ++ movb $0xa, %al /* LF */ 1.394 ++ jmp print_char 1.395 ++ 1.396 ++ 1.397 ++print_str: 1.398 ++prloop: 1.399 ++ lodsb 1.400 ++ call print_char 1.401 + loop prloop 1.402 +-freeze: jmp freeze 1.403 ++ ret 1.404 ++ 1.405 ++/* print_hex prints the word pointed to by ss:bp in hexadecimal. */ 1.406 ++ 1.407 ++print_hex: 1.408 ++ movw (%bp),%dx /* load word into dx */ 1.409 ++ movb $4, %cl 1.410 ++ call print_2digits 1.411 ++print_2digits: 1.412 ++ call print_digit 1.413 ++/* fall through */ 1.414 ++print_digit: 1.415 ++ rol %cl,%dx /* rotate to use lowest 4 bits */ 1.416 ++ movb $0x0f, %al /* mask for nybble */ 1.417 ++ andb %dl,%al 1.418 ++ addb $0x90, %al /* convert al to ascii hex */ 1.419 ++ daa /* (four instructions) */ 1.420 ++ adcb $0x40, %al 1.421 ++ daa 1.422 ++print_char: 1.423 ++ movb $0x0e, %ah /* write char, tty mode */ 1.424 ++ movw $0x0007, %bx /* page 0, attribute 7 (normal) */ 1.425 ++ int $0x10 1.426 ++ ret 1.427 ++ 1.428 ++sread: .word 0 /* sectors read of current track */ 1.429 ++head: .word 0 /* current head */ 1.430 ++track: .word 0 /* current track */ 1.431 ++ 1.432 ++sectors: 1.433 ++ .word 0 1.434 ++ 1.435 ++dpseg: .word 0 1.436 ++dpoff: .word 0 1.437 + 1.438 +-why: .ascii "This image cannot be loaded from a floppy disk.\r\n" 1.439 +-why_end: 1.440 ++disksizes: 1.441 ++ .byte 36,18,15,9,0 1.442 + 1.443 ++msg1: 1.444 ++ .ascii "Loading ROM image" 1.445 ++msg1end: 1.446 + 1.447 + .org 497 1.448 + setup_sects: 1.449 +@@ -117,15 +402,22 @@ 1.450 + whose entry point is SYSSEG:0. 1.451 + */ 1.452 + setup_code: 1.453 +- pushl $0 /* No parameters to preserve for exit path */ 1.454 +- pushw $0 /* Use prefix exit path mechanism */ 1.455 ++ movw $(SYSSEG-(PREFIXSIZE/16)), %ax 1.456 + /* Etherboot expects to be contiguous in memory once loaded. 1.457 + * LILO doesn't do this, but since we don't need any 1.458 + * information that's left in the prefix, it doesn't matter: 1.459 + * we just have to ensure that %cs:0000 is where the start of 1.460 + * the Etherboot image *would* be. 1.461 + */ 1.462 +- ljmp $(SYSSEG-(PREFIXSIZE/16)), $_start 1.463 ++go_setup_code: 1.464 ++ xorw %cx, %cx 1.465 ++ pushw %cx 1.466 ++ pushw %cx /* No parameters to preserve for exit path */ 1.467 ++ pushw %cx /* Use prefix exit path mechanism */ 1.468 ++ pushw %ax 1.469 ++ pushw $_start 1.470 ++ /* Calculated lcall to _start with %cs:0000 = image start */ 1.471 ++ lret 1.472 + 1.473 + .section ".text16", "ax", @progbits 1.474 + .globl prefix_exit 1.475 + 1.476 +--- etherboot-5.4.3/src/arch/i386/prefix/bImageprefix.S 1.477 ++++ etherboot-5.4.3/src/arch/i386/prefix/bImageprefix.S 1.478 +@@ -82,6 +82,14 @@ 1.479 + #define SIG1 0xAA55 1.480 + #define SIG2 0x5A5A 1.481 + 1.482 ++/* SYS_SIZE is the number of clicks (16 bytes) to be loaded. For Etherboot 1.483 ++ * purposes, we need to load everything but the boot sector itself, i.e. 32 1.484 ++ * clicks less than the size of the entire (verbatim) image. The image size 1.485 ++ * is practically limited only by the available base memory size. 1.486 ++ */ 1.487 ++.globl SYSSIZE 1.488 ++.equ SYSSIZE, _verbatim_size_pgh - 32 1.489 ++ 1.490 + .text 1.491 + .code16 1.492 + .arch i386 1.493 +@@ -90,40 +98,349 @@ 1.494 + .globl _prefix 1.495 + _prefix: 1.496 + 1.497 +-/* 1.498 +- This is a minimal boot sector. If anyone tries to execute it (e.g., if 1.499 +- a .lilo file is dd'ed to a floppy), print an error message. 1.500 +-*/ 1.501 ++ call here 1.502 ++here: 1.503 ++ pop %ax 1.504 ++ cmpw $0x103, %ax /* COM entry point is cs:0x100 */ 1.505 ++ jne bootsector 1.506 ++ 1.507 ++/* We need a real mode stack that won't be stomped on by Etherboot 1.508 ++ which starts at 0x20000. Choose something that's sufficiently high, 1.509 ++ but not in DOC territory. Note that we couldn't do this in a real 1.510 ++ .com program since stack variables are in the same segment as the 1.511 ++ code and data, but this isn't really a .com program, it just looks 1.512 ++ like one to make DOS load it into memory. It still has the 64kB 1.513 ++ limitation of .com files though. */ 1.514 ++#define STACK_SEG 0x7000 1.515 ++#define STACK_SIZE 0x4000 1.516 ++ /* Set up temporary stack */ 1.517 ++ movw $STACK_SEG, %ax 1.518 ++ movw %ax, %ss 1.519 ++ movw $STACK_SIZE, %sp 1.520 ++ 1.521 ++ /* Calculate segment address of image start */ 1.522 ++ pushw %cs 1.523 ++ popw %ax 1.524 ++ addw $(0x100/16), %ax 1.525 ++ jmp go_setup_code 1.526 + 1.527 +-bootsector: 1.528 +- jmp $BOOTSEG, $go - _prefix /* reload cs:ip to match relocation addr */ 1.529 ++bootsector: 1.530 ++ jmp $BOOTSEG, $go /* reload cs:ip to match relocation addr */ 1.531 + go: 1.532 +- movw $0x2000, %di /* 0x2000 is arbitrary value >= length 1.533 +- of bootsect + room for stack */ 1.534 ++ movw $0x2000-12, %di /* 0x2000 is arbitrary value >= length */ 1.535 ++ /* of bootsect + room for stack + 12 for */ 1.536 ++ /* saved disk parm block */ 1.537 + 1.538 + movw $BOOTSEG, %ax 1.539 + movw %ax,%ds 1.540 + movw %ax,%es 1.541 +- 1.542 +- cli 1.543 +- movw %ax, %ss /* put stack at BOOTSEG:0x2000. */ 1.544 ++ movw %ax,%ss /* put stack at initial position */ 1.545 + movw %di,%sp 1.546 +- sti 1.547 + 1.548 +- movw $why_end-why, %cx 1.549 +- movw $why - _prefix, %si 1.550 ++/* Many BIOS's default disk parameter tables will not recognize multi-sector 1.551 ++ * reads beyond the maximum sector number specified in the default diskette 1.552 ++ * parameter tables - this may mean 7 sectors in some cases. 1.553 ++ * 1.554 ++ * Since single sector reads are slow and out of the question, we must take care 1.555 ++ * of this by creating new parameter tables (for the first disk) in RAM. We 1.556 ++ * will set the maximum sector count to 36 - the most we will encounter on an 1.557 ++ * ED 2.88. High doesn't hurt. Low does. 1.558 ++ * 1.559 ++ * Segments are as follows: ds=es=ss=cs - BOOTSEG 1.560 ++ */ 1.561 ++ 1.562 ++ xorw %cx,%cx 1.563 ++ movw %cx,%es /* access segment 0 */ 1.564 ++ movw $0x78, %bx /* 0:bx is parameter table address */ 1.565 ++ pushw %ds /* save ds */ 1.566 ++/* 0:bx is parameter table address */ 1.567 ++ ldsw %es:(%bx),%si /* loads ds and si */ 1.568 ++ 1.569 ++ movw %ax,%es /* ax is BOOTSECT (loaded above) */ 1.570 ++ movb $6, %cl /* copy 12 bytes */ 1.571 ++ cld 1.572 ++ pushw %di /* keep a copy for later */ 1.573 ++ rep 1.574 ++ movsw /* ds:si is source, es:di is dest */ 1.575 ++ popw %di 1.576 + 1.577 +- movw $0x0007, %bx /* page 0, attribute 7 (normal) */ 1.578 +- movb $0x0e, %ah /* write char, tty mode */ 1.579 +-prloop: 1.580 ++ movb $36,%es:4(%di) 1.581 ++ 1.582 ++ movw %cx,%ds /* access segment 0 */ 1.583 ++ xchgw %di,(%bx) 1.584 ++ movw %es,%si 1.585 ++ xchgw %si,2(%bx) 1.586 ++ popw %ds /* restore ds */ 1.587 ++ movw %di, dpoff /* save old parameters */ 1.588 ++ movw %si, dpseg /* to restore just before finishing */ 1.589 ++ pushw %ds 1.590 ++ popw %es /* reload es */ 1.591 ++ 1.592 ++/* Note that es is already set up. Also cx is 0 from rep movsw above. */ 1.593 ++ 1.594 ++ xorb %ah,%ah /* reset FDC */ 1.595 ++ xorb %dl,%dl 1.596 ++ int $0x13 1.597 ++ 1.598 ++/* Get disk drive parameters, specifically number of sectors/track. 1.599 ++ * 1.600 ++ * It seems that there is no BIOS call to get the number of sectors. Guess 1.601 ++ * 36 sectors if sector 36 can be read, 18 sectors if sector 18 can be read, 1.602 ++ * 15 if sector 15 can be read. Otherwise guess 9. 1.603 ++ */ 1.604 ++ 1.605 ++ movw $disksizes, %si /* table of sizes to try */ 1.606 ++ 1.607 ++probe_loop: 1.608 + lodsb 1.609 ++ orb %al, %al 1.610 ++ je got_sectors /* if all else fails, try 9 */ 1.611 ++ cbtw /* extend to word */ 1.612 ++ movw %ax, sectors 1.613 ++ xchgw %cx,%ax /* cx = track and sector */ 1.614 ++ xorw %dx,%dx /* drive 0, head 0 */ 1.615 ++ movw $0x0200, %bx /* address after boot sector */ 1.616 ++ /* (512 bytes from origin, es = cs) */ 1.617 ++ movw $0x0201, %ax /* service 2, 1 sector */ 1.618 ++ int $0x13 1.619 ++ jc probe_loop /* try next value */ 1.620 ++ 1.621 ++got_sectors: 1.622 ++ movw $msg1end-msg1, %cx 1.623 ++ movw $msg1, %si 1.624 ++ call print_str 1.625 ++ 1.626 ++/* ok, we've written the Loading... message, now we want to load the system */ 1.627 ++ 1.628 ++ pushw %es /* = ds */ 1.629 ++ movw $SYSSEG, %ax 1.630 ++ movw %ax,%es /* segment of SYSSEG<<4 */ 1.631 ++ pushw %es 1.632 ++ call read_it 1.633 ++ 1.634 ++/* This turns off the floppy drive motor, so that we enter the kernel in a 1.635 ++ * known state, and don't have to worry about it later. 1.636 ++ */ 1.637 ++ movw $0x3f2, %dx 1.638 ++ xorb %al,%al 1.639 ++ outb %al,%dx 1.640 ++ 1.641 ++ call print_nl 1.642 ++ pop %es /* = SYSSEG */ 1.643 ++ pop %es /* balance push/pop es */ 1.644 ++sigok: 1.645 ++ 1.646 ++/* Restore original disk parameters */ 1.647 ++ movw $0x78, %bx 1.648 ++ movw dpoff, %di 1.649 ++ movw dpseg, %si 1.650 ++ xorw %ax,%ax 1.651 ++ movw %ax,%ds 1.652 ++ movw %di,(%bx) 1.653 ++ movw %si,2(%bx) 1.654 ++ 1.655 ++/* after that (everything loaded), we call to the .ROM file loaded. */ 1.656 ++ 1.657 ++ movw $SYSSEG, %ax 1.658 ++go_setup_code: 1.659 ++ xorw %cx, %cx 1.660 ++ pushw %cx 1.661 ++ pushw %cx /* No parameters to preserve for exit path */ 1.662 ++ pushw %cx /* Use prefix exit path mechanism */ 1.663 ++ pushw %ax 1.664 ++ pushw $_start 1.665 ++ /* Calculated lcall to _start with %cs:0000 = image start */ 1.666 ++ lret 1.667 ++ 1.668 ++/* This routine loads the system at address SYSSEG<<4, making sure no 64kB 1.669 ++ * boundaries are crossed. We try to load it as fast as possible, loading whole 1.670 ++ * tracks whenever we can. 1.671 ++ * 1.672 ++ * in: es - starting address segment (normally SYSSEG) 1.673 ++ */ 1.674 ++read_it: 1.675 ++ movw $0,sread /* read whole image incl boot sector */ 1.676 ++ movw %es,%ax 1.677 ++ testw $0x0fff, %ax 1.678 ++die: jne die /* es must be at 64kB boundary */ 1.679 ++ xorw %bx,%bx /* bx is starting address within segment */ 1.680 ++rp_read: 1.681 ++ movw %es,%ax 1.682 ++ movw %bx,%dx 1.683 ++ movb $4, %cl 1.684 ++ shrw %cl,%dx /* bx is always divisible by 16 */ 1.685 ++ addw %dx,%ax 1.686 ++ cmpw $SYSSEG+SYSSIZE, %ax /* have we loaded all yet? */ 1.687 ++ jb ok1_read 1.688 ++ ret 1.689 ++ok1_read: 1.690 ++ movw sectors, %ax 1.691 ++ subw sread, %ax 1.692 ++ movw %ax,%cx 1.693 ++ shlw $9, %cx /* 80186 opcode */ 1.694 ++ addw %bx,%cx 1.695 ++ jnc ok2_read 1.696 ++ je ok2_read 1.697 ++ xorw %ax,%ax 1.698 ++ subw %bx,%ax 1.699 ++ shrw $9, %ax /* 80186 opcode */ 1.700 ++ok2_read: 1.701 ++ call read_track 1.702 ++ movw %ax,%cx 1.703 ++ addw sread, %ax 1.704 ++ cmpw sectors, %ax 1.705 ++ jne ok3_read 1.706 ++ movw $1, %ax 1.707 ++ subw head, %ax 1.708 ++ jne ok4_read 1.709 ++ incw track 1.710 ++ok4_read: 1.711 ++ movw %ax, head 1.712 ++ xorw %ax,%ax 1.713 ++ok3_read: 1.714 ++ movw %ax, sread 1.715 ++ shlw $9, %cx /* 80186 opcode */ 1.716 ++ addw %cx,%bx 1.717 ++ jnc rp_read 1.718 ++ movw %es,%ax 1.719 ++ addb $0x10, %ah 1.720 ++ movw %ax,%es 1.721 ++ xorw %bx,%bx 1.722 ++ jmp rp_read 1.723 ++ 1.724 ++read_track: 1.725 ++ pusha /* 80186 opcode */ 1.726 ++ pushw %ax 1.727 ++ pushw %bx 1.728 ++ pushw %bp /* just in case the BIOS is buggy */ 1.729 ++ movb $0x2e, %al /* 0x2e = . */ 1.730 ++ call print_char 1.731 ++ popw %bp 1.732 ++ popw %bx 1.733 ++ popw %ax 1.734 ++ 1.735 ++ movw sread, %cx 1.736 ++ incw %cx 1.737 ++ movb track, %ch 1.738 ++ movw $0x0100, %dx 1.739 ++ andb head, %dh 1.740 ++ movb $2, %ah 1.741 ++ 1.742 ++ pushw %dx /* save for error dump */ 1.743 ++ pushw %cx 1.744 ++ pushw %bx 1.745 ++ pushw %ax 1.746 ++ 1.747 ++ int $0x13 1.748 ++ jc bad_rt 1.749 ++ addw $8, %sp 1.750 ++ popa /* 80186 opcode */ 1.751 ++ ret 1.752 ++ 1.753 ++bad_rt: pushw %ax /* save error code */ 1.754 ++ call print_all /* ah = error, al = read */ 1.755 ++ 1.756 ++ xorb %ah,%ah 1.757 ++ xorb %dl,%dl 1.758 ++ int $0x13 1.759 ++ 1.760 ++ addw $10, %sp 1.761 ++ popa /* 80186 opcode */ 1.762 ++ jmp read_track 1.763 ++ 1.764 ++/* print_all is for debugging purposes. It will print out all of the registers. 1.765 ++ * The assumption is that this is called from a routine, with a stack frame like 1.766 ++ * dx 1.767 ++ * cx 1.768 ++ * bx 1.769 ++ * ax 1.770 ++ * error 1.771 ++ * ret <- sp 1.772 ++ */ 1.773 ++ 1.774 ++print_all: 1.775 ++ call print_nl /* nl for readability */ 1.776 ++ /* print_nl update ah and bx */ 1.777 ++ movw $5, %cx /* error code + 4 registers */ 1.778 ++ movw %sp,%bp 1.779 ++ 1.780 ++print_loop: 1.781 ++ pushw %cx /* save count left */ 1.782 ++ 1.783 ++ cmpb $5, %cl 1.784 ++ jae no_reg /* see if register name is needed */ 1.785 ++ 1.786 ++ movb $0x5+0x41-1, %al 1.787 ++ subb %cl,%al 1.788 + int $0x10 1.789 ++ 1.790 ++ movb $0x58, %al /* 'X' */ 1.791 ++ int $0x10 1.792 ++ 1.793 ++ movb $0x3A, %al /* ':' */ 1.794 ++ int $0x10 1.795 ++ 1.796 ++no_reg: 1.797 ++ addw $2, %bp /* next register */ 1.798 ++ call print_hex /* print it */ 1.799 ++ movb $0x20, %al /* print a space */ 1.800 ++ int $0x10 1.801 ++ popw %cx 1.802 ++ loop print_loop 1.803 ++ /* nl for readability */ 1.804 ++print_nl: 1.805 ++ movb $0xd, %al /* CR */ 1.806 ++ call print_char 1.807 ++ movb $0xa, %al /* LF */ 1.808 ++ jmp print_char 1.809 ++ 1.810 ++ 1.811 ++print_str: 1.812 ++prloop: 1.813 ++ lodsb 1.814 ++ call print_char 1.815 + loop prloop 1.816 +-freeze: jmp freeze 1.817 ++ ret 1.818 + 1.819 +-why: .ascii "This image cannot be loaded from a floppy disk.\r\n" 1.820 +-why_end: 1.821 ++/* print_hex prints the word pointed to by ss:bp in hexadecimal. */ 1.822 ++ 1.823 ++print_hex: 1.824 ++ movw (%bp),%dx /* load word into dx */ 1.825 ++ movb $4, %cl 1.826 ++ call print_2digits 1.827 ++print_2digits: 1.828 ++ call print_digit 1.829 ++/* fall through */ 1.830 ++print_digit: 1.831 ++ rol %cl,%dx /* rotate to use lowest 4 bits */ 1.832 ++ movb $0x0f, %al /* mask for nybble */ 1.833 ++ andb %dl,%al 1.834 ++ addb $0x90, %al /* convert al to ascii hex */ 1.835 ++ daa /* (four instructions) */ 1.836 ++ adcb $0x40, %al 1.837 ++ daa 1.838 ++print_char: 1.839 ++ movb $0x0e, %ah /* write char, tty mode */ 1.840 ++ movw $0x0007, %bx /* page 0, attribute 7 (normal) */ 1.841 ++ int $0x10 1.842 ++ ret 1.843 + 1.844 ++sread: .word 0 /* sectors read of current track */ 1.845 ++head: .word 0 /* current head */ 1.846 ++track: .word 0 /* current track */ 1.847 ++ 1.848 ++sectors: 1.849 ++ .word 0 1.850 ++ 1.851 ++dpseg: .word 0 1.852 ++dpoff: .word 0 1.853 ++ 1.854 ++disksizes: 1.855 ++ .byte 36,18,15,9,0 1.856 ++ 1.857 ++msg1: 1.858 ++ .ascii "Loading ROM image" 1.859 ++msg1end: 1.860 + 1.861 + .org 497 1.862 + setup_sects: