BTX loader hangs after version info

John Baldwin jhb at freebsd.org
Fri May 23 22:11:18 UTC 2008


On Friday 23 May 2008 09:26:45 am Kostik Belousov wrote:
> On Fri, May 23, 2008 at 08:29:09AM -0400, John Baldwin wrote:
> > On Friday 23 May 2008 07:53:11 am Kostik Belousov wrote:
> > > On Fri, May 23, 2008 at 01:22:55PM +1200, Mark Kirkwood wrote:
> > > > James Seward wrote:
> > > > >Hello,
> > > > >
> > > > >Two days ago I csup'd my desktop at home, which was running RELENG_7
> > > > >from about 7.0-RELEASE time, to bring it up-to-date (still on
> > > > >RELENG_7). I followed my usual buildkernel/world procedure (the usual
> > > > >one) which has worked fine all the way since 5.x. After installing
> > > > >kernel and restarting in single user, it was working fine. However,
> > > > >following installworld it will not boot.
> > > > >
> > > > >It stops immediately after "BTX loader 1.00 BTX version 1.02", but
> > > > >with the cursor on the line *above* the first "B". Nothing futher
> > > > >happens, but the system responds to Ctrl-Alt-Del.
> > > > >
> > > > >I have managed to start it using the install CD and csup'd back to a
> > > > >version just before the commit to BTX that moved it to 1.02 (March
> > > > >18th, I think). However, that version too hangs after "BTX loader 1.00
> > > > >BTX version 1.01".
> > > > >
> > > > >My desktop is currently building RELENG_7_0 to see if that will work,
> > > > >but I won't know that until later as I'm at work and it is at home :)
> > > > >
> > > > >The install CD (BTX 1.00/1.01) boots fine. Nothing else changed on my
> > > > >system between the last successful boot and the unsuccessful one.
> > > > >
> > > > >Any suggestions/advice for what I can try next, or what I can do to
> > > > >help the troubleshooting process?
> > > > >
> > > > >My desktop is an Athlon64 but I am using i386, on an Asus A8V-E Deluxe
> > > > >board.
> > > >
> > > > FWIW - I am seeing this too, on a Supermicro P3TDDE. 7-STABLE src from
> > > > 28-Feb is fine, but Mar, Apr, May code all hangs after printing "loading
> > > > /boot/defaults/loader.conf" - presumably reading my /boot/loader.conf?
> > > >
> > > > Interestingly I can usually get it to boot by escaping to the loader
> > > > prompt and then just pressing return.
> > > >
> > > > Oddly some other machines (Supermicro P3TDER and Asus PRO31J Laptop)
> > > > behave normally with src from Mar->May.
> > > >
> > > > In all cases the canonical procedure from UPDATING was used (buildworld,
> > > > kernel, reboot single, mergemaster -p, installworld, delete-old,
> > > > mergemaster, reboot).
> > > >
> > > > I happy to help collect some debug info (how do you switch this on for
> > > > the loader?), tho the machine exhibiting the problem is my workstation
> > > > (of course)!
> > >
> > > Try to install new bootblock.
> > 
> > I would be wary of that as it might make things worse?  These problems are all 
> > from starting /boot/loader.  boot2 is still working fine and thus there is 
> > still the possiblity of using boot2 to load /boot/loader.old as a workaround.  
> > If you update boot2 and it breaks you can't fix that w/o booting off of some 
> > other media such as a CD.
> > 
> > Debugging these hangs is not easy to do remotely.  If you know assembly then 
> > there are some things you can play with.  For example, in the case where it 
> > hangs after printing out the BTX version (from btxldr.S) you could start 
> > adding debugging to btx.S to print out '.' characters in various places and 
> > see how many get printed out before it hangs.  However, doing this requires 
> > familiarity with assembly and is a lot easier with physical access to a box.
> 
> When I worked on my version of the realbtx, I sometimes experienced hangs when
> vm86 btx run before real-mode btx. I did not investigated it then, only noted
> the issue.
> 

Try this patch.  I'm not 100% certain this will fix it as I can't reproduce
the issue, but I think it might help.  Specifically, when the boot code makes
a v86 call, the loader/boot2/whatever swaps in/out a new set of registers via
the v86 structure including the eflags register.  However, none of the boot
programs actually initialized the v86 structure.   Thus, the BIOS routines
would start off running with whatever garbage was in v86.efl when each boot
program started.  This meant that we could end up invoking BIOS routines with
interrupts disabled, and I think this might explain a hard hang (if a BIOS
routine was waiting for an interrupt the interrupt would never fire).  The
patch fixes all the boot programs to initialize v86 to a better known state. 
At the least it sets v86.efl to a sane value (0x202) rather than random.  (The
random might have always been 0x0 BTW, not sure on that one.)

--- //depot/vendor/freebsd/src/sys/boot/i386/boot2/boot2.c	2008/02/28 17:10:57
+++ //depot/user/jhb/boot/sys/boot/i386/boot2/boot2.c	2008/05/23 21:59:59
@@ -24,6 +24,7 @@
 
 #include <machine/bootinfo.h>
 #include <machine/elf.h>
+#include <machine/psl.h>
 
 #include <stdarg.h>
 
@@ -83,8 +84,8 @@
 #define NDEV		3
 #define MEM_BASE	0x12
 #define MEM_EXT 	0x15
-#define V86_CY(x)	((x) & 1)
-#define V86_ZR(x)	((x) & 0x40)
+#define V86_CY(x)	((x) & PSL_C)
+#define V86_ZR(x)	((x) & PSL_Z)
 
 #define DRV_HARD	0x80
 #define DRV_MASK	0x7f
@@ -237,6 +238,7 @@
 
     dmadat = (void *)(roundup2(__base + (int32_t)&_end, 0x10000) - __base);
     v86.ctl = V86_FLAGS;
+    v86.efl = PSL_RESERVED_DEFAULT | PSL_I;
     dsk.drive = *(uint8_t *)PTOV(ARGS);
     dsk.type = dsk.drive & DRV_HARD ? TYPE_AD : TYPE_FD;
     dsk.unit = dsk.drive & DRV_MASK;
--- //depot/vendor/freebsd/src/sys/boot/i386/gptboot/gptboot.c	2008/02/28 17:10:57
+++ //depot/user/jhb/boot/sys/boot/i386/gptboot/gptboot.c	2008/05/23 21:59:59
@@ -23,6 +23,7 @@
 
 #include <machine/bootinfo.h>
 #include <machine/elf.h>
+#include <machine/psl.h>
 
 #include <stdarg.h>
 
@@ -81,8 +82,8 @@
 #define NDEV		3
 #define MEM_BASE	0x12
 #define MEM_EXT 	0x15
-#define V86_CY(x)	((x) & 1)
-#define V86_ZR(x)	((x) & 0x40)
+#define V86_CY(x)	((x) & PSL_C)
+#define V86_ZR(x)	((x) & PSL_Z)
 
 #define DRV_HARD	0x80
 #define DRV_MASK	0x7f
@@ -235,6 +236,7 @@
 
     dmadat = (void *)(roundup2(__base + (int32_t)&_end, 0x10000) - __base);
     v86.ctl = V86_FLAGS;
+    v86.efl = PSL_RESERVED_DEFAULT | PSL_I;
     dsk.drive = *(uint8_t *)PTOV(ARGS);
     dsk.type = dsk.drive & DRV_HARD ? TYPE_AD : TYPE_FD;
     dsk.unit = dsk.drive & DRV_MASK;
--- //depot/vendor/freebsd/src/sys/boot/i386/loader/main.c	2007/10/24 04:07:14
+++ //depot/user/jhb/boot/sys/boot/i386/loader/main.c	2008/05/23 21:59:59
@@ -35,6 +35,7 @@
 #include <stand.h>
 #include <string.h>
 #include <machine/bootinfo.h>
+#include <machine/psl.h>
 #include <sys/reboot.h>
 
 #include "bootstrap.h"
@@ -86,6 +87,10 @@
     initial_bootdev = kargs->bootdev;
     initial_bootinfo = kargs->bootinfo ? (struct bootinfo *)PTOV(kargs->bootinfo) : NULL;
 
+    /* Initialize the v86 register set to a known-good state. */
+    bzero(&v86, sizeof(v86));
+    v86.efl = PSL_RESERVED_DEFAULT | PSL_I;
+
     /* 
      * Initialise the heap as early as possible.  Once this is done, malloc() is usable.
      */
--- //depot/vendor/freebsd/src/sys/boot/pc98/loader/main.c	2007/10/24 11:57:58
+++ //depot/user/jhb/boot/sys/boot/pc98/loader/main.c	2008/05/23 22:03:45
@@ -35,6 +35,7 @@
 #include <stand.h>
 #include <string.h>
 #include <machine/bootinfo.h>
+#include <machine/psl.h>
 #include <sys/reboot.h>
 
 #include "bootstrap.h"
@@ -86,6 +87,10 @@
     initial_bootdev = kargs->bootdev;
     initial_bootinfo = kargs->bootinfo ? (struct bootinfo *)PTOV(kargs->bootinfo) : NULL;
 
+    /* Initialize the v86 register set to a known-good state. */
+    bzero(&v86, sizeof(v86));
+    v86.efl = PSL_RESERVED_DEFAULT | PSL_I;
+
     /* 
      * Initialise the heap as early as possible.  Once this is done, malloc() is usable.
      */

-- 
John Baldwin


More information about the freebsd-stable mailing list