ReadAs

From Vita Development Wiki
Revision as of 21:11, 9 October 2024 by CreepNT (talk | contribs) (→‎Control register: Update bits 15:7 description)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

ReadAs is a functionality provided by an unknown device special device used to perform "arbitrary" bus transactions?

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 memory map.

Registers

Location

The ReadAs MMIO interface is located at physical address 0xE0020040.

Structure

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

Control register

The control register is used to configure ReadAs. Writing to the control register starts the ReadAs operation.

Bit(s) Description
0 Operation type (0: Read - 1: Write)
2:1 ? (maybe IA selection)
6:3 Bytes enable (Bit 6/5/4/3 => byte 3/2/1/0 in LE order)

Controls which bytes are read/write at target address.

(bit 5 sometimes also control whether read is aligned to 0x10 or not)

15:7 MReqInfo<15:7>
24:16 ?
30:25 Bus Master ID (impersonated for access)
31 RAZ/WI (maybe BUSY?)

Usage example

#define READAS_REG 0xE0020040 // readas32 device

#define READAS_MODE_READ  0x0
#define READAS_MODE_WRITE 0x1

#define READAS_DEV_S   (0x0 << 1) // default secure
#define READAS_DEV_UNK (0x1 << 1) // masks DRAM and DRAM regs, from ARM bus
#define READAS_DEV_NS  (0x2 << 1) // non-secure

// below options only apply to write mode and some offsets in read mode
#define READAS_BE_0 (0x1 << 3) //enable byte 0 (LSB)
#define READAS_BE_1 (0x2 << 3) //enable byte 1 - or READAS_NOALIGN in incompatible read offsets
#define READAS_BE_2 (0x4 << 3) //enable byte 2
#define READAS_BE_3 (0x8 << 3) //enable byte 3 (MSB)

#define READAS_BUS_MASTER(x) (((x) & 0x3Fu) << 25)

typedef struct {
    unsigned int addr;
    unsigned int val;
    unsigned int ctrl;
} __attribute__((packed)) e002_readas32;

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

// read from [addr] with configuration [cfg]
static u32_t readAs(u32_t addr, u32_t cfg) {
    READAS32->addr = addr;
    READAS32->val = 0xDEADBABE;
    READAS32->ctrl = (cfg & ~READAS_MODE_WRITE);
    while (READAS32->val == 0xDEADBABE) {} // wait until READAS replies
    return READAS32->val;
}

// write [data] to [addr] with configuration [cfg]
static void writeAs(u32_t addr, u32_t data, u32_t cfg) {
    READAS32->addr = addr;
    READAS32->val = data;
    READAS32->ctrl = (cfg | READAS_MODE_WRITE);
}

Ranges

Results after a full memcmp:

- mode 0 (READAS_DEV_S) 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 (READAS_DEV_UNK) 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 (READAS_DEV_NS) 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

  • On SoC v3.2+ 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 also zeroed (both in type 1 and type 8 cmep reset).