IdStorage: Difference between revisions

From Vita Development Wiki
Jump to navigation Jump to search
(→‎Content: Refactor leaf content section & add documentation)
Line 60: Line 60:
On Vita, the IdStorage partition is 512KiB and 32 sectors are reserved for the indexing table (<code>P = 1024, M = 32</code>, a non-optimal choice), which means the console's partition can hold '''up to 992 IdStorage leaves'''.
On Vita, the IdStorage partition is 512KiB and 32 sectors are reserved for the indexing table (<code>P = 1024, M = 32</code>, a non-optimal choice), which means the console's partition can hold '''up to 992 IdStorage leaves'''.


= Content =
= Leaf content =


== Table of leaves ==
Leaves not present in this section have not been found in any unit.


{| class="wikitable"
In the following section, "empty" means that the area has all bits set to 1 (i.e., 0xFF).
|-
"Present"/"Not present" means whether or not a leaf exists in IdStorage.
! Leaf Index !! Empty? !! Unique? !! Notes
 
|-
When a size is indicated, this means only the first X bytes of the leaf are used, and the rest is empty.
| 0x00->0x07 || No || No || SceIdStoragePspCertificates
 
|-
The following information may not be valid for pre-production units.
| 0x08->0x1F || Yes || No ||
 
|-
== 0x000~0x007 ==
| 0x20->0x27 || Yes || No || This is equal to SceIdStoragePspCertificates from  leaf 0x00 to 0x07.
 
|-
SceIdStoragePspCertificates
| 0x28->0x3F || Yes || No ||
 
|-
Identical across all units and duplicated in leaves 0x020 to 0x027.
| 0x40->0x47 || No || Yes || SceIdStoragePsp2Certificates
 
|-
== 0x040~0x047 ==
| 0x48->0x4F || No || Yes || It looks like a cert, but it may actually be useless data.
 
|-
SceIdStoragePsp2Certificates.
| 0x50->0x7D || Yes || No ||
 
|-
Console-unique.
| 0x7E || No || Yes ||
 
|-
== 0x048~0x04F ==
| 0x7F || Yes || No ||
 
|-
Console-unique. May be certificate(s).
| 0x80 || No || Yes || Special leaf with "SMI" header. SMI data: factory firmware encrypted and signed. Contains minver at offset 0x08 (size 4 bytes).
 
|-
== 0x07E ==
| 0x100 || No || Yes || Build data strings.
 
|-
Console-unique.
| 0x102 || No || Yes || Like idstorage mgmt data, Some strings, Like some flags, And like mac address, Maybe more?
 
|-
== 0x80 ==
| 0x103 || No || Yes || Hw info, Syscon version (include DL verstion), Production date, Mac address, Mac address (USB), some strings, and more.
 
|-
Service / Manufacturing Information (SMI)
| 0x104 || No || Yes || Diagnosis result. Probably only present on PS Vitas repaired by Sony.
 
|-
Console-unique. Contains minimal firmware version (checked in [[Second Loader|<code>second_loader</code>]]).
| 0x110 || No || Yes || Manufacturing flags (3 byte) + 0xFF padding.
 
|-
<source lang="c">
| 0x111 || No || Yes || Mac address (6 byte) + 0xFF padding.
struct SMILeaf {
|-
    uint8_t magic[4]; //'SMI\0'
| 0x112 || No || Yes || Serial number wide strings.
    uint32_t version; //1
|-
    uint32_t min_fwv; //Minimal firmware version
| 0x113 || No || Yes || IMEI and other 3g data on 3G, 0xFFed on other models
    uint8_t unused[0x80 - 0xC];
|-
    //Encrypted with per-console keys.
| 0x114 || No || Yes || some data (0x40 byte) + 0xFF padding.
    //This is used to verify the leaf has not been modified.
|-
    uint8_t encrypted_data[0x200 - 0x80];
| 0x115 || No || Yes || Model strings + 0xFF padding.
};
|-
</source>
|}
 
== 0x100 ==
 
Console-unique. Build data strings. One string starts at offset 0, and one string starts at offset 0x100. Both strings are 0x100 characters long.
 
In a 0.920 minfw unit, this leaf instead contains 0x0 at offset 0, 0x10 at offset 0x10, etc up to offset 0xF0, while all other bytes are zeroes.
 
== 0x102 ==
 
Console-unique. Per-console factory/service product information.
 
== 0x103 ==
 
Console-unique. Hardware information.
 
== 0x104 ==
 
Console-unique. Diagnostic results.
 
Not present if diagnostic software has not been executed on the unit.
 
== 0x110 ==
 
WlanRegion (3 bytes)
 
The following algorithm is used to derive it from PsCode:
<source lang="c">
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;
</source>
 
== 0x111 ==
 
WlanMacAddress (6 bytes)
 
Console-unique. The MAC address of the Wireless LAN adapter.
 
== 0x112 ==
 
MtpSerial (<code>wchar_t[0x20]</code>)
 
Console-unique. The serial number sent via the MTP protocol.
 
== 0x113 ==
 
Console-unique. Information related to the 3G modem.
 
Empty on non-3G models.
 
== 0x114 ==
 
DeviceLocation?
 
Identical for all consoles of a generation (one kind for Fat, one kind for Slim).
 
Empty on PSTV.
 
== 0x115 ==
 
ProductTypeInfo (<code>char[16]</code>)
 
Identical for consoles of the same "type".
 
Example values:
* <code>PDEL100000010000</code> (PDEL-1000)
* <code>PCH01004ZAZ20000</code> (PCH-1004 - Call of Duty: Black Ops Declassified limited edition)
* <code>PCH01100AA010002</code> (Black PCH-1100 - docomo carrier)
* <code>PCH02000ZA120000</code> (Glacier White PCH-2000)
 
== 0x116 ==
 
ColorVariation (4 bytes)
 
Not present on all units.
 
<source lang="c">
struct ColorVariation {
    uint8_t unk0;
    uint16_t unk1;
    uint8_t unk3;
    /* rest of the leaf is empty */
};
</source>
 
Example values:
* Call of Duty: Black Ops Declassified limited edition PCH-1004: <code>{ 0x01, 0x0000, 0x00 }</code>
* Glacier White PCH-2000 <code>{ 0x01, 0x000C, 0x00 }</code>
 
== 0x117 ==
 
TemperatureThreashold[https://en.wikipedia.org/wiki/Sic <sup>[sic<nowiki>]</nowiki></sup>] (4 elements of 1 byte each)
 
Not present on all units, and always all zeroes when present.
 
== 0x118 ==
 
AudioParam (1 byte)
 
Not present on all units.
 
If set to 0 (or the leaf is absent?), AVLS is never forcefully enabled.
 
== 0x119 ==
 
EtherMacAddress (6 bytes)
 
Console-unique. The MAC address of the Ethernet adapter.
 
Present on PSTV and PCH-2000 (where it is empty).
 
== 0x11A ==
 
WebBrowserParam (1 byte)
 
Can be 0/1/2/0x11?
 
Never seen in the wild. Maybe used on IDU units?
 
== 0x11B ==
 
ShutterParam (1 byte)
 
Never seen in the wild. Maybe used to disable the shutter sound?
 
== 0x11C ==
 
LedInfoParam (1 byte)
 
Never seen in the wild.
 
== Zeroed leaves ==
 
The following leaves are present in IdStorage, but seem to always contain zeroes:
* 0x008~0x01F
* 0x028~0x03F
* 0x050~0x07D
* 0x7F

Revision as of 01:31, 21 December 2023

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 to 255 * 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)
  • A P sectors wide partition can hold up to P - M leaves
    • This is because leaves are sector-sized, and the mapping table consumes M sectors
  • 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

Leaves not present in this section have not been found in any unit.

In the following section, "empty" means that the area has all bits set to 1 (i.e., 0xFF). "Present"/"Not present" means whether or not a leaf exists in IdStorage.

When a size is indicated, this means only the first X bytes of the leaf are used, and the rest is empty.

The following information may not be valid for pre-production units.

0x000~0x007

SceIdStoragePspCertificates

Identical across all units and duplicated in leaves 0x020 to 0x027.

0x040~0x047

SceIdStoragePsp2Certificates.

Console-unique.

0x048~0x04F

Console-unique. May be certificate(s).

0x07E

Console-unique.

0x80

Service / Manufacturing Information (SMI)

Console-unique. Contains minimal firmware version (checked in second_loader).

struct SMILeaf {
    uint8_t magic[4]; //'SMI\0'
    uint32_t version; //1
    uint32_t min_fwv; //Minimal firmware version
    uint8_t unused[0x80 - 0xC];
    //Encrypted with per-console keys.
    //This is used to verify the leaf has not been modified.
    uint8_t encrypted_data[0x200 - 0x80];
};

0x100

Console-unique. Build data strings. One string starts at offset 0, and one string starts at offset 0x100. Both strings are 0x100 characters long.

In a 0.920 minfw unit, this leaf instead contains 0x0 at offset 0, 0x10 at offset 0x10, etc up to offset 0xF0, while all other bytes are zeroes.

0x102

Console-unique. Per-console factory/service product information.

0x103

Console-unique. Hardware information.

0x104

Console-unique. Diagnostic results.

Not present if diagnostic software has not been executed on the unit.

0x110

WlanRegion (3 bytes)

The following algorithm is used to derive it 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;

0x111

WlanMacAddress (6 bytes)

Console-unique. The MAC address of the Wireless LAN adapter.

0x112

MtpSerial (wchar_t[0x20])

Console-unique. The serial number sent via the MTP protocol.

0x113

Console-unique. Information related to the 3G modem.

Empty on non-3G models.

0x114

DeviceLocation?

Identical for all consoles of a generation (one kind for Fat, one kind for Slim).

Empty on PSTV.

0x115

ProductTypeInfo (char[16])

Identical for consoles of the same "type".

Example values:

  • PDEL100000010000 (PDEL-1000)
  • PCH01004ZAZ20000 (PCH-1004 - Call of Duty: Black Ops Declassified limited edition)
  • PCH01100AA010002 (Black PCH-1100 - docomo carrier)
  • PCH02000ZA120000 (Glacier White PCH-2000)

0x116

ColorVariation (4 bytes)

Not present on all units.

struct ColorVariation {
    uint8_t unk0;
    uint16_t unk1;
    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 { 0x01, 0x000C, 0x00 }

0x117

TemperatureThreashold[sic] (4 elements of 1 byte each)

Not present on all units, and always all zeroes when present.

0x118

AudioParam (1 byte)

Not present on all units.

If set to 0 (or the leaf is absent?), AVLS is never forcefully enabled.

0x119

EtherMacAddress (6 bytes)

Console-unique. The MAC address of the Ethernet adapter.

Present on PSTV and PCH-2000 (where it is empty).

0x11A

WebBrowserParam (1 byte)

Can be 0/1/2/0x11?

Never seen in the wild. Maybe used on IDU units?

0x11B

ShutterParam (1 byte)

Never seen in the wild. Maybe used to disable the shutter sound?

0x11C

LedInfoParam (1 byte)

Never seen in the wild.

Zeroed leaves

The following leaves are present in IdStorage, but seem to always contain zeroes:

  • 0x008~0x01F
  • 0x028~0x03F
  • 0x050~0x07D
  • 0x7F