Ernie: Difference between revisions
(→NVS) |
(→NVS) |
||
Line 477: | Line 477: | ||
|- | |- | ||
| 0x20 || 0x280 || SNVS Sectors || 19 XTS encrypted sectors of size 0x20 bytes handled by update_service_sm.self || "SpkgInfoUtilInitForUpdater" on FW 0.931 | | 0x20 || 0x280 || SNVS Sectors || 19 XTS encrypted sectors of size 0x20 bytes handled by update_service_sm.self || "SpkgInfoUtilInitForUpdater" on FW 0.931 | ||
|- | |||
| 0x20 || 0x20 || SNVS Sectors || AES-XTS encrypted sector. The system version info. || | |||
|- | |||
| 0x40 || 0x20 || SNVS Sectors || AES-XTS encrypted sector. The vita processor version info. Current fw, baryon version, unknown processor, factory fw. || | |||
|- | |||
| 0x60 || 0x20 || SNVS Sectors || AES-XTS encrypted sector. some flags || | |||
|- | |||
| 0xA0 || 0x20 || SNVS Sectors || AES-XTS encrypted sector. SLB2 sha256(act or ina). || | |||
|- | |||
| 0xC0 || 0x20 || SNVS Sectors || AES-XTS encrypted sector. SLB2 sha256(act or ina). || | |||
|- | |- | ||
| 0x2A0 || 0x20 || Qa Flag Version || 0x10 bytes data + 0x10 bytes AES128CMAC. If unused, 0xFFed. || "sceSblQafManagerSetQaFlagVersion" on FW 0.940 | | 0x2A0 || 0x20 || Qa Flag Version || 0x10 bytes data + 0x10 bytes AES128CMAC. If unused, 0xFFed. || "sceSblQafManagerSetQaFlagVersion" on FW 0.940 |
Revision as of 15:10, 4 April 2021
Ernie is the codename for the Syscon chip. The Syscon is for exemple responsible for handling button input (including power button), reading/writing to non-volatile storage (NVS) for storing system flags (mostly encrypted and signed). For example IDU flag is stored in NVS. Syscon is also responsible for maintaining the physical address to the resume buffer during Suspend. Communication between Kermit and Syscon is mainly through SPI (see SceSyscon) but there are also some GPIO pins connecting the two. The chip model is NEC/Renesas uPD79F0109
and is likely custom designed for Sony.
See also: Ernie Secure
Boot Process
The following is logged from boot. The timestamp is in seconds (the starting time is irrelevant). The arrow at the start indicates direction: '>' means Kermit to Syscon (MOSI) and '<' means Syscon to Kermit (MISO). Then there is a 2 byte command id or response code, followed by a flag byte (response only), the payload, a checksum byte, and an (response only) unknown byte. Please note that the packets are listed in transfer order but this may not represent the logical order of the packets. It is currently unknown what the logical order should be, but one can guess that a response is "close to" a request.
First some version information seems to be sent from Syscon to Kermit. This is same for cold boot and resume boot. The last response indicates the type of boot where 0xFF80 is resume and 0xFF14 is regular boot.
< [2.048118000000000] 0x0004, flags=00, payload=[0D 06 00 01 | ....], chk=0xE1, unk=0x00 > [2.048118000000000] 0x0001, payload=[ | ], chk=0xFD < [2.048659583333333] 0x0004, flags=00, payload=[00 60 40 00 | .`@.], chk=0x55, unk=0x00 > [2.048659583333333] 0x0005, payload=[ | ], chk=0xF9 < [2.049330083333333] 0x0004, flags=00, payload=[32 30 31 32 31 31 30 38 31 37 30 34 | 201211081704], chk=0x92, unk=0x00 > [2.049330083333333] 0x0002, payload=[ | ], chk=0xFC < [2.054004333333333] 0x0004, flags=80, payload=[ | ], chk=0x79, unk=0x30 > [2.054004333333333] 0x0080, payload=[12 00 | ..], chk=0x6A < [2.058172916666666] 0x0024, flags=00, payload=[ | ], chk=0xD9, unk=0x30 > [2.058172916666666] 0x0000, payload=[ | ], chk=0xFE < [2.062716333333333] 0x0024, flags=00, payload=[ | ], chk=0xD9, unk=0x30 > [2.062716333333333] 0x0080, payload=[12 00 | ..], chk=0x6A < [2.111457750000000] 0x0004, flags=00, payload=[14 FF | ..], chk=0xE4, unk=0x32
Next some encrypted session is established. A 8 byte nonce is sent from Syscon (it appears random for each boot, cold or warm). Encrypted data from this point on always differs each boot.
> [2.111457750000000] 0x0010, payload=[ | ], chk=0xEE < [2.133389000000000] 0x0004, flags=80, payload=[ | ], chk=0x79, unk=0xFF > [2.133389000000000] 0x00A0, payload=[30 00 00 0B 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | 0.......................................], chk=0xFB < [2.150567250000000] 0x0024, flags=00, payload=[ | ], chk=0xD9, unk=0xFF > [2.150567250000000] 0x0000, payload=[ | ], chk=0xFE < [2.155149500000000] 0x0024, flags=00, payload=[30 01 00 0B 00 00 00 00 A4 B0 EF 23 D6 9A 3A 06 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | 0..........#..:.........................], chk=0x5F, unk=0x00 > [2.155149500000000] 0x00A0, payload=[30 00 00 0B 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | 0.......................................], chk=0xFB < [2.163572000000000] 0x0004, flags=80, payload=[ | ], chk=0x79, unk=0x01 > [2.163572000000000] 0x00A0, payload=[30 02 00 0B 01 00 00 00 6C 7F E0 79 AA 03 4B B0 96 B7 42 F0 BC F8 62 7A 35 27 53 68 3D 0D ED A7 13 F2 32 77 46 2D 54 F8 | 0.......l..y..K...B...bz5'Sh=.....2wF-T.], chk=0x9B < [2.189271166666667] 0x0024, flags=00, payload=[ | ], chk=0xD9, unk=0x01 > [2.189271166666667] 0x0000, payload=[ | ], chk=0xFE < [2.193866583333334] 0x0024, flags=00, payload=[30 03 00 0B 00 00 00 00 7A 44 6E C8 F5 FA 35 CB 9B E9 E6 A0 B6 5C 85 1D FB A8 89 5C 9C 04 0B 29 34 59 55 EB 1D 98 AB 83 | 0.......zDn...5......\.....\...)4YU.....], chk=0xC6, unk=0x00 > [2.193866583333334] 0x00A0, payload=[30 02 00 0B 01 00 00 00 6C 7F E0 79 AA 03 4B B0 96 B7 42 F0 BC F8 62 7A 35 27 53 68 3D 0D ED A7 13 F2 32 77 46 2D 54 F8 | 0.......l..y..K...B...bz5'Sh=.....2wF-T.], chk=0x9B
Some more data is exchanged. Up until this point all the plaintext payloads appear to be the same from coldboot and warmboot.
< [2.202246333333334] 0x0004, flags=80, payload=[ | ], chk=0x79, unk=0x03 > [2.202246333333334] 0x088E, payload=[01 22 | ."], chk=0x43 < [2.206411750000000] 0x0004, flags=00, payload=[ | ], chk=0xF9, unk=0x03 > [2.206411750000000] 0x0000, payload=[ | ], chk=0xFE < [2.217062666666667] 0x0024, flags=00, payload=[ | ], chk=0xD9, unk=0x03 > [2.217062666666667] 0x0000, payload=[ | ], chk=0xFE < [2.221620916666667] 0x0024, flags=00, payload=[ | ], chk=0xD9, unk=0x03 > [2.221620916666667] 0x088E, payload=[01 22 | ."], chk=0x43 < [2.229805500000000] 0x0004, flags=80, payload=[ | ], chk=0x79, unk=0x03 > [2.229805500000000] 0x1082, payload=[80 04 08 | ...], chk=0xDD < [2.233887583333333] 0x0024, flags=00, payload=[ | ], chk=0xD9, unk=0x03 > [2.233887583333333] 0x0000, payload=[ | ], chk=0xFE < [2.238363416666667] 0x0024, flags=00, payload=[FF FF FF FF 01 FF FF FF | ........], chk=0xD7, unk=0x44 > [2.238363416666667] 0x1082, payload=[80 04 08 | ...], chk=0xDD < [2.246473916666667] 0x0004, flags=80, payload=[ | ], chk=0x79, unk=0xFF
Now, there appears to be a branch. The next sequence only shows up for cold boots.
> [2.246473916666667] 0x1082, payload=[A0 04 01 | ...], chk=0xC4 < [2.250555000000000] 0x0024, flags=00, payload=[ | ], chk=0xD9, unk=0xFF > [2.250555000000000] 0x0000, payload=[ | ], chk=0xFE < [2.255030833333334] 0x0024, flags=00, payload=[FF | .], chk=0xD9, unk=0x00 > [2.255030833333334] 0x1082, payload=[A0 04 01 | ...], chk=0xC4 < [2.259176583333333] 0x0004, flags=00, payload=[01 01 13 00 | ....], chk=0xE0, unk=0xFF > [2.259176583333333] 0x1100, payload=[ | ], chk=0xED < [2.263720583333333] 0x0004, flags=80, payload=[ | ], chk=0x79, unk=0x01 > [2.263720583333333] 0x00D0, payload=[30 00 00 0F 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | 0.......................................], chk=0xC7 < [2.267827000000000] 0x0004, flags=00, payload=[ | ], chk=0xF9, unk=0x01 > [2.267827000000000] 0x0000, payload=[ | ], chk=0xFE < [2.278339666666667] 0x0024, flags=00, payload=[ | ], chk=0xD9, unk=0x01 > [2.278339666666667] 0x0000, payload=[ | ], chk=0xFE < [2.282830833333333] 0x0024, flags=00, payload=[30 01 00 0F 00 00 00 00 E1 CA 65 96 BB 7E 81 7A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | 0.........e..~.z........................], chk=0x97, unk=0x00 > [2.282830833333333] 0x00D0, payload=[30 00 00 0F 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | 0.......................................], chk=0xC7 < [2.291023500000000] 0x0004, flags=80, payload=[ | ], chk=0x79, unk=0x01 > [2.291023500000000] 0x00D0, payload=[30 02 00 0F 01 00 00 00 4E D7 C0 7C D5 E8 BB D7 3E 9E 43 7B B2 E3 4D 81 23 C8 C4 BF B8 4D 9B 25 0A 3D C7 45 E6 0D 23 43 | 0.......N..|....>.C{..M.#....M.%.=.E..#C], chk=0x38 < [2.295129250000000] 0x0004, flags=00, payload=[ | ], chk=0xF9, unk=0x01 > [2.295129250000000] 0x0000, payload=[ | ], chk=0xFE < [2.305641750000000] 0x0024, flags=00, payload=[ | ], chk=0xD9, unk=0x01 > [2.305641750000000] 0x0000, payload=[ | ], chk=0xFE < [2.310132916666667] 0x0024, flags=00, payload=[30 03 00 0F 00 00 00 00 5B 3E 5C 5F 11 F9 E4 6A 85 0D 1E 06 9E F9 33 25 9B 95 55 21 39 48 FC 55 C7 BF A7 E4 32 AD FC 65 | 0.......[>\_...j......3%..U!9H.U....2..e], chk=0x55, unk=0x00 > [2.310132916666667] 0x00D0, payload=[30 02 00 0F 01 00 00 00 4E D7 C0 7C D5 E8 BB D7 3E 9E 43 7B B2 E3 4D 81 23 C8 C4 BF B8 4D 9B 25 0A 3D C7 45 E6 0D 23 43 | 0.......N..|....>.C{..M.#....M.%.=.E..#C], chk=0x38 < [2.318358166666667] 0x0004, flags=80, payload=[ | ], chk=0x79, unk=0x03 > [2.318358166666667] 0x00D0, payload=[30 04 00 0F 00 00 00 00 52 8D 6D BC 90 C9 00 EE FA CA 47 63 10 D1 4A E5 5A FD BB 91 3A 6C DA EF 64 CA 71 01 4A A9 D5 31 | 0.......R.m.......Gc..J.Z...:l..d.q.J..1], chk=0x4B < [2.322464250000000] 0x0004, flags=00, payload=[ | ], chk=0xF9, unk=0x03 > [2.322464250000000] 0x0000, payload=[ | ], chk=0xFE < [2.332976833333333] 0x0024, flags=00, payload=[ | ], chk=0xD9, unk=0x03 > [2.332976833333333] 0x0000, payload=[ | ], chk=0xFE < [2.337468000000000] 0x0024, flags=00, payload=[30 05 00 0F 00 00 00 00 52 8D 6D BC 90 C9 00 EE FA CA 47 63 10 D1 4A E5 5A FD BB 91 3A 6C DA EF 64 CA 71 01 4A A9 D5 31 | 0.......R.m.......Gc..J.Z...:l..d.q.J..1], chk=0xF5, unk=0x00 > [2.337468000000000] 0x00D0, payload=[30 04 00 0F 00 00 00 00 52 8D 6D BC 90 C9 00 EE FA CA 47 63 10 D1 4A E5 5A FD BB 91 3A 6C DA EF 64 CA 71 01 4A A9 D5 31 | 0.......R.m.......Gc..J.Z...:l..d.q.J..1], chk=0x4B < [2.345696333333333] 0x0004, flags=80, payload=[ | ], chk=0x79, unk=0x05
Then another set of shared sequence. Some differences in the warmboot responses though. On line 18,
FF BF FF 74
becomes
FF FF FF 74
. On line 12, the
00 00 00 00
becomes the address of the resume buffer (ex
F0 1E 1F 41
).
> [2.345696333333333] 0x00D2, payload=[20 7A 3E 7B 31 DE FC 3A 11 5F 64 E7 AB A4 EC 17 | .z>{1..:._d.....], chk=0x77 < [2.349790333333333] 0x0004, flags=00, payload=[ | ], chk=0xF9, unk=0x05 > [2.349790333333333] 0x0000, payload=[ | ], chk=0xFE < [2.360448916666666] 0x0024, flags=00, payload=[ | ], chk=0xD9, unk=0x05 > [2.360448916666666] 0x0000, payload=[ | ], chk=0xFE < [2.364930250000000] 0x0024, flags=00, payload=[9D 0B BC 4D BA 66 40 2C 63 BE F3 79 D0 31 26 1E 47 3A 64 DE 68 2F AE E2 8A B6 F0 27 37 46 89 16 0E 71 04 FA BF C9 4A A1 DF 4B EF D3 3D 0D 39 CD | ...M.f@,c..y.1&.G:d.h/.....'7F...q....J..K..=.9.], chk=0x11, unk=0x00 > [2.364930250000000] 0x00D2, payload=[20 7A 3E 7B 31 DE FC 3A 11 5F 64 E7 AB A4 EC 17 | .z>{1..:._d.....], chk=0x77 < [2.373236666666667] 0x0004, flags=80, payload=[ | ], chk=0x79, unk=0x0B > [2.373236666666667] 0x0090, payload=[0C 00 04 | ...], chk=0x5B < [2.377318583333333] 0x0024, flags=00, payload=[ | ], chk=0xD9, unk=0x0B > [2.377318583333333] 0x0000, payload=[ | ], chk=0xFE < [2.381794416666667] 0x0024, flags=00, payload=[00 00 00 00 | ....], chk=0xD5, unk=0x66 > [2.381794416666667] 0x0090, payload=[0C 00 04 | ...], chk=0x5B < [2.385879750000000] 0x0004, flags=00, payload=[40 00 | @.], chk=0xB7, unk=0x00 > [2.385879750000000] 0x0800, payload=[ | ], chk=0xF6 < [2.386382583333333] 0x0004, flags=00, payload=[FF BF FF 74 | ...t], chk=0xC4, unk=0x66 > [2.386382583333333] 0x0100, payload=[ | ], chk=0xFD < [2.386871833333333] 0x0004, flags=00, payload=[10 00 00 00 | ....], chk=0xE5, unk=0x66 > [2.386871833333333] 0x0003, payload=[ | ], chk=0xFB < [2.387380083333333] 0x0000, flags=3F, payload=[ | ], chk=0xBE, unk=0x00 > [2.387380083333333] 0x0006, payload=[ | ], chk=0xF8 < [2.481997666666667] 0x0000, flags=80, payload=[ | ], chk=0x7D, unk=0x00 > [2.481986333333333] 0x00D2, payload=[30 14 F4 B8 84 89 81 AB 3D 07 66 DE AE B6 D3 24 | 0.......=.f....$], chk=0x10 < [2.514678500000000] 0x0020, flags=00, payload=[ | ], chk=0xDD, unk=0x00 > [2.514678500000000] 0x0000, payload=[ | ], chk=0xFE < [2.519163916666667] 0x0020, flags=00, payload=[1A 1F BC 74 AA 16 59 D6 5C E7 FF 5B E0 85 B2 C8 39 2D D6 95 98 2F B7 4B 71 64 34 D7 8D 2C 94 A1 91 CB 73 D7 8D E1 D0 07 E6 1E 0F DA E7 51 BC 69 | ...t..Y.\..[....9-.../.Kqd4..,....s..........Q.i], chk=0x3C, unk=0x00 > [2.519163916666667] 0x00D2, payload=[30 14 F4 B8 84 89 81 AB 3D 07 66 DE AE B6 D3 24 | 0.......=.f....$], chk=0x10 < [2.527551416666667] 0x0000, flags=80, payload=[ | ], chk=0x7D, unk=0x1F > [2.527540083333333] 0x088E, payload=[02 29 | .)], chk=0x3B < [2.531619416666667] 0x0000, flags=00, payload=[ | ], chk=0xFD, unk=0x1F > [2.531619416666667] 0x0000, payload=[ | ], chk=0xFE < [2.542392416666666] 0x0020, flags=00, payload=[ | ], chk=0xDD, unk=0x1F > [2.542392416666666] 0x0000, payload=[ | ], chk=0xFE < [2.546867583333333] 0x0020, flags=00, payload=[ | ], chk=0xDD, unk=0x1F > [2.546867583333333] 0x088E, payload=[02 29 | .)], chk=0x3B
Then, the two boot paths diverge completely (also note the time jump). It is suspected that at this point the kernel is started up on coldboot, and the kernel resumes for warmboot. For cold boot only, we see the beginning init sequence again, which is likely done in SceSyscon.
< [3.322105750000000] 0x0000, flags=00, payload=[0D 06 00 01 | ....], chk=0xE5, unk=0x16 > [3.322105750000000] 0x0001, payload=[ | ], chk=0xFD < [3.326563916666667] 0x0000, flags=00, payload=[32 30 31 32 31 31 30 38 31 37 30 34 | 201211081704], chk=0x96, unk=0x85 > [3.326552583333333] 0x0002, payload=[ | ], chk=0xFC < [3.331090666666667] 0x0000, flags=80, payload=[ | ], chk=0x7D, unk=0x30 > [3.331079333333333] 0x0080, payload=[12 00 | ..], chk=0x6A < [3.331576333333333] 0x0020, flags=00, payload=[ | ], chk=0xDD, unk=0x30 > [3.331576333333333] 0x0080, payload=[12 00 | ..], chk=0x6A < [3.332068833333333] 0x0000, flags=00, payload=[10 00 00 00 | ....], chk=0xE9, unk=0x31 > [3.332068833333333] 0x0004, payload=[ | ], chk=0xFA < [3.332541666666667] 0x0000, flags=00, payload=[00 FF 04 00 | ....], chk=0xF6, unk=0x31 > [3.332541666666667] 0x0103, payload=[ | ], chk=0xFA < [3.336980333333333] 0x0000, flags=00, payload=[10 00 00 00 | ....], chk=0xE9, unk=0x31 > [3.336980333333333] 0x0003, payload=[ | ], chk=0xFB ...
Packet checksum
The checksum byte of the packet is calculated as the binary negation of the sum of all the bytes of the packet (including the 2 bytes of the command id and the byte for the length). The checksum calculation can be implemented as follows:
void syscon_calc_checksum(unsigned char packet[32], int length) { int i; unsigned char hash = 0; for (i = 0; i < 3 + length; i++) hash += packet[i]; packet[3 + length] = ~hash; }
Commands
Commands are listed in the order seen in cold boot. The numbers in the captured packets indicate the assumed order with some unused packets filtered out (they appear to be resent). The ordering and grouping are assumed and may contain errors.
CMD 0x0001 - GetBaryonVersion
Gets some device specific version. Can also be seen in the packet header in Syscon Update. Also sent at kernel boot.
SEND 1 > [2.881037083333333] 0x0001, payload=[ | ], chk=0xFD RESP 1 < [2.881037083333333] 0x0004, flags=00, payload=[0D 06 00 01 | ....], chk=0xE1, unk=0x71
SEND 23 > [4.167151583333333] 0x0001, payload=[ | ], chk=0xFD RESP 23 < [4.167151583333333] 0x0000, flags=00, payload=[0D 06 00 01 | ....], chk=0xE5, unk=0x32
CMD 0x0005 - GetHardwareInfo
SEND 2 > [2.881578833333333] 0x0005, payload=[ | ], chk=0xF9 RESP 2 < [2.881578833333333] 0x0004, flags=00, payload=[00 60 40 00 | .`@.], chk=0x55, unk=0x71
CMD 0x0002 - GetBaryonTimestamp
Gets syscon firmware timestamp. Also sent at kernel boot.
SEND 3 > [2.882249083333333] 0x0002, payload=[ | ], chk=0xFC RESP 3 < [2.882249083333333] 0x0004, flags=00, payload=[32 30 31 32 31 31 30 38 31 37 30 34 | 201211081704], chk=0x92, unk=0x00
SEND 24 > [4.171598000000000] 0x0002, payload=[ | ], chk=0xFC RESP 24 < [4.171598000000000] 0x0000, flags=00, payload=[32 30 31 32 31 31 30 38 31 37 30 34 | 201211081704], chk=0x96, unk=0xF7
CMD 0x0080
Unknown. Sends data 0x0012 on 3.60. Does not get return data. Also sent at kernel boot.
SEND 4 > [2.895635416666666] 0x0080, payload=[12 00 | ..], chk=0x6A RESP 4 < [2.886923416666667] 0x0004, flags=80, payload=[ | ], chk=0x79, unk=0x30 RESP 4 < [2.891092083333333] 0x0024, flags=00, payload=[ | ], chk=0xD9, unk=0x30 RESP 4 < [2.895635416666666] 0x0024, flags=00, payload=[ | ], chk=0xD9, unk=0x30
SEND 25 > [4.176620750000000] 0x0080, payload=[12 00 | ..], chk=0x6A RESP 25 < [4.176123750000000] 0x0000, flags=80, payload=[ | ], chk=0x7D, unk=0x30 RESP 25 < [4.176620750000000] 0x0020, flags=00, payload=[ | ], chk=0xDD, unk=0x30
CMD 0x0010 - GetWakeupFactor
See Wakeup factor.
Boot type indicator. 0xFF14 on cold boot. 0xFF80 on resume boot.
SEND 5 > [2.950546416666667] 0x0010, payload=[ | ], chk=0xEE RESP 5 < [2.950546416666667] 0x0004, flags=00, payload=[14 FF | ..], chk=0xE4, unk=0x32
CMD 0x00A0
Runs twice. Appears to contain a 8 byte inner header. First packet sends all zeros and gets back a 8 byte random response. This is likely a nonce or challenge. This likely establishes an encrypted session. Encrypted data differs on each boot. There does not appear to be data transferred using the established session.
SEND 6 > [2.994470666666667] 0x00A0, payload=[30 00 00 0B 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | 0.......................................], chk=0xFB RESP 6 < [2.972471333333333] 0x0004, flags=80, payload=[ | ], chk=0x79, unk=0xFF RESP 6 < [2.989889500000000] 0x0024, flags=00, payload=[ | ], chk=0xD9, unk=0xFF RESP 6 < [2.994470666666667] 0x0024, flags=00, payload=[30 01 00 0B 00 00 00 00 CA 71 11 BA 86 87 EF 0D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | 0........q..............................], chk=0x66, unk=0x00 SEND 7 > [3.033187750000000] 0x00A0, payload=[30 02 00 0B 01 00 00 00 92 45 B4 A5 49 15 CE F2 39 0E 9E 4C BF FA 19 E6 5D CF BA 5A 6E C3 7C ED 2A 6D 4E 79 84 28 1C 2A | 0........E..I...9..L....]..Zn.|.*mNy.(.*], chk=0x97 RESP 7 < [3.002893083333333] 0x0004, flags=80, payload=[ | ], chk=0x79, unk=0x01 RESP 7 < [3.028592333333334] 0x0024, flags=00, payload=[ | ], chk=0xD9, unk=0x01 RESP 7 < [3.033187750000000] 0x0024, flags=00, payload=[30 03 00 0B 00 00 00 00 12 77 A5 98 67 F7 38 9B B4 54 48 FE 84 82 CF 84 41 42 87 A2 EA D1 CF 9C 5B D1 2A 3F 1E 50 B9 3D | 0........w..g.8..TH.....AB......[.*?.P.=], chk=0x0A, unk=0x00
CMD 0x088E
Unknown. Sends data 0x2201 on 3.60 and does not get a response.
SEND 8 > [3.061354583333333] 0x088E, payload=[01 22 | ."], chk=0x43 RESP 8 < [3.041713500000000] 0x0004, flags=80, payload=[ | ], chk=0x79, unk=0x03 RESP 8 < [3.046148250000000] 0x0004, flags=00, payload=[ | ], chk=0xF9, unk=0x03 RESP 8 < [3.056796250000000] 0x0024, flags=00, payload=[ | ], chk=0xD9, unk=0x03 RESP 8 < [3.061354583333333] 0x0024, flags=00, payload=[ | ], chk=0xD9, unk=0x03
CMD 0x1082 - NVS Read
Get data from NVS. 2-byte offset followed by 1 byte length. For example used to fetch boot-time flags, like Update Mode.
Get Qaf Token area: SEND 9 > [3.078212500000000] 0x1082, payload=[80 04 08 | ...], chk=0xDD RESP 9 < [3.069790250000000] 0x0004, flags=80, payload=[ | ], chk=0x79, unk=0x03 RESP 9 < [3.073736583333333] 0x0024, flags=00, payload=[ | ], chk=0xD9, unk=0x03 RESP 9 < [3.078212500000000] 0x0024, flags=00, payload=[FF FF FF FF 01 FF FF FF | ........], chk=0xD7, unk=0x77 Get Update Mode: SEND 10 > [3.094879833333333] 0x1082, payload=[A0 04 01 | ...], chk=0xC4 RESP 10 < [3.086322916666667] 0x0004, flags=80, payload=[ | ], chk=0x79, unk=0xFF RESP 10 < [3.090404000000000] 0x0024, flags=00, payload=[ | ], chk=0xD9, unk=0xFF RESP 10 < [3.094879833333333] 0x0024, flags=00, payload=[FF | .], chk=0xD9, unk=0x00
CMD 0x1100 - GetErnieDLVersion
Gets Ernie DownLoader Version i.e. version of Ernie firmware.
SEND 11 > [3.099025500000000] 0x1100, payload=[ | ], chk=0xED RESP 11 < [3.099025500000000] 0x0004, flags=00, payload=[01 01 13 00 | ....], chk=0xE0, unk=0xFF
CMD 0x00D0
Some encrypted transfer that looks close to Syscon#CMD 0x00A0 in format. Different on each boot.
SEND 12 > [3.122679833333333] 0x00D0, payload=[30 00 00 0F 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | 0.......................................], chk=0xC7 RESP 12 < [3.103569583333333] 0x0004, flags=80, payload=[ | ], chk=0x79, unk=0x01 RESP 12 < [3.107676166666667] 0x0004, flags=00, payload=[ | ], chk=0xF9, unk=0x01 RESP 12 < [3.118188666666667] 0x0024, flags=00, payload=[ | ], chk=0xD9, unk=0x01 RESP 12 < [3.122679833333333] 0x0024, flags=00, payload=[30 01 00 0F 00 00 00 00 9F CC 4A 69 73 E9 C0 5A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | 0.........Jis..Z........................], chk=0xDD, unk=0x00 SEND 13 > [3.150031916666667] 0x00D0, payload=[30 02 00 0F 01 00 00 00 98 6D 3A 1E C5 B1 E9 AF 54 65 55 91 3B DF 2B A8 0F AD B0 73 A0 A2 0F EE 5D 0A AF 41 A5 6D 32 20 | 0........m:.....TeU.;.+....s....]..A.m2.], chk=0xF4 RESP 13 < [3.130872500000000] 0x0004, flags=80, payload=[ | ], chk=0x79, unk=0x01 RESP 13 < [3.134978166666667] 0x0004, flags=00, payload=[ | ], chk=0xF9, unk=0x01 RESP 13 < [3.145539833333333] 0x0024, flags=00, payload=[ | ], chk=0xD9, unk=0x01 RESP 13 < [3.150031916666667] 0x0024, flags=00, payload=[30 03 00 0F 00 00 00 00 F5 19 C0 67 09 80 C6 DB 58 8D FB E1 86 22 D1 00 DA BB D2 AF AA 51 F9 57 7C 56 92 0A 94 D6 60 4D | 0..........g....X....".......Q.W|V....`M], chk=0xF0, unk=0x00 SEND 14 > [3.177452416666667] 0x00D0, payload=[30 04 00 0F 00 00 00 00 87 4E 59 41 22 98 F8 62 BD B4 C8 4F 4C 0A 81 90 47 1E 1E 70 D6 51 57 42 E5 EC 07 A2 D4 CF E5 02 | 0........NYA"..b...OL...G..p.QWB........], chk=0x9A RESP 14 < [3.158257166666667] 0x0004, flags=80, payload=[ | ], chk=0x79, unk=0x03 RESP 14 < [3.162363250000000] 0x0004, flags=00, payload=[ | ], chk=0xF9, unk=0x03 RESP 14 < [3.172875666666667] 0x0024, flags=00, payload=[ | ], chk=0xD9, unk=0x03 RESP 14 < [3.177452416666667] 0x0024, flags=00, payload=[30 05 00 0F 00 00 00 00 87 4E 59 41 22 98 F8 62 BD B4 C8 4F 4C 0A 81 90 47 1E 1E 70 D6 51 57 42 E5 EC 07 A2 D4 CF E5 02 | 0........NYA"..b...OL...G..p.QWB........], chk=0x44, unk=0x00
CMD 0x00D2 - SNVS RW
This command is used twice during boot and also quite often after boot. Data is different on each boot. Encrypted session using key from handshake above. Second transaction seems to be the firmware version data written during the update process. Likely firmware version check is done here.
SEND 15 > [3.204733083333333] 0x00D2, payload=[32 78 88 CF 3E 63 56 19 75 3A 0A 2D F3 49 63 E2 | 2x..>cV.u:.-.Ic.], chk=0xA4 RESP 15 < [3.185595250000000] 0x0004, flags=80, payload=[ | ], chk=0x79, unk=0x05 RESP 15 < [3.189740333333333] 0x0004, flags=00, payload=[ | ], chk=0xF9, unk=0x05 RESP 15 < [3.200251666666666] 0x0024, flags=00, payload=[ | ], chk=0xD9, unk=0x05 RESP 15 < [3.204733083333333] 0x0024, flags=00, payload=[D3 57 9B F2 A2 45 E2 7A 2A FC 84 12 97 8E 23 5F C8 AB FB 58 97 EC DE 20 94 0A 78 28 C6 EE C5 45 18 29 00 F4 56 22 53 AF 24 47 8E FF B1 5C DA 2F | .W...E.z*.....#_...X......x(...E.)..V"S.$G...\./], chk=0x4C, unk=0xFF
SEND 21 > [3.359112250000000] 0x00D2, payload=[1C 0B 9E FF FB 68 90 4B FD C2 05 CD D8 67 4D D0 | .....h.K.....gM.], chk=0x2D RESP 21 < [3.321934500000000] 0x0000, flags=80, payload=[ | ], chk=0x7D, unk=0x00 RESP 21 < [3.354626666666667] 0x0020, flags=00, payload=[ | ], chk=0xDD, unk=0x00 RESP 21 < [3.359112250000000] 0x0020, flags=00, payload=[6C B4 26 F3 CD 32 D3 3E 6F 80 F2 0F 68 F7 E2 96 58 DB 2F BB AB A6 98 DD 26 14 DD 61 12 E4 55 BA BB 32 1D 1F 75 D5 D1 4C 7E 4A 19 42 E5 B0 C6 AB | l.&..2.>o...h...X./.....&..a..U..2..u..L~J.B....], chk=0x84, unk=0xFF
CMD 0x0090 - VS Read
This command reads data from Ernie Volatile Storage. This is the inverse of command 0x91.
This is used for example to fetch the saved resume context buffer physical address. Kernel sets this before suspending and this value is passed to the resume function. See Suspend. The format is 2 byte offset and 1 byte length.
SEND 16 > [3.221743166666667] 0x0090, payload=[0C 00 04 | ...], chk=0x5B RESP 16 < [3.213273166666667] 0x0004, flags=80, payload=[ | ], chk=0x79, unk=0x57 RESP 16 < [3.217267333333333] 0x0024, flags=00, payload=[ | ], chk=0xD9, unk=0x57 RESP 16 < [3.221743166666667] 0x0024, flags=00, payload=[F0 0E 1F 41 | ...A], chk=0x77, unk=0x45
CMD 0x0091 - VS Write
This command writes data to Ernie Volatile Storage. This is the inverse of command 0x90.
CMD 0x0800 - Get USB Info
See KBL Param.
SEND 17 > [3.225828583333334] 0x0800, payload=[ | ], chk=0xF6 RESP 17 < [3.225828583333334] 0x0004, flags=00, payload=[40 00 | @.], chk=0xB7, unk=0x41
CMD 0x0100 - GetBootControlsInfo
See Boot Controls Info.
SEND 18 > [3.226331500000000] 0x0100, payload=[ | ], chk=0xFD RESP 18 < [3.226331500000000] 0x0004, flags=00, payload=[FF BF FF 74 | ...t], chk=0xC4, unk=0x45
CMD 0x0003 - GetSleepFactor
See Sleep Factor.
SEND 19 > [3.226820750000000] 0x0003, payload=[ | ], chk=0xFB RESP 19 < [3.226820750000000] 0x0004, flags=00, payload=[10 00 00 00 | ....], chk=0xE5, unk=0x45
CMD 0x0006 - Get Hardware flags
See Hardware flags.
SEND 20 > [3.227328833333333] 0x0006, payload=[ | ], chk=0xF8 RESP 20 < [3.227328833333333] 0x0000, flags=3F, payload=[ | ], chk=0xBE, unk=0x00
CMD 0x088E
Unknown. Appears to be the last command sent before a time-jump (likely indicating completion of early-boot). Might be some status indicator to tell Syscon that we're done.
SEND 22 > [3.386554833333333] 0x088E, payload=[02 29 | .)], chk=0x3B RESP 22 < [3.367488416666667] 0x0000, flags=80, payload=[ | ], chk=0x7D, unk=0xB4 RESP 22 < [3.371567833333333] 0x0000, flags=00, payload=[ | ], chk=0xFD, unk=0xB4 RESP 22 < [3.382079833333334] 0x0020, flags=00, payload=[ | ], chk=0xDD, unk=0xB4 RESP 22 < [3.386554833333333] 0x0020, flags=00, payload=[ | ], chk=0xDD, unk=0xB4
CMD 0x0004
Unknown. Likely happens after initial boot.
SEND 26 > [4.177113250000000] 0x0004, payload=[ | ], chk=0xFA RESP 26 < [4.177113250000000] 0x0000, flags=00, payload=[10 00 00 00 | ....], chk=0xE9, unk=0x31
CMD 0x0103
Unknown. Likely happens after initial boot.
SEND 27 > [4.177586083333333] 0x0103, payload=[ | ], chk=0xFA RESP 27 < [4.177586083333333] 0x0000, flags=00, payload=[00 FF 04 00 | ....], chk=0xF6, unk=0x31
Syscon Volatile Storage
Offset | Size | Name | Comment | Used by |
---|---|---|---|---|
0x0 | 8 | unknown | ||
0x8 | 4 | Syscon power on time | ex on DevKit: 0xA, 0x16, 0x1F, 0x24. ex on retail: 0x01BC0CD0, 0x05AC1AF7, 0x80000269 | SceRtc#sceRtcSetCurrentTickForDriver |
0xC | 4 | Resume context physical address | Set on retail. Not set on DevKit. ex: 0x411F1EF0 | second_loader |
0x10 | 5 | Current Tick | Set on retail and DevKit. | SceRtc#sceRtcSetCurrentTickForDriver |
0x15 | 3 | padding | ||
0x18 | 5 | Current Secure Tick | Set on retail. Not set on DevKit. | SceRtc#sceRtcSetCurrentSecureTickForDriver |
0x1D | 5 | Current Network Tick | Always a bit earlier than Current Tick and Current Secure Tick. | SceRtc#sceRtcSetCurrentNetworkTickForDriver |
0x22 | 5 | unknown Tick | Set on DevKit. Not set on retail. ?Current Debug Secure Tick? | SceRtc |
0x27 | 5 | unknown Tick | ?Current Debug Secure Tick? | SceRtc#SceRtcForDriver_A7236656 |
0x2C | 5 | Current Debug Network Tick | SceRtc#sceRtcSetCurrentDebugNetworkTickForDriver | |
0x31 | 0x8F | unknown | Maybe reserved. Probably unused. | |
0xE0 | 0x20 | CP DIP switches | Set on DevKit. Not set on retail. | second_loader |
Types
typedef struct SceSysconRtcTick { // size is 5 bytes uint8_t tick[5]; } SceSysconRtcTick; typedef struct SceSysconVolatileStorage { // size is 0x100 bytes uint8_t unk_0[8]; SceUInt32 powerOnTime; void *resumeContextPA; SceRtcSysconTick currentTick; uint8_t padding[3]; SceSysconRtcTick currentSecureTick; SceSysconRtcTick currentNetworkTick; SceSysconRtcTick unk_22; SceSysconRtcTick unk_27; SceSysconRtcTick currentDebugNetworkTick; uint8_t reserved[0x8F]; SceDIPSW dipsw; } SceSysconVolatileStorage;
NVS
Not every NVS sector is directly readable from non-secure kernel: some sectors are part of SNVS (Secure NVS) which means they are XTS encrypted and must be accessed through a Secure handshake.
On FW 3.60, NVS size is 0xB60 bytes:
- Area from 0 to 0x3FF cannot be read using SceSblSsMgr#sceSblNvsReadForKernel nor written using SceSblSsMgr#sceSblNvsWriteForKernel. This area is handled by Secure Modules.
- Area from 0x400 to 0x75F is handled by NS Kernel SceSblSsMgr.
- Area from 0x760 to 0xB5F are reserved for Test and Tool consoles. However this area seems unused.
Offset | Size | Name | Comment | Used by |
---|---|---|---|---|
0 | 0x20 | Mgmt Data | Embeds SNVS flags and ProductMode. Used for Update, PM and QAF. XTS encrypted sector. 0x10 data + 0x10 CMAC | "sceSblQafManagerSetFlag" (sub_81001610 on FW 0.990), "SpkgInfoUtilGetSNVSFlagStatus" and "SpkgInfoUtilSetSNVSFlagStatus" (on FW 0.931), setProductMode |
0x20 | 0x280 | SNVS Sectors | 19 XTS encrypted sectors of size 0x20 bytes handled by update_service_sm.self | "SpkgInfoUtilInitForUpdater" on FW 0.931 |
0x20 | 0x20 | SNVS Sectors | AES-XTS encrypted sector. The system version info. | |
0x40 | 0x20 | SNVS Sectors | AES-XTS encrypted sector. The vita processor version info. Current fw, baryon version, unknown processor, factory fw. | |
0x60 | 0x20 | SNVS Sectors | AES-XTS encrypted sector. some flags | |
0xA0 | 0x20 | SNVS Sectors | AES-XTS encrypted sector. SLB2 sha256(act or ina). | |
0xC0 | 0x20 | SNVS Sectors | AES-XTS encrypted sector. SLB2 sha256(act or ina). | |
0x2A0 | 0x20 | Qa Flag Version | 0x10 bytes data + 0x10 bytes AES128CMAC. If unused, 0xFFed. | "sceSblQafManagerSetQaFlagVersion" on FW 0.940 |
0x2C0 | 0x140 | Unknown | 0xFFed | |
0x400 | 0x80 | Qaf Token | second_loader | |
0x480 | 0x1 | Qaf Token Flag | 1 when Qaf Token is not set (FFed), 0 when Qaf Token is set | second_loader |
0x481 | 0x1 | Extra UART Flag | See KBL Param#Boot flags. | second_loader |
0x482 | 0x1 | Unknown | SceSblSsMgr#sceSblSsGetNvsDataForDriver, SceSblSsMgr#sceSblSsSetNvsDataForDriver | |
0x483 | 0x1 | Safe Mode Flag | See KBL Param#Boot flags. | SceSblSsMgr#sceSblSsGetNvsDataForDriver, SceSblSsMgr#sceSblSsSetNvsDataForDriver, second_loader |
0x484 | 0x1 | Unknown | ||
0x485 | 0x1 | Unknown | ||
0x486 | 0x1 | Internal Storage Flag | See KBL Param#Boot flags. Not present on FWs 0.931-0.990. Present on FW 3.60. | SceSblSsMgr#sceSblSsGetNvsDataForDriver, SceSblSsMgr#sceSblSsSetNvsDataForDriver, second_loader |
0x487 | 0x1 | Unknown | See KBL Param#Boot flags. | second_loader |
0x4A0 | 0x1 | Update Mode | See KBL Param#Boot flags. | SceSblUpdateMgr#sceSblUsGetUpdateModeForUser, SceSblUpdateMgr#sceSblUsSetUpdateModeForUser |
0x4A1 | 0x3 | Unknown. Unused. | ||
0x4A4 | 0x4 | System Language | SceRegistryMgr, SceSblSsMgr#sceSblSsGetNvsDataForDriver, SceSblSsMgr#sceSblSsSetNvsDataForDriver | |
0x4A8 | 0x1C | Unknown. Unused. | ||
0x4C4 | 0x1 | Unknown. Set to 0 by default. | ||
0x4C5 | 0x1B | Unknown. Unused. | ||
0x4E0 | 0x20 | Unknown per device ASCII string of length 22 characters ?VisibleId? | SceSblSsMgr#sceSblSsGetNvsDataForDriver, SceSblSsMgr#sceSblSsSetNvsDataForDriver | |
0x500 | 0x1 | Wlan/Bt Flag | SceSblSsMgr#sceSblSsGetNvsDataForDriver, SceSblSsMgr#sceSblSsSetNvsDataForDriver, SceWlanBt module_start | |
0x501 | 0x1F | Unknown. Unused. | ||
0x520 | 0x80 | Activation Area | first 0x20 bytes are SceNVSKitActivationData | SceSblSsMgr, SceSblPostSsMgr |
0x5A0 | 0x100 | Qaf Token RSA signature | Not present on FW 0.990. Present on FW 3.60. Maybe added on FW 1.80. | second_loader |
0x6A0 | 0xC0 | Unknown. Unused. | ||
0x760 | 0x400 | Reserved for Test and Tool. | Seems unused. |
Types
typedef struct SceNVSKitActivationData { // size is 0x20 bytes char magic[4]; // "act\n" uint32_t issue_no; uint32_t end_date; uint32_t start_date; char cmac_hash[0x10]; } SceNVSKitActivationData;
Pinout
A candidate package for this chip is Renesas' P121F1-50-BAL-1. It has the same size and number of pins.
UART
Name | Pin | Description |
---|---|---|
CTS0 | J7 | UART0 clear to send |
RTS0 | C6 | UART0 request to send |
TX0 | B6 | UART0 transmit |
RX0 | F11 | UART0 receive |
SW0 | A8 | Switch, see UART Console#OLED PSVita UART0 location |
SPI
Main communication with Kermit.
Name | Pin | Description |
---|---|---|
SS | A7 | Slave Select (often active low, output from master) |
MISO | A6 | Master In Slave Out (data output from slave) |
MOSI | C7 | Master Out Slave In (data output from master) |
SCLK | B7 | Serial Clock (output from master) |
Other
Name | Pin | Description |
---|---|---|
? | C11 | UDC pin 11 |
? | F9 | UDC pin 12 |
? | G4 | UDC pin 13 |
? | G8 | SN99057 pin 38 |
PWR_SW | G6 | Power switch through two transistor buffers |
Versions
Hardware Versions
See also [1].
Software Versions
See also [2].
Ernie firmware can be partly updated and downgraded with software updates embedded in PUP.
Ernie firmware is dependant of the hardware version and detects it based on Hardware Info.
Examples
With DevKit connected, psp2ctrl info
queries return the following results:
DEM-3000H running FW 0.990:
SysConVersion: 591105
-> converted to hexadecimal: 0x00090501 -> 0.9.5.1
PDEL-1001 running FW 1.692:
SCVersion: 0.9.2.4
PDEL-1001 running FW 3.600-3.680:
SCVersion: 1.0.3.6
Downgrade
Syscon is downgradable on DEM/PDEL/PTEL/QAF units. It might also be downgraded on retail when using a downgrade enabler like modoru.
Firmware
See Ernie Firmware