Contents

Suspending

To suspend the system, the Vita saves the current context into a buffer and sends it to the syscon. Then it issues a syscon request to enter the low-power state.

Context Buffer

Offset

Size

Description

0x0

0x4

Size of buffer (0x68)

0x4

0x4

Same as unk field of syscon_reset_device call

0x8

0x4

Some virtual address of buffer (unused?)

0xC

0x4

Virtual address of resume function with the following args:

(u32TTBR1,u32CONTEXTIDR,u32DACR)

0x10

0x4

Saved SCTLR

0x14

0x4

Saved ACTLR

0x18

0x4

Saved CPACR

0x1C

0x4

Saved TTBR0

0x20

0x4

Saved TTBR1

0x24

0x4

Saved TTBCR

0x28

0x4

Saved DACR

0x2C

0x4

Saved PRRR

0x30

0x4

Saved NMRR

0x34

0x4

Saved VBAR

0x38

0x4

Saved CONTEXTIDR

0x3C

0x4

Saved TPIDRURW

0x40

0x4

Saved TPIDRURO

0x44

0x4

Saved TPIDRPRW

0x48

0x18

Unknown/unused

0x60

0x8

System time

Saving Context

The context buffer defined above is built and the physical address of the buffer is sent to the Syscon with command 12. It calls Send command with syscon_send_command(12, &paddr, 4). Then it issues the command to suspend the device.

Resuming

Upon power up, the Boot Sequence is the same until the point where the secure kernel loader would jump into the non-secure kernel loader at 0x51000000. Instead, it copies the context resume function to the scratch buffer at 0x1F000000 and the context buffer to 0x1F001000. The resume function clears the caches and then enables the MMU. Next, it uses the context buffer to restore CP15 registers that were saved. On 1.69, it does not seem to restore ACTLR, TTBR1, or DACR. After the CP15 registers are restored, the translation tables should be restored and it then calls the resume function.

Rebooting with Patches

By abusing the way resume works, we can reboot the device into a custom firmware by patching the non-secure kernel loader. The general framework to do this is: first, patch the kernel loader in RAM to accept unsigned SELFs and load a custom kprx after psp2bootconfig.skprx. It could be the case that by the time your exploit runs the DRAM region containing the kernel loader has been wiped/reused. If so, you must use a lower level exploit to dump the loader. It may even be possible to dump the compressed version, in that case you wouldn't even need to perform cleanup. Your custom krpx will be loaded after the bare essential kernel libraries are loaded (memory management, threads, file IO, etc) and it can then patch the full module loader to accept unsigned SELFs as well as any other patches.

Cleaning up Bootloader

Ideally, if we can get the original compressed version of the non-secure bootloader that is extracted from kernel_boot_loader.self, we can load that to memory and jump to it from our resume function. However, by the time the system is in a state we control, usually that data would be corrupted. What we are left with is the non-secure kernel loader in the state after bootup is completed. In order to get it to run successfully again in our resume function, we need to clean up the data it uses.