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@0,10000000/sbus@0,10001000/espdma@5,8400000/esp@5,8800000/sd@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.