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>
