Date: Sun, 10 Nov 1996 00:19:55 +0100 From: Tor Egge <Tor.Egge@idt.ntnu.no> To: 100120.3121@compuserve.com Cc: freebsd-stable@freebsd.org, freebsd-current@freebsd.org Subject: Re: Follow on Atlantis board Message-ID: <199611092319.AAA04767@pat.idt.unit.no> In-Reply-To: Your message of "09 Nov 96 15:08:34 EST" References: <961109200834_100120.3121_EHQ22-1@CompuServe.COM>
next in thread | previous in thread | raw e-mail | index | archive | help
[ cc-ed to freebsd-current due to boot blocks in -current still being oversensitive to bios quirks ] > Some more info: > > in start.S (called immediately after booteasy passes control?) we added a > > mov $0x0080, %edx > > so the code looks like: > > /* bootstrap passes us drive number in %dl */ > mov $0x0080, %edx > cmpb $0x80, %dl > data32 > jae hd > > However in boot() in boot.c drive is still 0x333b. > > After that we removed this line, and added it to the last lines of boot2.S: > > mov $0x0080, %edx > movzbl %dl, %edx /* discard head (%dh) and random high bits */ > pushl %edx > call EXT(boot) > > Still in boot() drive was 0x333b... I thought i went crazy. > > Next we added a printf(drive) immediately after the boot() int ret with the > above patch intact. We also had a printf before the dosdev = drive; line. Now > the first printf showed 0x0080, but the 2nd was 0x333b. > > It seemed boot() was screwing up the stack somehow?? After some printf's > the following line screws the stack: > > for(ret = 0; ret < N_BIOS_GEOM; ret ++) > bootinfo.bi_bios_geom[ret] = get_diskinfo(ret + 0x80); > > I think it's get_diskinfo. But get_diskinfo seems too difficult for me to > investigate. Maybe some FreeBSD boot guru has an idea? I'm not a FreeBSD boot guru, but I've had similar problems using NetBSD boot blocks, due to a combination of the bios not preserving the upper 16 bits in registers, and the boot blocks not saving/restoring the correct registers in the routines calling bios. When using gdb on /usr/obj/usr/src/sys/i386/boot/biosboot/boot in FreeBSD 3.0-current and disassembling the boot function, you'll see that early in the function, the boot device is placed in %edi. The compiler correctly (according to the calling conventions) assumes that %edi is not modified by any routine called. Both memsize() and get_diskinfo() are called before the content of %edi is saved in the dosdev variable. They have a good chance of stomping upon the contents of %edi on some bioses. FreeBSD is not alone with these problems: I have a 486 with a DC-2000VL IDE controller that runs NetBSD 1.2 behind me. Standard NetBSD 1.2 boot blocks just freezes, when loading a kernel from the IDE drive. Loading the same kernel from a floppy with the same boot blocks works. Saving/restoring the appropiate registers in the routines that calls bios and changing prot_to_real to use ljmp instead of lret caused all these problems to disappear. Cut from /usr/src/contrib/gcc/config/i386/i386.h: ---- /* 1 for registers not available across function calls. These must include the FIXED_REGISTERS and also any registers that can be used without being saved. The latter must include the registers where values are returned and the register where structure-value addresses are passed. Aside from that, you can include as many other registers as you like. */ #define CALL_USED_REGISTERS \ /*ax,dx,cx,bx,si,di,bp,sp,st,st1,st2,st3,st4,st5,st6,st7,arg*/ \ { 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } ---- This means that it's OK to clobber most registers except %ebx, %esi, %edi and %ebp. (%eax is a special case, it may contain a return value). Thus, I recommend a patch similar to this one (which is for FreeBSD 3.0-current): Index: asm.S =================================================================== RCS file: /export/akg1/cvs/src/sys/i386/boot/biosboot/asm.S,v retrieving revision 1.9 diff -u -r1.9 asm.S --- asm.S 1996/03/08 07:27:52 1.9 +++ asm.S 1996/11/09 21:28:48 @@ -221,7 +221,6 @@ push %es push %esi push %edi - push %ecx cld @@ -236,7 +235,6 @@ rep stosb - pop %ecx pop %edi pop %esi pop %es @@ -254,7 +252,6 @@ push %es push %esi push %edi - push %ecx cld @@ -269,7 +266,6 @@ rep movsb - pop %ecx pop %edi pop %esi pop %es Index: bios.S =================================================================== RCS file: /export/akg1/cvs/src/sys/i386/boot/biosboot/bios.S,v retrieving revision 1.5 diff -u -r1.5 bios.S --- bios.S 1995/09/03 05:36:13 1.5 +++ bios.S 1996/11/09 21:33:29 @@ -75,8 +75,8 @@ mov %esp, %ebp push %ebx - push %ecx - push %edx + push %esi + push %edi push %es movb 0x10(%ebp), %dh @@ -110,8 +110,8 @@ movb %bh, %al /* return value in %ax */ pop %es - pop %edx - pop %ecx + pop %edi + pop %esi pop %ebx pop %ebp @@ -132,7 +132,8 @@ push %ebp mov %esp, %ebp push %ebx - push %ecx + push %esi + push %edi movb 0x8(%ebp), %cl @@ -149,7 +150,8 @@ data32 call EXT(real_to_prot) - pop %ecx + pop %edi + pop %esi pop %ebx pop %ebp ret @@ -167,6 +169,8 @@ push %ebp mov %esp, %ebp push %ebx /* save %ebx */ + push %esi + push %edi call EXT(prot_to_real) @@ -183,6 +187,8 @@ xor %eax, %eax movb %bl, %al + pop %edi + pop %esi pop %ebx pop %ebp ret @@ -203,6 +209,8 @@ push %ebp mov %esp, %ebp push %ebx + push %esi + push %edi call EXT(prot_to_real) /* enter real mode */ @@ -222,6 +230,8 @@ xor %eax, %eax movb %bl, %al + pop %edi + pop %esi pop %ebx pop %ebp ret @@ -238,8 +248,8 @@ mov %esp, %ebp push %es push %ebx - push %ecx - push %edx + push %esi + push %edi movb 0x8(%ebp), %dl /* diskinfo(drive #) */ call EXT(prot_to_real) /* enter real mode */ @@ -288,8 +298,8 @@ andb $0x3f, %cl /* mask of cylinder gunk */ movb %cl, %al /* max sector (and # sectors) */ - pop %edx - pop %ecx + pop %edi + pop %esi pop %ebx pop %es pop %ebp @@ -309,6 +319,8 @@ push %ebp mov %esp, %ebp push %ebx + push %esi + push %edi mov 8(%ebp), %ebx @@ -336,6 +348,8 @@ call EXT(real_to_prot) mov %ebx, %eax + pop %edi + pop %esi pop %ebx pop %ebp ret -------- - Tor Egge
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199611092319.AAA04767>