IdStorage: Difference between revisions
(→Leaf content: Rework descriptions and move leaf names in subsection title when applicable) |
(→Idps certificates: Refactor section and add note about PSPEMU usage) |
||
(18 intermediate revisions by 3 users not shown) | |||
Line 67: | Line 67: | ||
* The content of a leaf always starts at offset 0. | * The content of a leaf always starts at offset 0. | ||
* If leaf contents are smaller than 512 bytes, the unused parts are left empty. | * If leaf contents are smaller than 512 bytes, the unused parts are left empty. | ||
* Strings are padded with NUL bytes if the content is smaller than maximum size, but may be non-NUL terminated | |||
Leaves not listed in this section have not been found in any unit, and leaves listed in this section are not all found in every unit. | Leaves not listed in this section have not been found in any unit, and leaves listed in this section are not all found in every unit. | ||
Line 76: | Line 77: | ||
Leaves 0x000~0x07F are written to IdStorage during manufacturing by a function called '''<code>_writeIdpsCert</code>'''. | Leaves 0x000~0x07F are written to IdStorage during manufacturing by a function called '''<code>_writeIdpsCert</code>'''. | ||
Leaf 0x07E contains the | Leaf 0x07E contains the SHA-256 digest of leaves 0x000~0x07D, signed using RSA-2048. | ||
The public key used for signature verification can be found in <code>factTest.self</code>. | |||
Leaf 0x07F is not covered by the signature but is flashed | Leaf 0x07F is not covered by the signature but is flashed by '''<code>_writeIdpsCert</code>''' nonetheless. | ||
=== | === 0x000~0x03F - PSP leaves === | ||
PSP leaves 0x100~0x13F (read using <code>sceCompatIdStorageLookup</code>) are mapped to these PS Vita leaves instead (i.e., Vita leaf <code>X</code> contains PSP leaf <code>0x100 + X</code>). | |||
Like on a real PSP, this area is duplicated: leaves 0x000~0x01F are identical to 0x020~0x03F. Only the first half will be described. | |||
Identical across all units | ==== 0x000~0x007 - SceIdStoragePspCertificates ==== | ||
Identical across all units. | |||
==== 0x008~0x01F ==== | |||
Unused. Always all zeroes. | |||
=== 0x040~0x047 - SceIdStoragePsp2Certificates === | === 0x040~0x047 - SceIdStoragePsp2Certificates === | ||
Line 98: | Line 102: | ||
=== 0x048~0x04F === | === 0x048~0x04F === | ||
Console-unique. | Console-unique. Maybe UMD certificates like in PSP IdStorage. | ||
=== 0x050~0x07D === | |||
Unused. Always all zeroes. | |||
=== 0x07E === | === 0x07E === | ||
Line 107: | Line 115: | ||
Data contained between 0x0 and 0x5F is unknown, and data between 0x160 and 0x1FF is unused (always 00). | Data contained between 0x0 and 0x5F is unknown, and data between 0x160 and 0x1FF is unused (always 00). | ||
=== 0x07F === | |||
Unused. Always all zeroes. | |||
== 0x80 - SMI == | == 0x80 - SMI == | ||
Line 115: | Line 127: | ||
<source lang="c"> | <source lang="c"> | ||
/** | |||
* The SMI leaf can be divided in three areas: | |||
* - offset 0x000~0x07F: plaintext area | |||
* - offset 0x080~0x0FF: payload area | |||
* - offset 0x100~0x1FF: signature area | |||
*/ | |||
struct SMILeaf { | struct SMILeaf { | ||
uint8_t magic[4]; // | /** SMI Magic: Must be "SMI\0" */ | ||
uint32_t version; // | uint8_t magic[4]; | ||
uint32_t | /** SMI Version: Must be 1 */ | ||
uint8_t | uint32_t version; | ||
// | /** | ||
/ | * Minimal firmware version, in plaintext | ||
uint8_t | * This is ignored by second_loader. | ||
*/ | |||
uint32_t minfw_plaintext; | |||
/** | |||
* Padding up to offset 0x80 (payload area). | |||
* Checked by second_loader to be all zeroes. | |||
*/ | |||
uint8_t must_be_zero[0x80 - 0xC]; | |||
/** | |||
* Minimal firmware version allowed to run on unit. | |||
* Must be higher or equal to the version contained | |||
* in second_loader, or panic() will be called. | |||
*/ | |||
uint32_t manuSdkVersion; | |||
/** | |||
* Padding up to offset 0x100 (signature area). | |||
* ?Must be all zeroes but not checked? | |||
*/ | |||
uint8_t unused[0x100 - 0x84]; | |||
/** Signature area */ | |||
uint8_t signature[0x100]; | |||
}; | }; | ||
</source> | </source> | ||
=== Encryption and signature === | |||
To prevent modification or transplantation, the SMI leaf is encrypted (AES-CBC-256) using [[Cmep_Key_Ring_Base#0x200~0x2FF:_Master_keyrings|per-console keyslot 0x213]] and signed by SCE. | |||
* The ''plaintext area'' (<code>0x000~0x07F</code>) is not encrypted | |||
* The ''payload area'' (<code>0x080~0x0FF</code>) is encrypted twice | |||
** The first layer of encryption (''outer encryption'') is also applied to the ''signature area'' | |||
** The second layer of encryption (''inner encryption'') is only applied to this area | |||
* The ''signature area'' is only encrypted once | |||
** It contains the SHA-256 hash of ''plaintext area'' + '''inner-encrypted!''' ''payload area'', signed by SCE (?2048-bit? RSA) | |||
To decrypt an SMI leaf, perform the following: | |||
* Derive the <code>Outer Decryption Key</code> by '''encrypting''' the <code>Outer Key Seed</code> buffer using AES-CBC-256 (Key: keyslot 0x213; IV: <code>Outer Key Derivation IV</code>) | |||
* Decrypt the payload and signature area using AES-CBC-256 (Key = <code>Outer Decryption Key</code>, IV = <code>Outer Decryption IV</code>) | |||
* Verify the SMI signature (optional) | |||
** Compute SHA-256 of ''plaintext area'' + '''outer-decrypted''' ''payload area'' | |||
** Verify computed hash using data in ''signature area'' and the <code>SMI Verification Public Key</code> | |||
* Derive the <code>Inner Decryption Key</code> by '''encrypting''' the <code>Inner Key Seed</code> buffer using AES-CBC-256 (Key: keyslot 0x213; IV: <code>Inner Key Derivation IV</code>) | |||
* Decrypt the payload area (with Outer Encryption removed) using AES-CBC-256 (Key: <code>Inner Decryption Key</code>, IV: <code>Inner Decryption IV</code>) | |||
(N.B.: the <code>Outer Key Seed</code>, <code>Outer Key Derivation IV</code>, <code>Outer Decryption IV</code>, <code>SMI Verification Public Key</code>, <code>Inner Key Seed</code>, <code>Inner Key Derivation IV</code> and <code>Inner Decryption IV</code> are hardcoded in [[Second Loader]]) | |||
== 0x100 == | == 0x100 == | ||
Line 130: | Line 192: | ||
Name may be <code>Idlog</code>. | Name may be <code>Idlog</code>. | ||
Console-unique. | Console-unique. Two strings related to manufacturing. | ||
Both strings are 0x100 bytes wide; one starts at offset 0 and one at offset 0x100. | |||
The string at offset 0x100 is written at a different stage (end of manufacturing?) than the string at offset 0, so it is possible to find units with only first string written (e.g., a Dolphin CEM-3000 unit). | The string at offset 0x100 is written at a different stage (end of manufacturing?) than the string at offset 0, so it is possible to find units with only first string written (e.g., a Dolphin CEM-3000 unit). | ||
Line 139: | Line 201: | ||
Console-unique. Per-console factory/service product information. | Console-unique. Per-console factory/service product information. | ||
<source lang="c"> | |||
typedef struct { | |||
u32 server_ip; | |||
u16 server_port; | |||
u8 netmask; //Number of '1' bits in netmask | |||
u8 unused; | |||
u32 client_ip; | |||
u32 defaultGW; | |||
} conn_param; | |||
struct Leaf0x102 { | |||
u32 unk0; | |||
u32 unk4; | |||
struct { | |||
u8 id; | |||
u8 state; | |||
} ProcessId[0x20]; | |||
char gcpId[0x20]; | |||
char productId[0x20]; | |||
//The following fields indicate the number of X present in unit | |||
struct { | |||
u8 ComNum; //Com (3G module) | |||
u8 WlanNum; //Ethernet is also counted in here, despite field name | |||
u8 BtNum; //Bluetooth | |||
u8 BatteryNum; | |||
u8 HdmiNum; | |||
u8 CpNum; //Communication Processor | |||
struct { //Guessed field names | |||
u8 Front; | |||
u8 Back; | |||
} CameraNum; | |||
struct { //Guessed field names | |||
u8 Front; | |||
u8 Back; | |||
} TouchNum; | |||
u8 SixSenseNum; //Gyro | |||
u8 EMagNum; //Magnetometer / Compass | |||
u8 GpsNum; | |||
u8 AnaDevNum; //a.k.a. Analog Pad (AP) or Joystick | |||
u8 DisplayNum; | |||
u8 SimNum; //SIM slot | |||
} DeviceNum; | |||
u8 SimPackNum; //Prepaid SIM card | |||
u8 ComType; | |||
u8 unused_9A[14]; | |||
u32 contentsVer; //spkgInfo.version from sceSblUsGetSpkgInfo(0x18) | |||
u8 unk_AC[4]; | |||
u8 unk_B0; | |||
u8 unused_B1[0x7]; | |||
u8 unk_B8; | |||
u8 unused_B9[0x7]; | |||
conn_param conn_param_0; //For WLAN test? | |||
conn_param conn_param_1; //For Ethernet test? | |||
char ssid[0x20]; //SSID of AP used for WLAN test | |||
u8 test_bt_addr[6]; //Bluetooth MAC address for BT test | |||
u8 unused_106[2]; | |||
char ImeiBarcode[32]; | |||
char PartsNoBardcode[16]; | |||
char Imsi[16]; | |||
char IccId[20]; | |||
u8 unused_15C[4]; | |||
//Version of the software executed on the unit | |||
//during manufacturing. Each element of the array | |||
//corresponds to a different program. | |||
u32 softVer[3]; | |||
u8 unused_16C[4]; | |||
struct { | |||
char essid[12]; | |||
u8 channel; | |||
} WlanTestApInfo; | |||
u8 unused_17D[3]; | |||
u16 WlanRssi; | |||
u8 unused_182[6]; | |||
//Obtained from sceSblUsGetSpkgInfo(0x1C), which | |||
//corresponds to preinstall data patch Spkg. | |||
//First 4 bytes = spkgInfo.version | |||
//Fifth byte = spkgInfo.status[1] | |||
u8 CustomThemeVersion[5]; | |||
u8 unused_18D[3]; | |||
//If set, clears itself at some point during | |||
//factTest and skips something | |||
u8 ConfigProcessJumpFlag; | |||
u8 unused_191[111]; | |||
}; | |||
</source> | |||
=== ProcessId === | |||
The <code>ProcessId</code> field is an ID->status mapping table used to store on the unit the success or failure of various operations ("processes") performed during manufacturing. | |||
{| class="wikitable" style="text-align:center;" | |||
|+ Existing process IDs | |||
|- | |||
! Process ID | |||
! Description | |||
! Notes | |||
|- | |||
| 0 | |||
| colspan="2" | '''Unknown''' | |||
|- | |||
| 1 | |||
| <code>KervDiagResultFlag</code> check | |||
| Check if [[Ernie#NVS|KervDiagResultFlag (NVS 0x484)]] is 1 | |||
|- | |||
| 2 | |||
| First Image Update | |||
(<code>PSP2UPDAT.PUP.manu</code>, | |||
<code>PSP2UPDAT.PUP.preinst</code>, | |||
<code>PSP2UPDAT.PUP.preinst2</code>) | |||
| Performed by <code>1st image writing phase</code> <code>psp2config.skprx</code> firmware. | |||
The <code>preinst</code> PUPs are optional, but installed during this step if present. | |||
|- | |||
| 3 | |||
| <code>Manual(DISP)</code> | |||
| Display-related tests? | |||
Related to <code>pdTestOled</code>, <code>pdTestAnadevCalib</code>, <code>pdTestPadTest</code>, <code>pdTestSpeaker</code>? | |||
|- | |||
| 4 | |||
| <code>_wlanTest</code> | |||
| Tests that WLAN hardware is functional (connects to WLAN AP specified in <code>conn_param_0</code>?) | |||
|- | |||
| 5 | |||
| <code>_btTest</code> | |||
| Tests that Bluetooth hardware is functional | |||
|- | |||
| 6 | |||
| colspan="2" | '''Unknown''' | |||
|- | |||
| 7 | |||
| <code>Manual(TP)</code> | |||
| Touch panel tests? | |||
|- | |||
| 8 | |||
| PSP Compatibility | |||
| Tests that PSP Compatibilty hardware is functional (done in <code>compat_diag.skprx</code>) | |||
|- | |||
| 9~25 | |||
| colspan="2" | '''Unknown''' | |||
|- | |||
| 0x1A / 26 | |||
| <code>vshTest</code>? | |||
| | |||
|- | |||
| 0x1B / 27 | |||
| peri1 Firmware Update | |||
(<code>PSP2UPDAT.PUP.peri1</code>) | |||
| Which peripheral this corresponds to is unknown. | |||
|- | |||
| 0x1C / 28 | |||
| Touch Panel Firmware Update | |||
(<code>PSP2UPDAT.PUP.peri2</code>) | |||
| Skipped(?) if TP HW Info doesn't match <code>check_pre_cond.conf</code> file on Memory Card. | |||
|- | |||
| 0x1D / 29 | |||
| peri3 Firmware Update | |||
(<code>PSP2UPDAT.PUP.peri3</code>) | |||
| Which peripheral this corresponds to is unknown. | |||
|- | |||
| 0x1E / 30 | |||
| ?Reset Image? Update | |||
(<code>PSP2UPDAT.PUP.assy</code>) | |||
| These PUPs are assumed to be those with <code>reset image</code> <code>psp2config.skprx</code> | |||
|- | |||
| 0x1F / 31 | |||
| ?2nd Image? Update | |||
| <code>2nd Image</code> is assumed to be firmware the unit is shipped with ("Retail"). | |||
This ProductId is mentioned as <code>2nd Image Write</code> in various factTest <code>config.txt</code>. | |||
|} | |||
{| class="wikitable" style="text-align:center;" | |||
|+ Meaning of <code>state</code> | |||
|- | |||
! State | |||
! Description | |||
|- | |||
| colspan="2" | '''For tests''' | |||
|- | |||
| 0x00 | |||
| Test not attempted | |||
|- | |||
| 0x01 | |||
| Test OK | |||
|- | |||
| 0x02 | |||
| Test NG - ignored | |||
(NG ignored by operator) | |||
|- | |||
| 0x03 | |||
| Test skipped | |||
|- | |||
| 0x04 | |||
| Test NG | |||
|- | |||
| colspan="2" | '''For updates''' | |||
|- | |||
| 0x00 | |||
0x09 | |||
0xFF | |||
| ''<code>fresh input</code>'' | |||
|- | |||
| 0x01 | |||
| ''<code>already update</code>'' | |||
|- | |||
| 0x04 | |||
| ''<code>failed update</code>'' | |||
|} | |||
== 0x103 == | == 0x103 == | ||
Line 144: | Line 419: | ||
Console-unique. Unit hardware information. | Console-unique. Unit hardware information. | ||
{| class="wikitable" style="text-align:center" | |||
|- | |||
! Offset | |||
! Size | |||
! Name | |||
! Description | |||
|- | |||
| 0x000 | |||
| 0x4 | |||
| ErnieHwInfo | |||
| style="text-align:left;" | [[KBL_Param#Hardware_Info|Ernie (Syscon) Hardware Information]] | |||
|- | |||
| 0x004 | |||
| 0x4 | |||
| ErnieFwVersion | |||
| style="text-align:left;" | [[SceSyscon#sceSysconGetErnieVersionForDriver|Ernie Firmware Version]] (also called Ernie Verison) | |||
|- | |||
| 0x008 | |||
| 0x4 | |||
| ErnieDlVersion | |||
| style="text-align:left;" | [[SceSyscon#sceSysconGetErnieDLVersionForDriver|ErnieDlVersion]] | |||
|- | |||
| 0x00C | |||
| 0x2 | |||
| ErnieCfgVersion | |||
| style="text-align:left;" | Can be obtained with [[SceSyscon#sceSysconGetConfigStorageInfoForDriver]]. | |||
|- style="font-style:italic; font-family:serif !important;" | |||
| 0x00E | |||
| 0x12 | |||
| colspan="2" | Empty | |||
|- | |||
| 0x020 | |||
| 0x8 | |||
| EmmcFwVersion | |||
| style="text-align:left;" | Vendor ID (1 byte), empty space (1 byte) and Device Version (6 bytes) | |||
|- style="font-style:italic; font-family:serif !important;" | |||
| 0x028 | |||
| 0x8 | |||
| colspan="2" | Empty | |||
|- | |||
| 0x030 | |||
| 0x8 | |||
| EmmcFwVersion2 | |||
| style="text-align:left;" | Vendor ID (1 byte), Device Version (6 bytes) and an additional byte (for Samsung eMMC, 0 otherwise) | |||
|- style="font-style:italic; font-family:serif !important;" | |||
| 0x038 | |||
| 0x8 | |||
| colspan="2" | Empty | |||
|- | |||
| 0x040 | |||
| 0x2 | |||
| ElmoFWVer | |||
| style="text-align:left;" | [[SceSyscon#sceSysconGetElmoFwVersionForDriver|Elmo Firmware Version]] | |||
|- style="font-style:italic; font-family:serif !important;" | |||
| 0x042 | |||
| 0x1E | |||
| colspan="2" | Empty | |||
|- | |||
| 0x060 | |||
| 0x2 | |||
| CookieFWVer | |||
| style="text-align:left;" | [[SceSyscon#sceSysconGetCookieFwVersionForDriver|Cookie Firmware Version]] | |||
|- style="font-style:italic; font-family:serif !important;" | |||
| 0x062 | |||
| 0x1E | |||
| colspan="2" | Empty | |||
|- | |||
| 0x080 | |||
| 0x2 | |||
| BarkleyFwVersion | |||
| rowspan="2" style="text-align:left;" | [[SceSyscon#sceSysconMotionGetDeviceInfoForDriver|Motion Device]] Firmware Version/Hardware Information | |||
|- | |||
| 0x082 | |||
| 0x2 | |||
| BarkleyHwInfo | |||
|- style="font-style:italic; font-family:serif !important;" | |||
| 0x084 | |||
| 0x1C | |||
| colspan="2" | Empty | |||
|- | |||
| 0x0A0 | |||
| 0x2 | |||
| AbbyHWVersion | |||
| rowspan="3" style="text-align:left;" | [[SceSyscon#sceSysconGetBatteryVersionForDriver|Abby HW/FW/DF Version]] | |||
|- | |||
| 0x0A2 | |||
| 0x2 | |||
| AbbyFWVersion | |||
|- | |||
| 0x0A4 | |||
| 0x2 | |||
| AbbyDFVersion | |||
|- style="font-style:italic; font-family:serif !important;" | |||
| 0x0A6 | |||
| 0x02 | |||
| colspan="2" | Empty | |||
|- | |||
| 0x0A8 | |||
| 0x02 | |||
| BatteryVoltageCalib | |||
| rowspan="2" style="text-align:left;" | Battery calibration data (for Abby) | |||
|- | |||
| 0x0AA | |||
| 0x02 | |||
| BatteryCurrentCalib | |||
|- style="font-style:italic; font-family:serif !important;" | |||
| 0x0AC | |||
| 0x14 | |||
| colspan="2" | Empty | |||
|- | |||
| 0x0C0 | |||
| 0x8 | |||
| TouchpanelFWVersion | |||
| style="text-align:left;" | [[SceSyscon#sceSysconGetTouchpanelDeviceInfoForDriver|Touchpanel Version info]] (4 <code>u16</code>s) | |||
|- | |||
| 0x0C8 | |||
| 0x4 | |||
| TouchpanelConfigVersion | |||
| style="text-align:left;" | 2 <code>u16</code>s | |||
|- style="font-style:italic; font-family:serif !important;" | |||
| 0x0CC | |||
| 0x4 | |||
| colspan="2" | Empty | |||
|- | |||
| 0x0D0 | |||
| 0x10 | |||
| TouchpanelLotInfo | |||
| style="text-align:left;" | 8 bytes for each panel | |||
|- | |||
| 0x0E0 | |||
| 0x4 | |||
| WlanBtHWRevision | |||
| style="text-align:left;" | WLAN/Bluetooth Hardware Revision | |||
|- style="font-style:italic; font-family:serif !important;" | |||
| 0x0E4 | |||
| 0x4 | |||
| colspan="2" | Empty | |||
|- | |||
| 0x0E8 | |||
| 0x6 | |||
| WlanMacAddress | |||
| style="text-align:left;" | WLAN MAC Address | |||
|- style="font-style:italic; font-family:serif !important;" | |||
| 0x0EE | |||
| 0x2 | |||
| colspan="2" | Empty | |||
|- | |||
| 0x0F0 | |||
| 0x6 | |||
| BtMacAddress | |||
| style="text-align:left;" | Bluetooth MAC Address (usually equal to WlanMacAddress + 1) | |||
|- style="font-style:italic; font-family:serif !important;" | |||
| 0x0F6 | |||
| 0xA | |||
| colspan="2" | Empty | |||
|- | |||
| 0x100 | |||
| 0x20 | |||
| BatteryLotInfo | |||
| style="text-align:left;" | ASCII string | |||
|- | |||
| 0x120 | |||
| 0x64 | |||
| | |||
| style="text-align:left;" | An ASCII string containing a date. | |||
|- | |||
| 0x184 | |||
| 0x10 | |||
| OLEDLotInfo | |||
| style="text-align:left;" | ASCII string | |||
|- | |||
| 0x194 | |||
| 0x10 | |||
| | |||
| style="text-align:left;" | An ASCII string (usually starting with TDA). | |||
|- style="font-style:italic; font-family:serif !important;" | |||
| 0x1A4 | |||
| 0x4 | |||
| colspan="2" | Empty | |||
|- | |||
| 0x1A8 | |||
| 0x20 | |||
| LcdModLotInfo | |||
| style="text-align:left;" | ASCII string | |||
|- style="font-style:italic; font-family:serif !important;" | |||
| 0x1C8 | |||
| 0x38 | |||
| colspan="2" | Empty | |||
|} | |||
== 0x104 == | == 0x104 == | ||
Line 188: | Line 617: | ||
== 0x110 - WlanRegion == | == 0x110 - WlanRegion == | ||
The following algorithm is used to derive | PS Vita IdStorage leaf 0x110 contains only 0x10 bytes of data. The first 3 bytes are the WlanRegion. The rest are FFed (unused). | ||
The following algorithm is used to derive WlanRegion from PsCode: | |||
<source lang="c"> | <source lang="c"> | ||
byte WlanRegion[3]; | byte WlanRegion[3]; | ||
switch(pscode.product_code) { | switch(pscode.product_code) { | ||
Line 225: | Line 656: | ||
WlanRegion[0] = 0xFF; | WlanRegion[0] = 0xFF; | ||
</source> | </source> | ||
In Manufacturing Mode, WlanRegion is spoofed to <code>FF 1F 00</code>. | |||
== 0x111 - WlanMacAddress == | == 0x111 - WlanMacAddress == | ||
Console-unique. The MAC address of the Wireless LAN adapter (6 bytes). | Console-unique. The MAC address of the Wireless LAN adapter (6 bytes). | ||
Example: | |||
* some PCH-1100: D4-4B-5E -> OUI belongs to Taiyo Yuden Co., Ltd. - a Japanese firm | |||
* some Blue PCH-1xxx / PCH-2000 : F8-2F-A8 -> OUIs belongs to Hon Hai Precision Ind. Co.,Ltd., also known as Foxconn | |||
* some PCH-2000 : 2C-33-7A / 70-77-81 / D4-6A-6A -> OUI belongs to Hon Hai Precision Ind. Co.,Ltd., also known as Foxconn | |||
== 0x112 - MtpSerial == | == 0x112 - MtpSerial == | ||
Console-unique. | Console-unique. | ||
First 0x40 bytes are the USB Driver Device Id. It is the serial number reported via the MTP protocol (32 UTF-16 characters). | |||
It is used by [[SceEnumWakeUp]]. | |||
== 0x113 == | == 0x113 == | ||
Console-unique on 3G units and empty on all others. Contains informations related to the 3G modem. | Console-unique on 3G units and empty on all others. Contains informations related to the 3G modem. | ||
* 0x136-0x136: ComNum | |||
== 0x114 - DeviceLocation == | == 0x114 - DeviceLocation == | ||
Line 263: | Line 707: | ||
== 0x115 - ProductTypeInfo == | == 0x115 - ProductTypeInfo == | ||
A string of 16 characters containing information about the product type. Followed by FFs. | |||
Leaf 0x115 is not present on PS Vita CEM-3000NE2 (dolphin). It is identical for all consoles "with the same SKU model". See [https://www.psdevwiki.com/vita/index.php/SKU_Models PS Vita SKU models]. | |||
Example values: | Example values: | ||
Line 269: | Line 715: | ||
* <code>PCH01004ZAZ20000</code> (PCH-1004 - Call of Duty: Black Ops Declassified limited edition) | * <code>PCH01004ZAZ20000</code> (PCH-1004 - Call of Duty: Black Ops Declassified limited edition) | ||
* <code>PCH01100AA010002</code> (Crystal Black PCH-1100 - docomo carrier) | * <code>PCH01100AA010002</code> (Crystal Black PCH-1100 - docomo carrier) | ||
* <code>PCH02000ZA120000</code> ( | * <code>PCH02000ZA120000</code> (PCH-2000 White) | ||
Decomposition: <code>FFFF NNNN PPPP xxx | Decomposition: <code>FFFF NNNN PPPP xxx y</code> | ||
* <code>FFFF-NNNN PPPP</code> is usually printed on the product's box | * <code>FFFF-NNNN PPPP</code> is usually printed on the product's box and on the console's shell, although there can be small differences | ||
** <code>FFFF</code> = family (e.g., PCH, PDEL) | ** <code>FFFF</code> = family (e.g., PCH, PDEL) padded with zeroes | ||
** <code>NNNN</code> = number (e.g., 1000, 1004, 1100) | ** <code>NNNN</code> = number (e.g., 1000, 1004, 1100) | ||
** <code>PPPP</code> = variant code (e.g., 0001, ZAZ2, AA01, ZA12) | ** <code>PPPP</code> = variant code (e.g., 0001, ZAZ2, AA01, ZA12) | ||
* <code>xxx</code> = | * <code>xxx</code> = padding (always "000") | ||
* <code> | * <code>y</code> = Product target operator (carrier ID for 3G models - usually matches offset 0x88 of IdStorage leaf 0x113 on SIM-locked models). | ||
** 1: US operator | ** 1: US operator | ||
** 2: JP operator | ** 2: JP operator |
Latest revision as of 21:07, 4 November 2024
See also [1].
Description
Region of the PSVita eMMC where perconsole info is stored.
Location
Idstorage data is stored at first raw partition (code 0x1). Use [2] to extract.
Structure
The IdStorage partition is divided in two parts: the mapping table and the leaves.
Mapping table
The mapping table is located at the start of the partition. It's an array of 16-bit leaf IDs that serves as a leaf ID->index mapping table. The mapping table must be at least one-sector wide but may be bigger.
There are two leaf IDs reserved for usage in the mapping table: all entries corresponding to the mapping table (i.e. the first M
entries for an M sectors sized table) must hold the value 0xFFF5
, and all unallocated leaves hold the value 0xFFFF
.
To lookup a leaf index based on its ID, use the following algorithm:
#define M /* implementation defined */
#define SECTOR_SIZE (512)
#define NUM_TABLE_ITEMS ((M * SECTOR_SIZE) / sizeof(uint16_t))
uint16_t g_mappingTable[NUM_TABLE_ITEMS];
int leafIndexFromId(unsigned id) {
if (id >= 0xFFF0)
return /* ERROR: invalid leaf ID */;
for (int i = 0; i < NUM_TABLE_ITEMS; i++) {
if (g_mappingTable[i] == id)
return i;
}
return /* ERROR: leaf ID is not in mapping table */;
}
Leaves
Leaves are sector-sized (512 bytes) areas in the IdStorage partition used to store arbitrary data. While the data stored may be smaller, a leaf always occupies one sector in the partition.
To read a leaf's data, obtain the leaf index (this can be known directly, or obtained from a leaf ID using the previously mentioned algorithm) then read 512 bytes starting at offset 512 * leafIndex
in the IdStorage partition.
Limits
The number of leaves that can be stored in an IdStorage partition is limited by three factors: the size of the partition, the size of the mapping table and the size of leaf IDs.
- An
M
sectors wide mapping table can hold up to255 * M
leaves- This is because a single-sector mapping table can reference
SECTOR_SIZE/sizeof(u16) - 1 = 255
leaves (the- 1
is needed because a table consumes one entry for itself)
- This is because a single-sector mapping table can reference
- A
P
sectors wide partition can hold up toP - M
leaves- This is because leaves are sector-sized, and the mapping table consumes
M
sectors
- This is because leaves are sector-sized, and the mapping table consumes
- There are 65520 leaf IDs available
- While an unsigned 16-bit variable can hold 65536 values, IDs superior or equal to 0xFFF0 are reserved and cannot be used
From this, we can conclude that an IdStorage partition of P
sectors with an M
sectors mapping table can hold up to min(255*M, P-M, 65520)
leaves. We can also deduce an IdStorage partition is optimally shaped (no space is non-allocatable) when P = 256 * M
.
On Vita, the IdStorage partition is 512KiB and 32 sectors are reserved for the indexing table (P = 1024, M = 32
, a non-optimal choice), which means the console's partition can hold up to 992 IdStorage leaves.
Leaf content
In this section, the following conventions and terms are used:
- Empty: area has all bits set to 1 (i.e., 0xFF)
- Present / Not present: the leaf exists in IdStorage partition
- The content of a leaf always starts at offset 0.
- If leaf contents are smaller than 512 bytes, the unused parts are left empty.
- Strings are padded with NUL bytes if the content is smaller than maximum size, but may be non-NUL terminated
Leaves not listed in this section have not been found in any unit, and leaves listed in this section are not all found in every unit.
The following information may not be valid for all pre-production units (DEM/CEM).
Idps certificates
Leaves 0x000~0x07F are written to IdStorage during manufacturing by a function called _writeIdpsCert
.
Leaf 0x07E contains the SHA-256 digest of leaves 0x000~0x07D, signed using RSA-2048.
The public key used for signature verification can be found in factTest.self
.
Leaf 0x07F is not covered by the signature but is flashed by _writeIdpsCert
nonetheless.
0x000~0x03F - PSP leaves
PSP leaves 0x100~0x13F (read using sceCompatIdStorageLookup
) are mapped to these PS Vita leaves instead (i.e., Vita leaf X
contains PSP leaf 0x100 + X
).
Like on a real PSP, this area is duplicated: leaves 0x000~0x01F are identical to 0x020~0x03F. Only the first half will be described.
0x000~0x007 - SceIdStoragePspCertificates
Identical across all units.
0x008~0x01F
Unused. Always all zeroes.
0x040~0x047 - SceIdStoragePsp2Certificates
Console-unique.
0x048~0x04F
Console-unique. Maybe UMD certificates like in PSP IdStorage.
0x050~0x07D
Unused. Always all zeroes.
0x07E
Console-unique.
The RSA-2048 signature of the Idps certificates (2048 bits/256 bytes) is located at offset 0x60 of this leaf.
Data contained between 0x0 and 0x5F is unknown, and data between 0x160 and 0x1FF is unused (always 00).
0x07F
Unused. Always all zeroes.
0x80 - SMI
Service / Manufacturing Information (SMI)
Console-unique. Contains minimal firmware version (checked in second_loader
).
/**
* The SMI leaf can be divided in three areas:
* - offset 0x000~0x07F: plaintext area
* - offset 0x080~0x0FF: payload area
* - offset 0x100~0x1FF: signature area
*/
struct SMILeaf {
/** SMI Magic: Must be "SMI\0" */
uint8_t magic[4];
/** SMI Version: Must be 1 */
uint32_t version;
/**
* Minimal firmware version, in plaintext
* This is ignored by second_loader.
*/
uint32_t minfw_plaintext;
/**
* Padding up to offset 0x80 (payload area).
* Checked by second_loader to be all zeroes.
*/
uint8_t must_be_zero[0x80 - 0xC];
/**
* Minimal firmware version allowed to run on unit.
* Must be higher or equal to the version contained
* in second_loader, or panic() will be called.
*/
uint32_t manuSdkVersion;
/**
* Padding up to offset 0x100 (signature area).
* ?Must be all zeroes but not checked?
*/
uint8_t unused[0x100 - 0x84];
/** Signature area */
uint8_t signature[0x100];
};
Encryption and signature
To prevent modification or transplantation, the SMI leaf is encrypted (AES-CBC-256) using per-console keyslot 0x213 and signed by SCE.
- The plaintext area (
0x000~0x07F
) is not encrypted - The payload area (
0x080~0x0FF
) is encrypted twice- The first layer of encryption (outer encryption) is also applied to the signature area
- The second layer of encryption (inner encryption) is only applied to this area
- The signature area is only encrypted once
- It contains the SHA-256 hash of plaintext area + inner-encrypted! payload area, signed by SCE (?2048-bit? RSA)
To decrypt an SMI leaf, perform the following:
- Derive the
Outer Decryption Key
by encrypting theOuter Key Seed
buffer using AES-CBC-256 (Key: keyslot 0x213; IV:Outer Key Derivation IV
) - Decrypt the payload and signature area using AES-CBC-256 (Key =
Outer Decryption Key
, IV =Outer Decryption IV
) - Verify the SMI signature (optional)
- Compute SHA-256 of plaintext area + outer-decrypted payload area
- Verify computed hash using data in signature area and the
SMI Verification Public Key
- Derive the
Inner Decryption Key
by encrypting theInner Key Seed
buffer using AES-CBC-256 (Key: keyslot 0x213; IV:Inner Key Derivation IV
) - Decrypt the payload area (with Outer Encryption removed) using AES-CBC-256 (Key:
Inner Decryption Key
, IV:Inner Decryption IV
)
(N.B.: the Outer Key Seed
, Outer Key Derivation IV
, Outer Decryption IV
, SMI Verification Public Key
, Inner Key Seed
, Inner Key Derivation IV
and Inner Decryption IV
are hardcoded in Second Loader)
0x100
Name may be Idlog
.
Console-unique. Two strings related to manufacturing.
Both strings are 0x100 bytes wide; one starts at offset 0 and one at offset 0x100.
The string at offset 0x100 is written at a different stage (end of manufacturing?) than the string at offset 0, so it is possible to find units with only first string written (e.g., a Dolphin CEM-3000 unit).
0x102
Console-unique. Per-console factory/service product information.
typedef struct {
u32 server_ip;
u16 server_port;
u8 netmask; //Number of '1' bits in netmask
u8 unused;
u32 client_ip;
u32 defaultGW;
} conn_param;
struct Leaf0x102 {
u32 unk0;
u32 unk4;
struct {
u8 id;
u8 state;
} ProcessId[0x20];
char gcpId[0x20];
char productId[0x20];
//The following fields indicate the number of X present in unit
struct {
u8 ComNum; //Com (3G module)
u8 WlanNum; //Ethernet is also counted in here, despite field name
u8 BtNum; //Bluetooth
u8 BatteryNum;
u8 HdmiNum;
u8 CpNum; //Communication Processor
struct { //Guessed field names
u8 Front;
u8 Back;
} CameraNum;
struct { //Guessed field names
u8 Front;
u8 Back;
} TouchNum;
u8 SixSenseNum; //Gyro
u8 EMagNum; //Magnetometer / Compass
u8 GpsNum;
u8 AnaDevNum; //a.k.a. Analog Pad (AP) or Joystick
u8 DisplayNum;
u8 SimNum; //SIM slot
} DeviceNum;
u8 SimPackNum; //Prepaid SIM card
u8 ComType;
u8 unused_9A[14];
u32 contentsVer; //spkgInfo.version from sceSblUsGetSpkgInfo(0x18)
u8 unk_AC[4];
u8 unk_B0;
u8 unused_B1[0x7];
u8 unk_B8;
u8 unused_B9[0x7];
conn_param conn_param_0; //For WLAN test?
conn_param conn_param_1; //For Ethernet test?
char ssid[0x20]; //SSID of AP used for WLAN test
u8 test_bt_addr[6]; //Bluetooth MAC address for BT test
u8 unused_106[2];
char ImeiBarcode[32];
char PartsNoBardcode[16];
char Imsi[16];
char IccId[20];
u8 unused_15C[4];
//Version of the software executed on the unit
//during manufacturing. Each element of the array
//corresponds to a different program.
u32 softVer[3];
u8 unused_16C[4];
struct {
char essid[12];
u8 channel;
} WlanTestApInfo;
u8 unused_17D[3];
u16 WlanRssi;
u8 unused_182[6];
//Obtained from sceSblUsGetSpkgInfo(0x1C), which
//corresponds to preinstall data patch Spkg.
//First 4 bytes = spkgInfo.version
//Fifth byte = spkgInfo.status[1]
u8 CustomThemeVersion[5];
u8 unused_18D[3];
//If set, clears itself at some point during
//factTest and skips something
u8 ConfigProcessJumpFlag;
u8 unused_191[111];
};
ProcessId
The ProcessId
field is an ID->status mapping table used to store on the unit the success or failure of various operations ("processes") performed during manufacturing.
Process ID | Description | Notes |
---|---|---|
0 | Unknown | |
1 | KervDiagResultFlag check
|
Check if KervDiagResultFlag (NVS 0x484) is 1 |
2 | First Image Update
(
|
Performed by 1st image writing phase psp2config.skprx firmware.
The |
3 | Manual(DISP)
|
Display-related tests?
Related to |
4 | _wlanTest
|
Tests that WLAN hardware is functional (connects to WLAN AP specified in conn_param_0 ?)
|
5 | _btTest
|
Tests that Bluetooth hardware is functional |
6 | Unknown | |
7 | Manual(TP)
|
Touch panel tests? |
8 | PSP Compatibility | Tests that PSP Compatibilty hardware is functional (done in compat_diag.skprx )
|
9~25 | Unknown | |
0x1A / 26 | vshTest ?
|
|
0x1B / 27 | peri1 Firmware Update
( |
Which peripheral this corresponds to is unknown. |
0x1C / 28 | Touch Panel Firmware Update
( |
Skipped(?) if TP HW Info doesn't match check_pre_cond.conf file on Memory Card.
|
0x1D / 29 | peri3 Firmware Update
( |
Which peripheral this corresponds to is unknown. |
0x1E / 30 | ?Reset Image? Update
( |
These PUPs are assumed to be those with reset image psp2config.skprx
|
0x1F / 31 | ?2nd Image? Update | 2nd Image is assumed to be firmware the unit is shipped with ("Retail").
This ProductId is mentioned as |
State | Description |
---|---|
For tests | |
0x00 | Test not attempted |
0x01 | Test OK |
0x02 | Test NG - ignored
(NG ignored by operator) |
0x03 | Test skipped |
0x04 | Test NG |
For updates | |
0x00
0x09 0xFF |
fresh input
|
0x01 | already update
|
0x04 | failed update
|
0x103
Console-unique. Unit hardware information.
Offset | Size | Name | Description |
---|---|---|---|
0x000 | 0x4 | ErnieHwInfo | Ernie (Syscon) Hardware Information |
0x004 | 0x4 | ErnieFwVersion | Ernie Firmware Version (also called Ernie Verison) |
0x008 | 0x4 | ErnieDlVersion | ErnieDlVersion |
0x00C | 0x2 | ErnieCfgVersion | Can be obtained with SceSyscon#sceSysconGetConfigStorageInfoForDriver. |
0x00E | 0x12 | Empty | |
0x020 | 0x8 | EmmcFwVersion | Vendor ID (1 byte), empty space (1 byte) and Device Version (6 bytes) |
0x028 | 0x8 | Empty | |
0x030 | 0x8 | EmmcFwVersion2 | Vendor ID (1 byte), Device Version (6 bytes) and an additional byte (for Samsung eMMC, 0 otherwise) |
0x038 | 0x8 | Empty | |
0x040 | 0x2 | ElmoFWVer | Elmo Firmware Version |
0x042 | 0x1E | Empty | |
0x060 | 0x2 | CookieFWVer | Cookie Firmware Version |
0x062 | 0x1E | Empty | |
0x080 | 0x2 | BarkleyFwVersion | Motion Device Firmware Version/Hardware Information |
0x082 | 0x2 | BarkleyHwInfo | |
0x084 | 0x1C | Empty | |
0x0A0 | 0x2 | AbbyHWVersion | Abby HW/FW/DF Version |
0x0A2 | 0x2 | AbbyFWVersion | |
0x0A4 | 0x2 | AbbyDFVersion | |
0x0A6 | 0x02 | Empty | |
0x0A8 | 0x02 | BatteryVoltageCalib | Battery calibration data (for Abby) |
0x0AA | 0x02 | BatteryCurrentCalib | |
0x0AC | 0x14 | Empty | |
0x0C0 | 0x8 | TouchpanelFWVersion | Touchpanel Version info (4 u16 s)
|
0x0C8 | 0x4 | TouchpanelConfigVersion | 2 u16 s
|
0x0CC | 0x4 | Empty | |
0x0D0 | 0x10 | TouchpanelLotInfo | 8 bytes for each panel |
0x0E0 | 0x4 | WlanBtHWRevision | WLAN/Bluetooth Hardware Revision |
0x0E4 | 0x4 | Empty | |
0x0E8 | 0x6 | WlanMacAddress | WLAN MAC Address |
0x0EE | 0x2 | Empty | |
0x0F0 | 0x6 | BtMacAddress | Bluetooth MAC Address (usually equal to WlanMacAddress + 1) |
0x0F6 | 0xA | Empty | |
0x100 | 0x20 | BatteryLotInfo | ASCII string |
0x120 | 0x64 | An ASCII string containing a date. | |
0x184 | 0x10 | OLEDLotInfo | ASCII string |
0x194 | 0x10 | An ASCII string (usually starting with TDA). | |
0x1A4 | 0x4 | Empty | |
0x1A8 | 0x20 | LcdModLotInfo | ASCII string |
0x1C8 | 0x38 | Empty |
0x104
Console-unique. Test/diagnostic results.
This leaf is only present if diagnostic software has been executed on the unit or some factory tests failed.
0x110 - WlanRegion
PS Vita IdStorage leaf 0x110 contains only 0x10 bytes of data. The first 3 bytes are the WlanRegion. The rest are FFed (unused).
The following algorithm is used to derive WlanRegion from PsCode:
byte WlanRegion[3];
switch(pscode.product_code) {
case 0x100:
case 0x101:
case 0x102:
case 0x104:
case 0x10B:
case 0x10F:
case 0x110:
case 0x111:
WlanRegion[2] = 0;
WlanRegion[1] = 7;
break;
case 0x103:
case 0x106:
case 0x108:
case 0x10A:
case 0x10D:
case 0x10E:
WlanRegion[2] = 0;
WlanRegion[1] = 0x1F;
break;
case 0x105:
case 0x107:
case 0x109:
case 0x10C:
WlanRegion[2] = 1;
WlanRegion[1] = 0x1F;
break;
default:
goto error;
}
WlanRegion[0] = 0xFF;
In Manufacturing Mode, WlanRegion is spoofed to FF 1F 00
.
0x111 - WlanMacAddress
Console-unique. The MAC address of the Wireless LAN adapter (6 bytes).
Example:
- some PCH-1100: D4-4B-5E -> OUI belongs to Taiyo Yuden Co., Ltd. - a Japanese firm
- some Blue PCH-1xxx / PCH-2000 : F8-2F-A8 -> OUIs belongs to Hon Hai Precision Ind. Co.,Ltd., also known as Foxconn
- some PCH-2000 : 2C-33-7A / 70-77-81 / D4-6A-6A -> OUI belongs to Hon Hai Precision Ind. Co.,Ltd., also known as Foxconn
0x112 - MtpSerial
Console-unique.
First 0x40 bytes are the USB Driver Device Id. It is the serial number reported via the MTP protocol (32 UTF-16 characters).
It is used by SceEnumWakeUp.
0x113
Console-unique on 3G units and empty on all others. Contains informations related to the 3G modem.
- 0x136-0x136: ComNum
0x114 - DeviceLocation
Identical for all consoles of a generation (one kind for Fat, one kind for Slim, empty on PSTV).
Contains four struct DeviceLocation
s describing the location of physical devices in the unit.
struct DeviceLocation { //size is 0x10 bytes
//0x00 - Front camera
//0x01 - Back camera
//0x10 - Accelerometer
//0x11 - Gyro
uint32_t type;
int32_t x;
int32_t y;
int32_t z;
};
The structures are usually found in the following order: Cameras followed by Motion (Acc + Gyro).
There is also an unknown int32 flag at offset 0x100.
0x115 - ProductTypeInfo
A string of 16 characters containing information about the product type. Followed by FFs.
Leaf 0x115 is not present on PS Vita CEM-3000NE2 (dolphin). It is identical for all consoles "with the same SKU model". See PS Vita SKU models.
Example values:
PDEL100000010000
(PDEL-1000)PCH01004ZAZ20000
(PCH-1004 - Call of Duty: Black Ops Declassified limited edition)PCH01100AA010002
(Crystal Black PCH-1100 - docomo carrier)PCH02000ZA120000
(PCH-2000 White)
Decomposition: FFFF NNNN PPPP xxx y
FFFF-NNNN PPPP
is usually printed on the product's box and on the console's shell, although there can be small differencesFFFF
= family (e.g., PCH, PDEL) padded with zeroesNNNN
= number (e.g., 1000, 1004, 1100)PPPP
= variant code (e.g., 0001, ZAZ2, AA01, ZA12)
xxx
= padding (always "000")y
= Product target operator (carrier ID for 3G models - usually matches offset 0x88 of IdStorage leaf 0x113 on SIM-locked models).- 1: US operator
- 2: JP operator
- 3: EU generic
- 4: Asia generic
- 5: Canada operator
- 6: Mexico generic
0x116 - ColorVariation
Used for wave color by SceShell if present. (Patch example)
struct ColorVariation {
uint8_t unk0;
uint16_t unk1; //maybe just two uint8_t?
uint8_t unk3;
/* rest of the leaf is empty */
};
Example values:
- Call of Duty: Black Ops Declassified limited edition PCH-1004:
{ 0x01, 0x0000, 0x00 }
- Glacier White PCH-2000 / White PSTV:
{ 0x01, 0x000C, 0x00 }
0x117 - TemperatureThreashold
The typo in this leaf's name is present in SCE code.
Contains 4 elements of 1 byte each, which are always all zeroes when the leaf is present.
Sent to Syscon?
0x118 - AudioParam
1 byte. If set to 0 (or the leaf is absent?), AVLS is never forcefully enabled.
Should be 0x0 except on units with PsCode Product Code 0x105 (Europe/East/Africa), 0x107 (Great Britain/United Kingdom) or 0x109 (Australia/New Zealand).
0x119 - EtherMacAddress
Console-unique. The MAC address of the Ethernet adapter (6 bytes).
Empty or not present for non-PSTV units.
0x11A - WebBrowserParam
1 byte.
Seen: 0x02 on PCH200X, 0x11 on PSTV
Should be 0x1 on Fat CEX/DEX, 0x2 on Slim, 0x11 on PSTV and 0x0 on all other units.
0x11B - ShutterParam
1 byte. When leaf is present and contains 0x01, the value returned by sceAVConfigGetShutterVol()
changes from 30 to 26.
Seen: 0x01 on PCH200X, 0x00 on PSTV.
Should be 0x1 on Slim units and 0x0 on all others.
0x11C - LedInfoParam
1 byte.
Seen: 0x01 on PCH200X, 0x00 on PSTV
Should be 0x1 on Slim units and 0x0 on all others.