[OpenBIOS] SOLVED: the mystery of Solaris on SPARC32 and the missing Forth arguments

Mark Cave-Ayland mark.cave-ayland at siriusit.co.uk
Mon Oct 18 14:46:38 CEST 2010

Hi folks,

So I thought it may be interesting over the weekend to take a look and 
see how Solaris on SPARC32 is looking at the moment, and found that I 
was getting about as far as Artyom was, i.e. ufsboot dies after emitting 
this cryptic Forth statement with missing parameters:

['] find-device catch if 2drop true else current-device device-end then 
swap l!

With gdb primed with a breakpoint set at obp_fortheval_v2() I was able 
to poke around and see what was happening at the time the call into 
OpenBIOS was being made. Nothing interesting there. But jumping back a 
frame showed some extra information being set in the o registers:

(gdb) bt
#0  obp_fortheval_v2 (str=0x1190d0 " ['] find-device catch if 2drop true 
else current-device device-end then swap l!")
     at ../arch/sparc32/romvec.c:424
#1  0x00113dd4 in ?? ()
#2  0x00113dd4 in ?? ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
(gdb) frame 1
#1  0x00113dd4 in ?? ()
(gdb) info regi
o0             0x1190d0 1151184
o1             0x49     73
o2             0x1335c0 1258944
o3             0x130794 1247124
o4             0x0      0
o5             0x0      0

Okay; so let's take a look at what's in these o registers:

(gdb) x/1s 0x1190d0
0x1190d0:        " ['] find-device catch if 2drop true else 
current-device device-end then swap l!"
(gdb) x/1s 0x1335c0
"/iommu at 0,10000000/sbus at 0,10001000/espdma at 5,8400000/esp at 5,8800000/sd at 2,0:d"
(gdb) x/4xb 0x130794
0x130794:       0xff    0xff    0xff    0xff

Bingo! The missing parameters! Stepping back to just before where the 
code is invoked, I see this:

0x00113dac:     sethi  %hi(0x118c00), %g2
0x00113db0:     mov  %i0, %o0
0x00113db4:     ld  [ %g2 + 0xa0 ], %g2
0x00113db8:     mov  %l2, %o1
0x00113dbc:     mov  %l1, %o2
0x00113dc0:     mov  %i2, %o3
0x00113dc4:     mov  %i4, %o4
0x00113dc8:     ld  [ %g2 + 0x7c ], %l0
0x00113dcc:     call  %l0
0x00113dd0:     mov  %i5, %o5

So this makes it appear as if %o0 to %o5 are all set in preparation for 
the romvec call. Now minus the actual Forth string (actually a cstr), if 
the other values were pushed onto the stack in reverse order then it 
appears that this code would it is supposed to.

There is one Forth call in the traces that only takes 1 parameter, but 
there doesn't seem to be a way of passing the number of arguments into 
the romvec call. However, based on looking at the traces, starting with 
the first non-zero value in the highest o register and then pushing all 
the lower o register values onto the Forth stack before execution should 
give the correct result.

On the basis of this, I'd like to suggest the following proposal:

1) Change the signature of obp_fortheval_v2() from:

static void obp_fortheval_v2(char *str)


static void obp_fortheval_v2(char *str, int arg0, int arg1, int arg2, 
int arg3, int arg4)

2) Add code to obp_fortheval_v2 that starting from arg4 and working down 
to arg0, finds the first non-zero value and then pushes all remaining 
values argN down to arg0 onto the Forth stack before executing the Forth 

Does this sound reasonable? I'm surprised that one else has realised 
that the obp_fortheval_v2 function signature was wrong, but I guess it 
probably hardly gets used for anything these days.

As a separate hack, the equivalent of the OpenBOOT current-device word 
in OpenBIOS is active-package. So we should probably create an OpenBIOS 
variable called current-device too, and set its value to -1 when the 
function is entered. Then after all Forth has been evaluated, if it's 
value has changed from before the Forth call was made then set 
active-package to the new value before exit.



Mark Cave-Ayland - Senior Technical Architect
PostgreSQL - PostGIS
Sirius Corporation plc - control through freedom
t: +44 870 608 0063

Sirius Labs: http://www.siriusit.co.uk/labs

More information about the OpenBIOS mailing list