Editing PFS
Jump to navigation
Jump to search
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: | ||
'''PFS''' ( | '''PFS''' (Playstation File System) is the file system used by (at least) downloadable content and games on the PS4. It is loosely based on the [[wikipedia:UFS|UFS]] (Unix File System) used in FreeBSD. PFS typically uses a 64kB block size, although the block size is configurable and specified in the file system header. | ||
= Structure = | == Structure == | ||
There are four main sections in | There are four main sections in a Playstation File System: | ||
* Header (superblock) | * Header (superblock) | ||
* Inode blocks | * Inode blocks | ||
Line 9: | Line 9: | ||
* Data blocks | * Data blocks | ||
== Header/Superblock == | === Header/Superblock === | ||
{| class="wikitable" | {| class="wikitable" | ||
! Offset !! Value !! Size !! Notes | ! Offset !! Value !! Size !! Notes | ||
|- | |- | ||
| 0x00 || version || 0x8 || | | 0x00 || version || 0x8 || Should be 1 | ||
|- | |- | ||
| 0x08 || | | 0x08 || magic || 0x8 || Should be 20130315 | ||
|- | |- | ||
| 0x10 || id || 0x8 || | | 0x10 || id || 0x8 || | ||
Line 28: | Line 27: | ||
| 0x1B || rsv || 0x1 || | | 0x1B || rsv || 0x1 || | ||
|- | |- | ||
| 0x1C || mode || 0x2 || | | 0x1C || mode || 0x2 || | ||
|- | |- | ||
| 0x1E || unknown || 0x2 || | | 0x1E || unknown || 0x2 || | ||
|- | |- | ||
| 0x20 || blocksz || 0x4 || The size of each block in the filesystem | | 0x20 || blocksz || 0x4 || The size of each block in the filesystem. | ||
|- | |- | ||
| 0x24 || nbackup || 0x4 || | | 0x24 || nbackup || 0x4 || | ||
|- | |- | ||
| 0x28 || nblock || 0x8 || | | 0x28 || nblock || 0x8 || | ||
|- | |- | ||
| 0x30 || ndinode || 0x8 || Number of inodes in the inode blocks | | 0x30 || ndinode || 0x8 || Number of inodes in the inode blocks | ||
Line 46: | Line 45: | ||
| 0x48 || superroot_ino || 0x8 || | | 0x48 || superroot_ino || 0x8 || | ||
|} | |} | ||
<source lang="c"> | <source lang="c"> | ||
typedef struct { | typedef struct { | ||
Line 68: | Line 66: | ||
</source> | </source> | ||
== Inodes == | === Inodes === | ||
Inode table starts at the second block and continues for <tt>ndinodeblock</tt> blocks. | |||
Inode table starts at the second block and continues for <tt> | |||
{| class="wikitable" | {| class="wikitable" | ||
! Offset !! Value !! Size !! Notes | ! Offset !! Value !! Size !! Notes | ||
|- | |- | ||
| 0x00 || mode|| 0x2 || Inode mode (bitwise OR of flags; file=0x8000, directory=0x4000) | | 0x00 || mode|| 0x2 || Inode mode (bitwise OR of flags; file=0x8000, directory=0x4000) | ||
|- | |- | ||
| 0x02 || nlink || 0x2 || | | 0x02 || nlink || 0x2 || | ||
|- | |- | ||
| 0x04 || flags|| 0x4 || | | 0x04 || flags|| 0x4 || | ||
|- | |- | ||
| 0x08 || size || 0x8 || | | 0x08 || size || 0x8 || | ||
|- | |- | ||
| 0x10 || | | 0x10 || unknown || 0x38 || | ||
|- | |- | ||
| | | 0x48 || uid|| 0x4 || | ||
|- | |- | ||
| | | 0x4C || gid|| 0x4 || | ||
|- | |- | ||
| 0x50 || unknown || 0x10 || | |||
| 0x50 || | |||
|- | |- | ||
| 0x60 || blocks || 0x4 || Number of blocks occupied | | 0x60 || blocks || 0x4 || Number of blocks occupied | ||
Line 104: | Line 93: | ||
| 0x94 || ib || 0x14 || Indirect blocks | | 0x94 || ib || 0x14 || Indirect blocks | ||
|} | |} | ||
<source lang="c"> | <source lang="c"> | ||
typedef struct { | typedef struct { | ||
uint16 mode; | |||
uint16 nlink; | uint16 nlink; | ||
uint16 flags[2]; | |||
uint64 size; | uint64 size; | ||
char unk1[56]; | |||
uint32 uid; | uint32 uid; | ||
uint32 gid; | uint32 gid; | ||
uint64 | uint64 unk2[2]; | ||
uint32 blocks; | uint32 blocks; | ||
int32 db[12]; | int32 db[12]; | ||
Line 145: | Line 109: | ||
</source> | </source> | ||
== Dirents == | === Dirents === | ||
Dirents are 8-byte aligned. The <tt>entsize</tt> value will say the total length of this dirent. There is typically padding after <tt>name</tt> which can just be skipped. | |||
{| class="wikitable" | {| class="wikitable" | ||
! Offset !! Value !! Size !! Notes | ! Offset !! Value !! Size !! Notes | ||
Line 157: | Line 116: | ||
| 0x00 || ino || 0x4 || Inode index | | 0x00 || ino || 0x4 || Inode index | ||
|- | |- | ||
| 0x04 || type|| 0x4 || Type of entry. 2=file, 3=directory | | 0x04 || type|| 0x4 || Type of entry. 2=file, 3=directory | ||
|- | |- | ||
| 0x08 || namelen|| 0x4 || Length of filename (add 1 for 0-terminator) | | 0x08 || namelen|| 0x4 || Length of filename (add 1 for 0-terminator) | ||
|- | |- | ||
| 0x10 || name || namelen + 1 || Filename and 0-terminator | | 0x10 || name || namelen + 1 || Filename and 0-terminator | ||
Line 167: | Line 124: | ||
| 0x11 + namelen || padding || variable || Padding so this structure is exactly <tt>entsize</tt> bytes. | | 0x11 + namelen || padding || variable || Padding so this structure is exactly <tt>entsize</tt> bytes. | ||
|} | |} | ||
<source lang="c"> | <source lang="c"> | ||
typedef struct { | typedef struct { | ||
Line 178: | Line 134: | ||
</source> | </source> | ||
== | == Tools == | ||
* [https://github.com/maxton/GameArchives/releases/latest GameArchives/ArchiveExplorer] library/tool that supports opening and extracting from PFS images | |||
* [https://github.com/maxton/GameArchives/releases/latest GameArchives/ArchiveExplorer | |||