[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
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
(gdb)
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)
to:
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
string.
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.
ATB,
Mark.
--
Mark Cave-Ayland - Senior Technical Architect
PostgreSQL - PostGIS
Sirius Corporation plc - control through freedom
http://www.siriusit.co.uk
t: +44 870 608 0063
Sirius Labs: http://www.siriusit.co.uk/labs
More information about the OpenBIOS
mailing list