Skip site navigation (1)Skip section navigation (2)
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>