ReadAs

From Vita Development Wiki

readAs is a special functionality provided by an unknown device.

It can be used to read/write data anywhere on the mapped memory. It is suspected to be a DMAC4 interface.

It is never accessed by any currently reverse-engineered code and is not referenced in any accessible memory map.

Configuration registers for cmep

Register Description
0xE0020040 Address
0xE0020044 Data (in/out)
0xE0020048 Mode

Modes

Mode is a bitfield. You can enable/disable some readAs features as well as change the used DMAC channel.

Bit Description
0 Write data to address
1 Mode 2 - Alternative Secure?
2 Mode 4 - Non-secure?
3 Read/Write address byte 0
4 R/W byte 1 and allow non-0x10-aligned address read
5 Read/Write address byte 2
6 Read/Write address byte 3
30 ?? hangs with bits 0 and 2

Observation: while write mode always respects bits 3-6, read mode seems to have a set of address ranges that always read all 4 bytes.

Usage example

#define READAS_REG 0xE0020040 // readas32 device

#define RAS_DEV_S 0 // default secure
#define RAS_MODE_WRITE 0b1 // write mode
#define RAS_DEV_UNK 0b10 // masks DRAM and DRAM regs, from arm bus
#define RAS_DEV_NS 0b100 // non-secure

// below options only apply to write mode and some offsets in read mode
#define RAS_B0 0b1000
#define RAS_B1 0b10000 // or RAS_NOALIGN in incompatible read offsets
#define RAS_B2 0b100000
#define RAS_B3 0b1000000
#define RAS_32 (RAS_B0 | RAS_B1 | RAS_B2 | RAS_B3)

typedef struct {
    unsigned int addr;
    unsigned int resp;
    unsigned int mode;
} __attribute__((packed)) e002_readas32;

static volatile e002_readas32* const READAS32 = (void*)READAS_REG;

// read from [addr] with mode [mode]
static u32_t readAs(u32_t addr, u32_t mode) {
    READAS32->addr = addr;
    READAS32->resp = 0xDEADBABE;
    READAS32->mode = mode;
    
    while (READAS32->resp == 0xDEADBABE) {} // wait until RAS replies
    
    return READAS32->resp;
}

// write to [addr] with mode [mode]
static void writeAs(u32_t addr, u32_t data, u32_t mode) {
    READAS32->addr = addr;
    READAS32->resp = data;
    READAS32->mode = mode | RAS_MODE_WRITE;
}

Ranges

Results after a full memcmp:

- mode 0 vs normal cmep read
--not available in mode 0:
0x00300000-0x00400000
0xE0000000-0xE0040000
0xE0058000-0xE0068000
0xE00C0000-0xE00D0000
0xE0100000-0xE0101000
0xE04D0000-0xE04DC000
0xE20A0000-0xE20B0000
0xE20C0000-0xE20D0000
0xE3110000-0xE3120000
0xE8000000-0xE8400000

- mode 2 vs 0
--not available in mode 2:
0x40000000-0xC0000000
0xE0400000-0xE0420000
0xE04E0000-0xE04E1000
0xE3000000-0xE3020000
0xE3101000-0xE3104000
0xE5000000-0xE5020000
0xE50C0000-0xE50D0000
0xE5880000-0xE6010000
0xEC340000-0xEC370000
0xED948000-0xED970000

- mode 4 vs mode 0
--not available in mode 0 (!)
0x00000000-0x00008000
0xE0100000-0xE0101000
0xE04D0000-0xE04DC000
0xE20A0000-0xE20B0000
0xE3110000-0xE3120000
--not available in mode 4:
0x00040000-0x00060000
0x00800000-0x00820000
0xE0000000-0xE0100000
0xEC000000-0xEE700000

Notes

  • All read modes can be disabled by writing 0x420 to physical address 0xE0010010.
  • This cmep device has been updated in PS Vita SoC rev 4 compared to rev 3.2. When cmep is reset the configuration is zeroed (both in type 1 and type 8 cmep reset).