http://www.psdevwiki.com/ps4/api.php?action=feedcontributions&user=155.33.166.149&feedformat=atom PS4 Developer wiki - User contributions [en] 2024-03-28T15:43:52Z User contributions MediaWiki 1.39.6 http://www.psdevwiki.com/ps4/index.php?title=PFS&diff=276394 PFS 2016-12-03T22:26:04Z <p>155.33.166.149: add patent for flat path table</p> <hr /> <div>'''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.<br /> <br /> == Structure ==<br /> <br /> There are four main sections in a Playstation File System:<br /> * Header (superblock)<br /> * Inode blocks<br /> * Directory blocks<br /> * Data blocks<br /> <br /> === Header/Superblock ===<br /> {| class=&quot;wikitable&quot;<br /> ! Offset !! Value !! Size !! Notes<br /> |-<br /> | 0x00 || version || 0x8 || Should be 1<br /> |-<br /> | 0x08 || magic || 0x8 || Should be 20130315<br /> |-<br /> | 0x10 || id || 0x8 || <br /> |-<br /> | 0x18 || fmode || 0x1 || <br /> |-<br /> | 0x19 || clean || 0x1 || <br /> |-<br /> | 0x1A || ronly || 0x1 || If 1, this is a readonly filesystem<br /> |-<br /> | 0x1B || rsv || 0x1 || <br /> |-<br /> | 0x1C || mode || 0x2 || <br /> |-<br /> | 0x1E || unknown || 0x2 || <br /> |-<br /> | 0x20 || blocksz || 0x4 || The size of each block in the filesystem.<br /> |-<br /> | 0x24 || nbackup || 0x4 || <br /> |-<br /> | 0x28 || nblock || 0x8 || <br /> |-<br /> | 0x30 || ndinode || 0x8 || Number of inodes in the inode blocks<br /> |-<br /> | 0x38 || ndblock || 0x8 || Number of data blocks<br /> |-<br /> | 0x40 || ndinodeblock || 0x8 || Number of inode blocks<br /> |-<br /> | 0x48 || superroot_ino || 0x8 || <br /> |}<br /> &lt;source lang=&quot;c&quot;&gt;<br /> typedef struct {<br /> int64 version;<br /> int64 magic;<br /> int32 id[2];<br /> char fmode;<br /> char clean;<br /> char ronly;<br /> char rsv;<br /> int16 mode;<br /> int16 unk1;<br /> int32 blocksz;<br /> int32 nbackup;<br /> int64 nblock;<br /> int64 ndinode;<br /> int64 ndblock;<br /> int64 ndinodeblock;<br /> int64 superroot_ino;<br /> } PFS_HDR;<br /> &lt;/source&gt;<br /> <br /> === Inodes ===<br /> Inode table starts at the second block and continues for &lt;tt&gt;header.ndinodeblock&lt;/tt&gt; blocks.<br /> There are only &lt;tt&gt;header.blocksz / sizeof(di_d32)&lt;/tt&gt; inodes per block. (inodes will never cross a block boundary)<br /> <br /> For an explanation of inodes, direct and indirect blocks, see [[wikipedia:Inode_pointer_structure|inode pointer structure]] on Wikipedia. Most PFS images from PKGs have just one direct block pointer per file, and the file's data just takes up consecutive blocks. But if there is fragmentation on the file system, you will have to follow the direct and indirect block pointers.<br /> {| class=&quot;wikitable&quot;<br /> ! Offset !! Value !! Size !! Notes<br /> |-<br /> | 0x00 || mode|| 0x2 || Inode mode (bitwise OR of flags; file=0x8000, directory=0x4000)<br /> |-<br /> | 0x02 || nlink || 0x2 || <br /> |-<br /> | 0x04 || flags|| 0x4 || <br /> |-<br /> | 0x08 || size || 0x8 || <br /> |-<br /> | 0x10 || unknown || 0x38 || <br /> |-<br /> | 0x48 || uid|| 0x4 || <br /> |-<br /> | 0x4C || gid|| 0x4 || <br /> |-<br /> | 0x50 || unknown || 0x10 || <br /> |-<br /> | 0x60 || blocks || 0x4 || Number of blocks occupied<br /> |-<br /> | 0x64 || db || 0x30 || Direct blocks<br /> |-<br /> | 0x94 || ib || 0x14 || Indirect blocks<br /> |}<br /> &lt;source lang=&quot;c&quot;&gt;<br /> typedef struct {<br /> uint16 mode;<br /> uint16 nlink;<br /> uint16 flags[2];<br /> uint64 size;<br /> char unk1[56];<br /> uint32 uid;<br /> uint32 gid;<br /> uint64 unk2[2];<br /> uint32 blocks;<br /> int32 db[12];<br /> int32 ib[5];<br /> } di_d32;<br /> &lt;/source&gt;<br /> <br /> === Dirents ===<br /> Each inode with a mode OR'd with 0x4000 points to block(s) of dirents. Dirents contain the name and type of files, directories, symlinks, etc. Each directory will have an associated dirent block containing at least the '.' and '..' special files, along with all other files and sub-directories in that directory. Dirents are 8-byte aligned. The &lt;tt&gt;entsize&lt;/tt&gt; value will say the total length of this dirent. There is typically padding after &lt;tt&gt;name&lt;/tt&gt; which can just be skipped.<br /> <br /> If the type of the dirent is 3, it is a directory. Its &lt;tt&gt;ino&lt;/tt&gt; value indicates the inode number (0 being the first inode). That inode will point to the dirent block for that directory so you can continue down the file system tree.<br /> <br /> If the type of the dirent is 2, it is a file. Its inode will point you to the location(s) of the file data.<br /> {| class=&quot;wikitable&quot;<br /> ! Offset !! Value !! Size !! Notes<br /> |-<br /> | 0x00 || ino || 0x4 || Inode index<br /> |-<br /> | 0x04 || type|| 0x4 || Type of entry. 2=file, 3=directory<br /> |-<br /> | 0x08 || namelen|| 0x4 || Length of filename (add 1 for 0-terminator)<br /> |-<br /> | 0x0C || entsize || 0x4 || Size of this whole struct, in bytes<br /> |-<br /> | 0x10 || name || namelen + 1 || Filename and 0-terminator<br /> |-<br /> | 0x11 + namelen || padding || variable || Padding so this structure is exactly &lt;tt&gt;entsize&lt;/tt&gt; bytes.<br /> |}<br /> &lt;source lang=&quot;c&quot;&gt;<br /> typedef struct {<br /> int32 ino;<br /> int32 type;<br /> int32 namelen;<br /> int32 entsize;<br /> char name[namelen+1];<br /> } dirent;<br /> &lt;/source&gt;<br /> <br /> === Finding the root ===<br /> The filesystem tree starts with the superroot, a sort of meta-directory that contains the root directory within it, along with something called a &quot;flat_path_table&quot;. The superroot's inode is typically the first (zeroeth) inode entry in the table, but you should check &lt;tt&gt;PFS_HDR.superroot_ino&lt;/tt&gt; for the actual index. The true root of the filesystem is the &quot;uroot&quot; directory within the super root.<br /> <br /> [https://www.google.com/patents/EP2878348A1?cl=en Patent, essentially for the PFS image format, explaining the flat path table]<br /> <br /> == Tools ==<br /> * [https://github.com/maxton/GameArchives/releases/latest GameArchives/ArchiveExplorer] C# library/tool that supports opening and extracting from PFS images</div> 155.33.166.149