Editing VTRM

Jump to navigation Jump to search
Warning: You are not logged in. Your IP address will be publicly visible if you make any edits. If you log in or create an account, your edits will be attributed to your username, along with other benefits.

The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then publish the changes below to finish undoing the edit.

Latest revision Your text
Line 1: Line 1:
The PS4 VTRM functionality seems to be similar with the one of the PS3. We can either dump it via HW or via SW method. Tools to unpack and dump the VTRM can be found here [http://www.psdevwiki.com/ps4/Flash-Main Tool] on the Top, under sources.
The PS4s VTRM functionality seems to be similar with the one from the PS3. We can either Dump them via HW or via Software methode. Tools to unpack and dump the VTRM can be found here [http://www.psdevwiki.com/ps4/Flash-Main Tool] on the Top, under sources.
 
On the PS4 a Dev/Test units only have one Region whilst a Retail unit has two Regions. One of those regions is used for deactivation and the other one for activation.
 
=== Region0 ===
 
SCEVTRM Magic on 0x380048.
 
The 0xFC in this example here mark the very first entry for a VTRM. Otherwise it would be 4 bytes either all 0x00 which means not in use or 0x03 0x00 0x00 0x00 which means in use. 0xFC is always tighten to 0x00 placed on offset 0x380050 and 0x380058 or in the second VTRM on 0x3A0050 and 0x3A0058 and it is the counter for activation and deactivation of the console. Following the counting: This means for every
 
uneven number == Activated
 
and for every
 
even number == Deactivated
 
or
 
If VTRM0 is marked as in use then the console is deactivated and if VTRM1 is marked as in use then PS4 is activated.
 
Following some examples. Remember mark 0xFC and count 0x00 == factory state.
 
'''Deactivated'''
{| class="wikitable"
|-
! Console A !! Console B !! Console C
|-
| <pre> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00380000  FC FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  üÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
00380010  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
00380020  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
00380030  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
00380040  01 00 00 00 FF FF FF FF 53 43 45 56 54 52 4D 00  ....ÿÿÿÿSCEVTRM.
00380050  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00380060  00 10 00 00 00 00 00 00 1D 00 00 00 00 00 00 00  ................
00380070  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ</pre> || <pre> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00380000  00 00 00 00 FF FF FF FF FF FF FF FF FF FF FF FF  üÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
00380010  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
00380020  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
00380030  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
00380040  01 00 00 00 FF FF FF FF 53 43 45 56 54 52 4D 00  ....ÿÿÿÿSCEVTRM.
00380050  16 00 00 00 00 00 00 00 16 00 00 00 00 00 00 00  ................
00380060  00 10 00 00 00 00 00 00 1D 00 00 00 00 00 00 00  ................
00380070  FF FF FF FF FF FF FF FF FC FF FF FF FF FF FF FF  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ</pre> || <pre> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00380000  00 00 00 00 FF FF FF FF FF FF FF FF FF FF FF FF  üÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
00380010  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
00380020  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
00380030  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
00380040  01 00 00 00 FF FF FF FF 53 43 45 56 54 52 4D 00  ....ÿÿÿÿSCEVTRM.
00380050  0E 00 00 00 00 00 00 00 0E 00 00 00 00 00 00 00  ................
00380060  00 10 00 00 00 00 00 00 1D 00 00 00 00 00 00 00  ................
00380070  FF FF FF FF FF FF FF FF FC FF FF FF FF FF FF FF  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ</pre>
|-
|}
 
So we have more ways to identify if a dump is from a Retail or a Dev/Test console. Either we can check if there are any incremental counters used on the VTRM or we can check if the VTRM has any mark like 0xFC or 0x00000000 or 0x03000000 then it is a Retail else Dev/Test. Or we also can check the first 4 bytes of both VTRMs against 4x 0xFF bytes, if true == Dev/Test else Retail.
 
NOTE: Dev/Test Consoles only do use one VTRM. The array for the second VTRM is completely empty on this SKU models beside that they don't have any mark and also no counter. (yea sure why if they only use one ^^)
 
NOTE²: There is another byte that will change during this process. On offset 0x3A0078 for factory the byte is 0xFF. As soon as the console would be the first time activated (so count 0x01) then this byte change to 0xFE. After this (so count 0x02 and upwards) the byte will always be 0xFC.
 
=== Region0 Digest? ===
 
This region of 0x60 bytes is the exact same on the same console of different FW and BIOS versions. We can use those 0x60 bytes to identify dumps as different or as from one and the same device. It's kind of a unique console identifier. I will add a new entry to the SystemFlash Extractor and hash this array with SHA1 which we then can use to store it in the DataBase. That gives us the ability to even identify a dump and its informations from the DataBase out as one and the same device or as a different one, while at same time to protect the privacy of the user in case we use a checksum to store and not the console specific unique value.
 
'''(From a already dead console)'''
Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00380170                          BE AF 32 B6 91 8A CF 6B          ¾¯2¶‘ŠÏk
00380180  87 67 90 C3 93 8B 71 A5 02 7D 24 B3 BA E3 C1 1F  ‡g.Ó‹q¥.}$³ºãÁ.  "
00380190  50 18 52 A2 70 B8 21 E7 C0 7E 2C CF B9 B5 19 BF  P.R¢p¸!çÀ~,Ϲµ.¿  "
003801A0  79 33 BA CF 8D 50 3D 03 32 BD 8A 25 00 DA A5 2B  y3ºÏ.P=.2½Š%.Ú¥+  "
003801B0  4B 1E 27 27 96 07 87 52 7F DD 05 ED A5 DA 51 C8  K.''–.‡R.Ý.í¥ÚQÈ    "
003801C0  AB F6 48 B9 08 FF CF 89 83 B2 76 37 51 75 8D 87  «öH¹.ÿωƒ²v7Qu.‡  "
003801D0  F8 A1 06 69 F7 73 58 36                          ø¡.i÷sX6          "
 
=== Region0 UserRegion ===
 
=== Region1 ===
 
SCEVTRM Magic on 0x3A0048
 
'''Activated'''
{| class="wikitable"
|-
! Console A !! Console B !! Console C
|-
| <pre> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00380000  03 00 00 00 FF FF FF FF FF FF FF FF FF FF FF FF  üÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
00380010  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
00380020  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
00380030  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
00380040  01 00 00 00 FF FF FF FF 53 43 45 56 54 52 4D 00  ....ÿÿÿÿSCEVTRM.
00380050  01 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00  ................
00380060  00 10 00 00 00 00 00 00 1D 00 00 00 00 00 00 00  ................
00380070  FF FF FF FF FF FF FF FF FE FF FF FF FF FF FF FF  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ</pre> || <pre> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00380000  03 00 00 00 FF FF FF FF FF FF FF FF FF FF FF FF  üÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
00380010  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
00380020  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
00380030  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
00380040  01 00 00 00 FF FF FF FF 53 43 45 56 54 52 4D 00  ....ÿÿÿÿSCEVTRM.
00380050  17 00 00 00 00 00 00 00 17 00 00 00 00 00 00 00  ................
00380060  00 10 00 00 00 00 00 00 1D 00 00 00 00 00 00 00  ................
00380070  FF FF FF FF FF FF FF FF FC FF FF FF FF FF FF FF  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ</pre> || <pre> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00380000  03 00 00 00 FF FF FF FF FF FF FF FF FF FF FF FF  üÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
00380010  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
00380020  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
00380030  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
00380040  01 00 00 00 FF FF FF FF 53 43 45 56 54 52 4D 00  ....ÿÿÿÿSCEVTRM.
00380050  0F 00 00 00 00 00 00 00 0F 00 00 00 00 00 00 00  ................
00380060  00 10 00 00 00 00 00 00 1D 00 00 00 00 00 00 00  ................
00380070  FF FF FF FF FF FF FF FF FC FF FF FF FF FF FF FF  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ</pre>
|-
|}
 
{| class="wikitable"
|-
! Console A, B !! Console C
|-
| <pre> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
003801D0                          FF FF FF FF FF FF FF FF          ÿÿÿÿÿÿÿÿ
003801E0  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
  [...]                filled FF region
003A0160  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
003A0170  FF FF FF FF FF FF FF FF                          ÿÿÿÿÿÿÿÿ</pre> || <pre> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
0039FFF0  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
003A0000  03 00 00 00 FF FF FF FF FF FF FF FF FF FF FF FF  ....ÿÿÿÿÿÿÿÿÿÿÿÿ
003A0010  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
  [...]                filled FF region
003A0040  01 00 00 00 FF FF FF FF 53 43 45 56 54 52 4D 00  ....ÿÿÿÿSCEVTRM.
003A0040  01 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00  ................
003A0040  00 10 00 00 00 00 00 00 1D 00 00 00 00 00 00 00  ................
003A0040  FF FF FF FF FF FF FF FF FE FF FF FF FF FF FF FF  ÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿ
003A0050  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
  [...]                filled FF region
003A0160  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
003A0170  FF FF FF FF FF FF FF FF                          ÿÿÿÿÿÿÿÿ</pre>
|-
|}
 
=== Region1 Digest? ===
 
The same like for Region0 applies here but with the difference that those both digest? from Region0 and Region1 do differ on the same console and also on different versions. But Region0 do match Region0 of different FW and BIOS versions and the same applies for Region1. Those 0x60 bytes from Region1 are always the same on different FW and BIOS versions of the same console.
 
=== Region1 UserRegion ===


== Structure ==
== Structure ==
==== Header ====
* size is always 0x80 bytes
* integer values are endian swapped
{| class="wikitable"
|-
! From !! To !! Description
|-
| 00 || 03 || '''Flag''' Marks the VTRM status. Factory state = 0xFC (1 byte). Activation state = 0x03000000. Deactivation state = 0x00000000.
|-
| 04 || 3F || '''Padding0''' Nothing only 0xFF bytes.
|-
| 40 || 43 || '''Constant''' always 0x01000000.
|-
| 44 || 47 || '''Padding1''' Nothing always 0xFF bytes.
|-
| 48 || 4F || '''Magic''' The VTRM Magic.
|-
| 50 || 53 || '''Count0''' The activation / deactivation count.
|-
| 54 || 57 || '''Padding2''' Nothing always 0x00 bytes.
|-
| 58 || 5B || '''Count1''' The control byte for the activation / deactivation count. It need to be the same like '''Count0'''.
|-
| 5C || 5F || '''Padding3''' Nothing always 0x00 bytes.
|-
| 60 || 6F || '''Ukn''' Unknowen always the same 16 bytes.
|-
| 70 || 76 || '''Padding4''' Nothing always 0xFF bytes.
|-
| 77 || 77 || '''Ctrlflag''' Tigthen with the '''Flag''' variable. Factory state = 0xFF. First activation state = 0xFE. Else it will be always state = 0xFC.
|-
| 78 || 7F || '''Padding5''' Nothing always 0xFF bytes.
|}
'''C'''
<source lang="c">
typedef struct vtrmHeader {
    unsigned char FLAG;
    unsigned const char PADDING0;
    unsigned int32 CONSTANT;
    unsigned const char PADDING1;
    unsigned const char MAGIC;
    unsigned int32 COUNT0;
    unsigned const char PADDING2;
    unsigned int32 COUNT1;
    unsigned const char PADDING3;
    unsigned const char UKN;
    unsigned const char PADDING4;
    unsigned char CTRLFLAG;
    unsigned const char PADDING5;
} vtrmHeader;
</source>
'''CSharp'''
<source lang="csharp">
protected internal struct vtrmHeader {
    internal static byte[] FLAG = new byte[4];
    internal static byte[] PADDING0 = new byte[60];
    internal static int32 CONSTANT;
    internal static byte[] PADDING1 = new byte[4];
    internal static byte[] MAGIC = new byte[8];
    internal static int32 COUNT0;
    internal static byte[] PADDING2 = new byte[4];
    internal static int32 COUNT1;
    internal static byte[] PADDING3 = new byte[4];
    internal static byte[] UKN = new byte[16];
    internal static byte[] PADDING4 = new byte[8];
    internal static byte[] CTRLFLAG = new byte[1];
    internal static byte[] PADDING5 = new byte[7];
}
</source>
==== Body ====


== Function Calls ==
== Function Calls ==
From 1.76. [http://pastebin.com/gWg1JeA8 pastebin]
<pre>
VtrmCipherCalcHeaderDigest            LOAD FFFFFFFF827CF0E0 00000141 00000138 00000000 R . . . B . .
VtrmCipherCalcAssignTableDigest      LOAD FFFFFFFF827CF230 00000078 00000020 00000000 R . . . B . .
VtrmCipherCalcSectorDigestTableDigest LOAD FFFFFFFF827CF2B0 00000078 00000020 00000000 R . . . B . .
VtrmCipherCalcUserRegionDigest        LOAD FFFFFFFF827CF330 00000078 00000020 00000000 R . . . B . .
VtrmCipherEncryptUserRegion          LOAD FFFFFFFF827CF3B0 000000A6 00000048 00000000 R . . . B . .
VtrmCipherDecryptUserRegion          LOAD FFFFFFFF827CF460 000000A6 00000048 00000000 R . . . B . .
vtrm_erase_sector                    LOAD FFFFFFFF827CF510 0000001B                  R . . . . . .
vtrm_pread                            LOAD FFFFFFFF827CF530 00000029                  R . . . . . .
vtrm_pwrite                          LOAD FFFFFFFF827CF560 00000029                  R . . . . . .
VtrmUtilLockInitialize                LOAD FFFFFFFF827CF590 0000001D 00000008 00000000 R . . . B . .
VtrmUtilLockFinialize                LOAD FFFFFFFF827CF5B0 00000014 00000008 00000000 R . . . B . .
VtrmUtilLock                          LOAD FFFFFFFF827CF5D0 0000003A 00000008 00000000 R . . . B . .
VtrmUtilUnlock                        LOAD FFFFFFFF827CF610 0000003A 00000008 00000000 R . . . B . .
VTRM_MALLOC                          LOAD FFFFFFFF827CF650 00000011                  R . . . . . .
VTRM_FREE                            LOAD FFFFFFFF827CF670 0000000C                  R . . . . . .
VTRM_CONTIGMALLOC                    LOAD FFFFFFFF827CF680 00000039 00000018 00000000 R . . . B . .
VTRM_CONTIGFREE                      LOAD FFFFFFFF827CF6C0 0000000C                  R . . . . . .
VtrmUtilBswap16                      LOAD FFFFFFFF827CF6D0 00000008                  R . . . . . .
VtrmUtilBswap32                      LOAD FFFFFFFF827CF6E0 00000005                  R . . . . . .
VtrmUtilBswap64                      LOAD FFFFFFFF827CF6F0 00000007                  R . . . . . .
VtrmUtilDumpVtrmHeader                LOAD FFFFFFFF827CF700 00000001                  R . . . . . .
VtrmUtilFillVtrmHeaderDefault        LOAD FFFFFFFF827CF710 00000055                  R . . . . . .
VtrmUtilCheckVtrmHeader              LOAD FFFFFFFF827CF770 00000038                  R . . . . . .
VtrmUtilIsErasedSector                LOAD FFFFFFFF827CF7B0 00000026                  R . . . . . .
VtrmUtilCompareDataVersion            LOAD FFFFFFFF827CF7E0 00000041                  R . . . . . .
VtrmUtilDumpDigest                    LOAD FFFFFFFF827CF830 00000001                  R . . . . . .
VtrmUtilCountAllocatedEntry          LOAD FFFFFFFF827CF840 0000003F                  R . . . . . .
</pre>
Please note that all contributions to PS4 Developer wiki are considered to be released under the GNU Free Documentation License 1.2 (see PS4 Developer wiki:Copyrights for details). If you do not want your writing to be edited mercilessly and redistributed at will, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource. Do not submit copyrighted work without permission!

To protect the wiki against automated edit spam, we kindly ask you to solve the following hCaptcha:

Cancel Editing help (opens in new window)