3 /* NOTE: this boot sector contains instructions that need at least an 80186.
4 * Yes, as86 has a bug somewhere in the valid instruction set checks.
6 * SYS_SIZE is the number of clicks (16 bytes) to be loaded.
8 .equ SYSSIZE, 8192 # 8192 * 16 bytes = 128kB maximum size of .ROM file
10 /* floppyload.S Copyright (C) 1991, 1992 Linus Torvalds
11 * modified by Drew Eckhardt
12 * modified by Bruce Evans (bde)
14 * floppyprefix.S is loaded at 0x0000:0x7c00 by the bios-startup routines.
16 * It then loads the system at SYSSEG<<4, using BIOS interrupts.
18 * The loader has been made as simple as possible, and continuous read errors
19 * will result in a unbreakable loop. Reboot by hand. It loads pretty fast by
20 * getting whole tracks at a time whenever possible.
23 .equ BOOTSEG, 0x07C0 /* original address of boot-sector */
25 .equ SYSSEG, 0x1000 /* system loaded at SYSSEG<<4 */
30 .section ".prefix", "ax", @progbits
33 jmp $BOOTSEG, $go /* reload cs:ip to match relocation addr */
35 movw $0x2000-12, %di /* 0x2000 is arbitrary value >= length */
36 /* of bootsect + room for stack + 12 for */
37 /* saved disk parm block */
42 movw %ax,%ss /* put stack at BOOTSEG:0x4000-12. */
45 /* Many BIOS's default disk parameter tables will not recognize multi-sector
46 * reads beyond the maximum sector number specified in the default diskette
47 * parameter tables - this may mean 7 sectors in some cases.
49 * Since single sector reads are slow and out of the question, we must take care
50 * of this by creating new parameter tables (for the first disk) in RAM. We
51 * will set the maximum sector count to 36 - the most we will encounter on an
52 * ED 2.88. High doesn't hurt. Low does.
54 * Segments are as follows: ds=es=ss=cs - BOOTSEG
58 movw %cx,%es /* access segment 0 */
59 movw $0x78, %bx /* 0:bx is parameter table address */
60 pushw %ds /* save ds */
61 /* 0:bx is parameter table address */
62 ldsw %es:(%bx),%si /* loads ds and si */
64 movw %ax,%es /* ax is BOOTSECT (loaded above) */
65 movb $6, %cl /* copy 12 bytes */
67 pushw %di /* keep a copy for later */
69 movsw /* ds:si is source, es:di is dest */
74 movw %cx,%ds /* access segment 0 */
78 popw %ds /* restore ds */
79 movw %di, dpoff /* save old parameters */
80 movw %si, dpseg /* to restore just before finishing */
82 popw %es /* reload es */
84 /* Note that es is already set up. Also cx is 0 from rep movsw above. */
86 xorb %ah,%ah /* reset FDC */
90 /* Get disk drive parameters, specifically number of sectors/track.
92 * It seems that there is no BIOS call to get the number of sectors. Guess
93 * 36 sectors if sector 36 can be read, 18 sectors if sector 18 can be read,
94 * 15 if sector 15 can be read. Otherwise guess 9.
97 movw $disksizes, %si /* table of sizes to try */
101 cbtw /* extend to word */
103 cmpw $disksizes+4, %si
104 jae got_sectors /* if all else fails, try 9 */
105 xchgw %cx,%ax /* cx = track and sector */
106 xorw %dx,%dx /* drive 0, head 0 */
107 movw $0x0200, %bx /* address after boot sector */
108 /* (512 bytes from origin, es = cs) */
109 movw $0x0201, %ax /* service 2, 1 sector */
111 jc probe_loop /* try next value */
114 movw $msg1end-msg1, %cx
118 /* ok, we've written the Loading... message, now we want to load the system */
121 movw %ax,%es /* segment of SYSSEG<<4 */
125 /* This turns off the floppy drive motor, so that we enter the kernel in a
126 * known state, and don't have to worry about it later.
133 pop %es /* = SYSSEG */
135 /* Restore original disk parameters */
144 /* Everything now loaded. %es = SYSSEG, so %es:0000 points to
145 * start of loaded image.
151 /* Decompress runtime image. %es:0000 points to decompressed
154 lcall $SYSSEG, $decompress16
157 /* Set up internal environment. Address of entry-point
158 * function is returned in %es:di.
160 pushw %es /* setup16 says %ds:0000 must point to image */
166 /* Call to arch_main. Register INT19 as an exit path. This
167 * call will never return.
169 movl $exit_via_int19, %eax
171 pushl %eax /* Dummy return address */
173 /* Do the equivalent of ljmp *%es:di */
179 /* This routine loads the system at address SYSSEG<<4, making sure no 64kB
180 * boundaries are crossed. We try to load it as fast as possible, loading whole
181 * tracks whenever we can.
183 * in: es - starting address segment (normally SYSSEG)
186 movw $1,sread /* don't reload the prefix */
189 die: jne die /* es must be at 64kB boundary */
190 xorw %bx,%bx /* bx is starting address within segment */
195 shrw %cl,%dx /* bx is always divisible by 16 */
197 cmpw $SYSSEG+SYSSIZE, %ax /* have we loaded all yet? */
239 pushw %bp /* just in case the BIOS is buggy */
240 movw $0x0e2e, %ax /* 0x2e = . */
256 pushw %dx /* save for error dump */
267 bad_rt: pushw %ax /* save error code */
268 call print_all /* ah = error, al = read */
278 /* print_all is for debugging purposes. It will print out all of the registers.
279 * The assumption is that this is called from a routine, with a stack frame like
289 call print_nl /* nl for readability */
290 movw $5, %cx /* error code + 4 registers */
294 pushw %cx /* save count left */
297 jae no_reg /* see if register name is needed */
299 movw $0x0007, %bx /* page 0, attribute 7 (normal) */
300 movw $0xe05+0x41-1, %ax
304 movb $0x58, %al /* 'X' */
307 movb $0x3A, %al /* ':' */
311 addw $2, %bp /* next register */
312 call print_hex /* print it */
313 movb $0x20, %al /* print a space */
317 call print_nl /* nl for readability */
321 movw $0x0007, %bx /* page 0, attribute 7 (normal) */
322 movb $0x0e, %ah /* write char, tty mode */
330 movw $0x0007, %bx /* page 0, attribute 7 (normal) */
331 movw $0xe0d, %ax /* CR */
333 movb $0xa, %al /* LF */
337 /* print_hex prints the word pointed to by ss:bp in hexadecimal. */
340 movw (%bp),%dx /* load word into dx */
342 movb $0x0e, %ah /* write char, tty mode */
343 movw $0x0007, %bx /* page 0, attribute 7 (normal) */
349 rol %cl,%dx /* rotate so that lowest 4 bits are used */
350 movb $0x0f, %al /* mask for nybble */
352 addb $0x90, %al /* convert al to ascii hex (four instructions) */
359 sread: .word 0 /* sectors read of current track */
360 head: .word 0 /* current head */
361 track: .word 0 /* current track */
373 .ascii "Loading ROM image"