Talk:Undocumented SPU Channels: Difference between revisions

From PS3 Developer wiki
Jump to navigation Jump to search
mNo edit summary
No edit summary
Line 63: Line 63:


* spu_rdchcnt() returns 1 on the following channels: 64, 69, 70, 71, 74, but 0 on 73, why?
* spu_rdchcnt() returns 1 on the following channels: 64, 69, 70, 71, 74, but 0 on 73, why?
* How many other undocumented channels exists? is there any possibility to determine if specific channel exists?
* How many other undocumented channels exists? Is there any possibility to determine if specific channel exists?
* What is the purpose of other undocumented channels? h/w decryption facility? validation? something else?
* What is the purpose of other undocumented channels? H/W decryption facility? Validation? Something else?
* Is it possible to refill config ring storage?
* Is it possible to refill config ring storage?
== Utility functions for channel fuzzing ==
<syntaxhighlight lang="c">
uint32_t get_channel_count(uint32_t n) {
static uint32_t f[] __attribute__ ((aligned(16))) = {
0x01E00003, // rchcnt $3, $ch(?)
0x35000000, // bi $LR
0x4020007F, // lnop
};
f[0] &= ~(0x7F << 7);
f[0] |= (n & 0x7F) << 7;
uint32_t (* pf)(void) = (void*)&f;
si_sync();
return pf();
}
uint32_t read_channel(uint32_t n) {
static uint32_t f[] __attribute__ ((aligned(16))) = {
0x01A00003, // rdch $3, $ch(?)
0x35000000, // bi $LR
0x4020007F, // lnop
};
f[0] &= ~(0x7F << 7);
f[0] |= (n & 0x7F) << 7;
uint32_t (* pf)(void) = (void*)&f;
si_sync();
return pf();
}
void write_channel(uint32_t n, uint32_t value) {
static uint32_t f[] __attribute__ ((aligned(16))) = {
0x21A00003, // wrch $ch(?), $3
0x35000000, // bi $LR
0x4020007F, // lnop
};
f[0] &= ~(0x7F << 7);
f[0] |= (n & 0x7F) << 7;
void (* pf)(uint32_t) = (void*)&f;
si_sync();
pf(value);
}
</syntaxhighlight>

Revision as of 21:37, 25 July 2014

Channel 67

Used to get the config ring.

Use is similar to channel 73.


uint8_t expectedConfigRing65[];
uint8_t expectedConfigRing90[];
   
function _start+1340() { //extracted from bootloader on 0x1A datecode console
   
    uint64_t vr = getSPU_VR(); //First active SPE priv1 SPU_VR register
    uint32_t toIgnore;
    uint32_t toRead;
    uint8_t expectedConfigRing;
    uint8_t readedConfigRing[];
    switch (vr) {
        case 0x201:
        case 0x202:
            //90nm console
            toIgnore = 0xA6;
            toRead = 0x156;
            expectedConfigRing = expectedConfigRing90;
            break;
        default:
            //65nm console
            toIgnore = 0xBB;
            toRead = 0x152;
            expectedConfigRing = expectedConfigRing90;
    }
    unsigned int index;
    for (index = 0; index < toIgnore>>3; index++) {
        rdch(67);
    }
    for (index = 0; index < toRead; index++) {
        readedConfigRing[index] = rdch(67) & 0xFF;
    }
    while (moreBitFieldsToCheck) {
        checkConfigRingField(expectedConfigRing, readedConfigRing, field, .....);
    }
   
}

Channel 64

Used to control isolation-mode persistent storage (w:ch72/r:ch73) and probably config ring storage (r:ch67).

Other values written to channel 64 (on bootldr): 0x00, 0x02, 0x20000

Isolation-mode control flags

  • 0x0 : clear config ring storage?
  • 0x2 : kill spe and exit isolation mode
  • (0x1 | 0x2) = 0x3 : cause spe stall (while waiting for blocking channel with mailbox interrupt)?
  • 0x10000 : reset persistent storage r/w index (writes to ch72 and reads from ch73 will start at index zero)
  • 0x20000 : lock persistent storage write
  • 0x40000 : lock persistent storage read
  • (0x20000 | 0x40000) = 0x60000 : lock persistent storage r/w (reading from ch73 will return zero as long as the current isolated session lasts)

Some observations and questions

  • spu_rdchcnt() returns 1 on the following channels: 64, 69, 70, 71, 74, but 0 on 73, why?
  • How many other undocumented channels exists? Is there any possibility to determine if specific channel exists?
  • What is the purpose of other undocumented channels? H/W decryption facility? Validation? Something else?
  • Is it possible to refill config ring storage?

Utility functions for channel fuzzing

uint32_t get_channel_count(uint32_t n) {
	static uint32_t f[] __attribute__ ((aligned(16))) = {
		0x01E00003, // rchcnt $3, $ch(?)
		0x35000000, // bi $LR
		0x4020007F, // lnop
	};
	f[0] &= ~(0x7F << 7);
	f[0] |= (n & 0x7F) << 7;
	uint32_t (* pf)(void) = (void*)&f;
	si_sync();
	return pf();
}

uint32_t read_channel(uint32_t n) {
	static uint32_t f[] __attribute__ ((aligned(16))) = {
		0x01A00003, // rdch $3, $ch(?)
		0x35000000, // bi $LR
		0x4020007F, // lnop
	};
	f[0] &= ~(0x7F << 7);
	f[0] |= (n & 0x7F) << 7;
	uint32_t (* pf)(void) = (void*)&f;
	si_sync();
	return pf();
}

void write_channel(uint32_t n, uint32_t value) {
	static uint32_t f[] __attribute__ ((aligned(16))) = {
		0x21A00003, // wrch $ch(?), $3
		0x35000000, // bi $LR
		0x4020007F, // lnop
	};
	f[0] &= ~(0x7F << 7);
	f[0] |= (n & 0x7F) << 7;
	void (* pf)(uint32_t) = (void*)&f;
	si_sync();
	pf(value);
}