My memory didn't work well. It's not as simple as a command that allows to write anywhere. It's an interrupt with interesting settings done just before firing it. And this mechanism assumes an interrupt handler has been set by Hypervisor for his own needs (but we assume altering push buffer was not expected by Sony and so, no heavy protection is set, yet, to prevent us from using this interrupt handler for our own nasty goals...)
You could write to any register, on xbox1 (nv2a) by taking advantage of a specific interrupt you could fire with command
#define NV20_TCL_PRIMITIVE_3D_FIRE_INTERRUPT 0x00000100
(0x100 is considered a "trapped address" by NVidia miniport driver)
with data=0x320 (in order to identify what treatment should be done, inside the interrupt handler)
Extract from pbKit.c (interrupt handler) :
Code: Select all
static void pb_subprog(DWORD subprogID, DWORD paramA, DWORD paramB)
{
//inner registers 0x1D8C & 0x1D90 match 2 outer registers :
//[0x1D8C]=[NV20_TCL_PRIMITIVE_3D_PARAMETER_A]=VIDEOREG(NV_PGRAPH_PARAMETER_A)=[0xFD401A88]
//[0x1D90]=[NV20_TCL_PRIMITIVE_3D_PARAMETER_B]=VIDEOREG(NV_PGRAPH_PARAMETER_B)=[0xFD40186C]
//so they can be used by a push buffer sequence to set parameters
//before triggering a subprogram by the command 0x0100 which will
//throw an interrupt and have CPU execute its code right here.
//Here just test the subprogID value and execute your own subprogram
//associated code (avoid using subprogID=0, it seems to be reserved)
int next;
switch(subprogID)
{
case PB_SETOUTER: //sets an outer register
VIDEOREG(paramA)=paramB;
break;
The exact same code exists in xbox1 miniport driver...
(triggered by 0x320 value)
Before triggering the copy (register #paramA <= value ParamB), you need, of course, to set a value for paramA and paramB. And here comes a tasty secret : Two inner registers (you can set only with push buffer commands) are physically linked to two outer registers (mmio registers).
So, in order to set any value anywhere you would enqueue this :
Code: Select all
pb_push1(p,NV20_TCL_PRIMITIVE_3D_PARAMETER_A,dest_reg); p+=2;
pb_push1(p,NV20_TCL_PRIMITIVE_3D_PARAMETER_B,value); p+=2;
pb_push1(p,NV20_TCL_PRIMITIVE_3D_FIRE_INTERRUPT,PB_SETOUTER); p+=2; //subprogID PB_SETOUTER: set a value in dest_reg
Let's assume hypervisor handles such interrupts and have a set of prepared treatments depending on the data following 0x100 command...
(I don't know well chipsets>nv20, so I'm just refering nv20 values as ex.)
One of these treatments may be that : write something anywhere
(with HV's priviledges!)
Ok, it's a naive dream... But accessing HV's push buffer was one too...