IdStorage: Difference between revisions
m (Fix typos, add SECTOR_SIZE define in code, change leaf description) |
|||
Line 22: | Line 22: | ||
<source lang="C"> | <source lang="C"> | ||
#define M /* implementation defined */ | #define M /* implementation defined */ | ||
#define SECTOR_SIZE (512) | |||
#define NUM_TABLE_ITEMS ((M * SECTOR_SIZE) / sizeof(uint16_t)) | #define NUM_TABLE_ITEMS ((M * SECTOR_SIZE) / sizeof(uint16_t)) | ||
Line 40: | Line 41: | ||
== Leaves == | == Leaves == | ||
Leaves are used to store arbitrary data. | 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 <code>512 * leafIndex</code> in the IdStorage 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 <code>512 * leafIndex</code> in the IdStorage partition. | ||
Line 49: | Line 50: | ||
* An <code>M</code> sectors wide mapping table can hold up to <code>255 * M</code> leaves | * 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 | ** This is because a single-sector mapping table can reference <code>SECTOR_SIZE/sizeof(u16) - 1 = 255</code> leaves (the <code>- 1</code> is needed because a table consumes one entry for itself) | ||
* A <code>P</code> sectors wide partition can hold up to <code>P - M</code> leaves | * 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 | ** This is because leaves are sector-sized, and the mapping table consumes <code>M</code> sectors | ||
Line 55: | Line 56: | ||
** While an unsigned 16-bit variable can hold 65536 values, IDs superior or equal to 0xFFF0 are reserved and cannot be used | ** 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 * | 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 * M</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'''. | 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'''. |
Revision as of 10:58, 18 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 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.
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. |
0x104 | No | Yes | Diagnosis result. Probably only present on PS Vitas repaired by Sony. |
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. |