IdStorage: Difference between revisions

From Vita Development Wiki
Jump to navigation Jump to search
(→‎Structure: Add detailed explanations on layout and limits)
Line 11: Line 11:
= Structure =
= Structure =


On PSVita, max 993 leaves exist. Many leaves are empty, Some are empty, others are unique, and there are others which are duplicated. All leaves are of size 512 bytes.
The IdStorage partition is divided in two parts: the mapping table and the leaves.


First 0x20 * 0x200 bytes of the IDStorage eMMC partition is the index table, an array of 2-byte integers, which maps idstorage leaf to idstorage index. To find the index of a leaf, go through the array and note index of the element with the value of the desired leaf. Then, seek to <code>512 * index</code> and read out the leaf data.
== 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 <code>M</code> entries for an </code>M</code> sectors sized table) must hold the value <code>0xFFF5</code>, and all unallocated leaves hold the value <code>0xFFFF</code>.
 
To lookup a leaf index based on its ID, use the following algorithm:
<source lang="C">
#define M /* implementation defined */
 
#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 */;
}
</source>
 
== Leaves ==
 
Leaves are used to store arbitrary data. On Vita, leaves are all 512-bytes sized (one sector).
 
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 <code>512 * leafIndex</code> 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 <code>M</code> sectors wide mapping table can hold up to <code>255 * M</code> leaves
** This is because a single-sector mapping table can hold <code>SECTOR_SIZE/sizeof(u16) - 1 = 255</code> leaves (<code>- 1</code> is needed because the table uses an entry for itself)
* A <code>P</code> sectors wide partition can hold up to <code>P - M</code> leaves
** This is because leaves are sector-sized, and the mapping table consumes <code>M</code> 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 <code>P</code> sectors with an <code>M</code> sectors mapping table can hold up to <code>min(255*M, P-M, 65520)</code> leaves. We can also deduce an IdStorage partition is optimally shaped (no space is non-allocatable) when <code>P = 256 * N</code>.
 
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 =
= Content =

Revision as of 15:22, 6 January 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 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 used to store arbitrary data. On Vita, leaves are all 512-bytes sized (one sector).

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 hold SECTOR_SIZE/sizeof(u16) - 1 = 255 leaves (- 1 is needed because the table uses an 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 * N.

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.

Content

Table of leaves

Leaf Index Empty? Unique? Notes
0x00->0x07 No No SceIdStoragePspCertificates
0x08->0x1F Yes No
0x20->0x27 Yes No This is equal to SceIdStoragePspCertificates from leaf 0x00 to 0x07.
0x28->0x3F Yes No
0x40->0x47 No Yes SceIdStoragePsp2Certificates
0x48->0x4F No Yes It looks like a cert, but it may actually be useless data.
0x50->0x7D Yes No
0x7E No Yes
0x7F Yes No
0x80 No Yes Special leaf with "SMI" header. SMI data: factory firmware encrypted and signed. Contains minver at offset 0x08 (size 4 bytes).
0x100 No Yes Build data strings.
0x102 No Yes Like idstorage mgmt data, Some strings, Like some flags, And like mac address, Maybe more?
0x103 No Yes Hw info, Syscon version (include DL verstion), Production date, Mac address, Mac address (USB), some strings, and more.
0x110 No Yes Manufacturing flags (3 byte) + 0xFF padding.
0x111 No Yes Mac address (6 byte) + 0xFF padding.
0x112 No Yes Serial number wide strings.
0x113 No Yes 0xFFed.
0x114 No Yes some data (0x40 byte) + 0xFF padding.
0x115 No Yes Model strings + 0xFF padding.