SceIofilemgr

From Vita Development Wiki
Jump to navigation Jump to search

SceIofilemgr is the primary interface for file IO. Read File Management for more information on file IO.

Module

This module exists in only in non-secure world. The SELF can be found in os0:kd/iofilemgr.skprx.

Known NIDs

Version Name World Privilege NID
1.69 SceIofilemgr Non-secure Kernel 0x3E244C17
3.60 SceIofilemgr ? Kernel 0x9642948C

Libraries

This module is accessible by usermode.

Known NIDs

Version Name World Visibility NID
1.69 SceIofilemgrForDriver Non-secure Kernel 0x40FD29C7
3.60 SceIofilemgrForDriver ? Kernel 0x40FD29C7
1.69 SceIofilemgr Non-secure User 0xF2FF276E
3.60 SceIofilemgr ? User 0xF2FF276E

Mount Points

This table is stored in data segment of SceIofilemgr as array of vfs_mount_point_info elements.

When sceVfsMount is executed it finds vfs_add_data element by filesystem string and then selects appropriate mount scenario by devMinor and devMajor.

  • <rnd> means random numeric string of length 13
Unix Mount Dev Major Dev Minor Filesystem Vita Mount Block Device VSH Mount Id
/tty 0x4000020 0x6003 dummy_ttyp_dev_fs tty dummy_ttyp_dev_fs 0x0
/dev 0x10 0x3 sdstor_dev_fs sdstor0: sd 0x1
/md 0x10 0x2003 md_dev_fs md0: md 0x2
/sd/exfat 0x2030001 0x30002 exfat sd0: sdstor0:ext-pp-act-a, sdstor0:ext-lp-act-entire 0x100
/os/exfat 0x1000001 0x1002 exfat os0: sdstor0:int-lp-act-os 0x200
/vs/exfat 0x1000001 0x1002 exfat vs0: sdstor0:int-lp-ign-vsh 0x300
/vd/exfat 0x1000001 0x10002 exfat vd0: sdstor0:int-lp-ign-vshdata 0x400
/tm/exfat 0x1000001 0x10002 exfat tm0: sdstor0:int-lp-ign-vtrm 0x500
/ur/exfat 0x1000001 0x50002 exfat ur0: sdstor0:int-lp-ign-user 0x600
/ud/exfat 0x1000001 0x10002 exfat ud0: sdstor0:int-lp-ign-updater 0x700
/ux/exfat 0x2020001 0x30002 exfat ux0: sdstor0:xmc-lp-ign-userext / sdstor0:int-lp-ign-userext 0x800
/gro/exfat 0x2010001 0x21002 exfat gro0: sdstor0:gcd-lp-ign-gamero 0x900
/grw/exfat 0x2010001 0x20002 exfat grw0: sdstor0:gcd-lp-ign-gamerw 0xA00
/sa/exfat 0x1000001 0x1002 exfat sa0: sdstor0:int-lp-ign-sysdata 0xB00
/pd/exfat 0x1000001 0x1002 exfat pd0: sdstor0:int-lp-ign-pidata 0xC00
/imc/exfat 0x2020001 0x30002 exfat imc0: sdstor0:int-lp-ign-userext 0xD00
/xmc/exfat 0x2020001 0x30002 exfat xmc0: sdstor0:xmc-lp-ign-userext 0xE00
/uma/exfat 0x2030001 0x2 exfat uma0: sdstor0:uma-pp-act-a, sdstor0:uma-lp-act-entire 0xF00
/lma/exfat 0x1 0x5 exfat lma0: / 0x10000
/lmb/exfat 0x1 0x5 exfat lmb0: / 0x20000
/mfa/exfat 0x1 0x5 exfat mfa0: / 0x50000
/mfb/exfat 0x1 0x5 exfat mfb0: / 0x60000
/PD<rnd> 0x3 0x1001 PFS_GDSD_INF PD<rnd>0 0x0

Block Device Naming Rules

First level prefix

  • int
  • ext
  • gcd
  • mcd
  • uma
  • usd
  • xmc

Second level prefix

  • lp
  • pp

Third level prefix

  • ina
  • act
  • ign

Forth level prefix

  • unused
  • idstor
  • sloader
  • os
  • vsh
  • vshdata
  • vtrm
  • user
  • userext
  • gamero
  • gamerw
  • updater
  • sysdata
  • mediaid
  • pidata
  • entire

Partition Block Devices

Each partition has numeric alias (string) that looks like to be used to reference the partition.

Numeric names most likely follow order of partitions in MBR.

To access device node use /dev prefix (like /dev/gcd-lp-ign-gamero).

In total there can be 16 aliases from 0 to 15 per physical device (eMMC, Game Card, Memory Card). Alias 16 is hardcoded and is called entire.

Aliases 0-15 correspond to eMMC.

Aliases 100-115 correspond to Game Card.

Aliases 200-215 correspond to Memory Card.

block device numeric name
int-lp-ign-idstor (need to confirm) 000
int-lp-ign-sloader (need to confirm) 001
- 002
int-lp-act-os 003
- 004
int-lp-ign-sysdata 005
int-lp-ign-vtrm 006
int-lp-ign-vsh 007
int-lp-ign-vshdata 008
int-lp-ign-updater 009
int-lp-ign-pidata 010
int-lp-ign-user 011
int-lp-ign-userext 012
int-lp-act-entire 016
gcd-lp-ign-gamero, gcd-lp-act-mediaid (need to confirm) 100
gcd-lp-ign-gamerw (need to confirm) 101
ext-lp-act-entire (need to confirm) 116
mcd-lp-act-mediaid 200
- 201
mcd-lp-act-entire (need to confirm) 216

VFS Nodes

Module Name Comment
SceSdstor sdstor_dev_fs
SceExfatfs exfat
SceIofilemgr dummy_ttyp_dev_fs
ScePfsMgr PFS_REDIRECT_INF Redirect Pseudo Drive.
ScePfsMgr PFS_GDSD_INF Gamedata/Savedata Pseudo Drive.
ScePfsMgr PFS_AC_INF AC Pseudo Drive.

VFS Operations

  • implemented operation is marked as implemented
  • not implemented is marked as
  • return 0 placeholder is marked as 0
  • return error is marked with corresponding error name
Function sdstor_dev_fs exfat dummy_ttyp_dev_fs PFS_REDIRECT_INF PFS_GDSD_INF PFS_AC_INF
1 implemented implemented implemented implemented implemented implemented
2 SCE_ERROR_ERRNO_EBUSY implemented 0 implemented implemented implemented
3 implemented implemented implemented implemented implemented implemented
4 implemented
5
6
7 implemented 0 implemented implemented
8
9 0 0 0 0 0 0
10 0 0 0 0 0
11
12 implemented implemented implemented implemented implemented
13 implemented implemented implemented implemented implemented

VFS Node Operations

  • implemented operation is marked as implemented
  • not implemented is marked as
  • return 0 placeholder is marked as 0
  • return error is marked with corresponding error name
Function sdstor_dev_fs exfat dummy_ttyp_dev_fs PFS_REDIRECT_INF PFS_GDSD_INF PFS_AC_INF
1 implemented implemented 0 implemented implemented implemented
2 implemented implemented implemented implemented
3 implemented implemented 0 implemented implemented implemented
4 implemented implemented implemented implemented implemented implemented
5 implemented implemented 0 implemented implemented implemented
6 implemented implemented implemented implemented implemented implemented
7 implemented implemented 0 implemented implemented implemented
8 SCE_ERROR_ERRNO_EUNSUP 0 implemented implemented implemented
9 implemented implemented implemented implemented implemented
10 implemented implemented implemented implemented
11 implemented implemented implemented implemented
12 implemented implemented implemented implemented
13 implemented implemented implemented implemented
14 implemented implemented implemented implemented
15 implemented implemented implemented implemented
16 implemented implemented implemented implemented
17 implemented implemented implemented implemented
18
19 implemented implemented implemented implemented implemented
20 implemented implemented implemented implemented implemented
21 0 implemented 0 implemented implemented implemented
22 implemented
23 implemented
24 0 implemented implemented implemented implemented
25 implemented implemented implemented implemented
26 implemented implemented implemented implemented
27 implemented implemented implemented implemented
28 implemented implemented implemented implemented
29

Typical i/o operation execution

This is a very brief desctiption for overall understanding of io vfs_node operations. Implementation of SceIofilemgr is quite solid and most of the functions are implemented in the same manner however there could be exceptions. When io operation like sceIoLseek is called here is what happens:

  • all user space arguments are copied to kernel space, usually onto the kernel stack. all user space uids are converted to kernel space uids
  • optionally control may be passed to wrapper function that also does conversion
  • then control is passed to kernel level function like sceIoLseekForDriver
  • kernel level function checks 0x2198 (IoSchedulerDispatcher initialized) flag

if dispatcher is not initialized:

  • kernel level function updates 0x1964 (i/o dirty) and 0x1980 (i/o counter) flags
  • kernel level function spawns separate thread and passes all arguments in single structure
  • separate thread then unpacks all arguments, finds vfs_node and calls exported function like vfs_node_func7
  • exported function packs all arguments into single stucture and calls real callback since it has vfs_node with node operation table
  • callback routine should be located in generic device driver, like SceSdstor, SceExfatfs or ScePfsMgr. It unpacks the arguments and then does something. For example SceSdstor dispatches the call further to SceSdif, SceWlanBt, SceMsif and SceUsbMass.
  • kernel level function updates 0x1980 (i/o counter) flag

if dispatcher is initialized:

  • kernel level function passes arguments to wrapper
  • wrapper initializes io_contex and assigns i/o operation index
  • wrapper updates 0x1964 (i/o dirty) and 0x1980 (i/o counter) flags
  • wrapper runs dispatcher function (offset 0x17C00) in separate thread. this function selects proper vfs_node function based on i/o operation index.
  • wrapper updates 0x1980 (i/o counter) flag

i/o operation index

Typically operations are dispatched from kernel functions.

However there are exceptions: sceIoLseek32, sceIoDopenAsync, sceIoDreadAsync, sceIoDcloseAsync user functions can be dispatched.

Typically operations have normal and async version - regulated by async flag in io_context.

However there are exceptions: sceIoLseek32, sceIoIoctlForDriver, sceIoDevctlForDriver, sceIoGetstatForDriver_2, sceIoChstatForDriver_2, sceIoDreadForDriver_2 do not have async version.

Index Normal Operation Async Operation Vfs Node Function Vfs Function
1 sceIoOpenForDriver sceIoOpenAsyncForDriver
2 sceIoCloseForDriver sceIoCloseAsyncForDriver
3 sceIoReadForDriver sceIoReadAsyncForDriver
4 sceIoWriteForDriver sceIoWriteAsyncForDriver
5 sceIoLseekForDriver sceIoLseekAsyncForDriver 7
6 sceIoLseek32 N/A 7
7 sceIoIoctlForDriver N/A 8
8 sceIoRemoveForDriver sceIoRemoveAsyncForDriver
9 sceIoDopenForDriver sceIoDopenAsyncForDriver
10 sceIoDcloseForDriver sceIoDcloseAsyncForDriver
11 sceIoDreadForDriver sceIoDreadAsyncForDriver 14
12 sceIoMkdirForDriver sceIoMkdirAsyncForDriver 10
13 sceIoRmdirForDriver sceIoRmdirAsyncForDriver
14 sceIoRenameForDriver sceIoRenameAsyncForDriver
15 sceIoChstatForDriver sceIoChstatAsyncForDriver 16
16 sceIoChstatByFdForDriver sceIoChstatByFdAsyncForDriver 26
17 sceIoGetstatForDriver sceIoGetstatAsyncForDriver 15
18 sceIoGetstatByFdForDriver sceIoGetstatByFdAsyncForDriver 25
19 sceIoDevctlForDriver N/A 12
20 sceIoSyncForDriver sceIoSyncAsyncForDriver 24
21 sceIoSyncByFdForDriver sceIoSyncByFdAsyncForDriver
22 sceIoPreadForDriver sceIoPreadAsyncForDriver
23 sceIoPwriteForDriver sceIoPwriteAsyncForDriver
24 sceIoGetstatForDriver_2 N/A
25 sceIoChstatForDriver_2 N/A
26 sceIoDreadForDriver_2 N/A
27 N/A sceIoDopenAsync
28 N/A sceIoDreadAsync
29 N/A sceIoDcloseAsync

Types


typedef struct vfs_block_dev_info //size is 0x14
{
  char* vitaMount;
  char* filesystem; // Some name, I guess it is filesystem
  char* blockDevicePrimary;
  char* blockDeviceSecondary; // can be 0
  uint32_t vshMountId; //must be same as in mount_point_info
}vfs_block_dev_info;

typedef struct vfs_mount_point_info_base
{
  char* unixMount;
  uint32_t unk_4; //zero
  uint32_t devMajor;
  uint32_t devMinor;

  char* filesystem;
  void* unk_14; //zero
  vfs_block_dev_info* blockDev1;
  uint32_t unk_1C; //zero
} vfs_mount_point_info_base;

typedef struct vfs_mount_point_info //size is 0x38
{
  uint32_t vshMountId;
  
  vfs_mount_point_info_base base;

  vfs_block_dev_info* blockDev2; //same as blockDev1
  
  uint32_t unk_28; //zero - except for (ux0:, gro0:, grw0:) - maybe related to device specific data?
  uint32_t unk_2C; //zero
  
  uint32_t unk_30; //zero
  uint32_t unk_34; //zero
}vfs_mount_point_info;

//probably vfsops
struct node_ops1 // size is 0x34 (13 pointers)
{
  int (*func1)(void* ctx);
  int (*func2)(void* ctx); // ?
  int (*func3)(void* ctx);
  int (*func4)(void* ctx);
  int (*func5)(void* ctx); // not implemented by all
  int (*func6)(void* ctx); // not implemented by all
  int (*func7)(void* ctx);
  int (*func8)(void* ctx); // not implemented by all
  int (*func9)(void* ctx); // called by sceVfsAddVfs
  int (*func10)(void* ctx); // called by sceVfsDeleteVfs
  int (*func11)(void* ctx); // not implemented by all
  int (*func12)(void* ctx); // sceIoDevctlForDriver
  int (*func13)(void* ctx); // (initialize partition entry in table)(map block device name on numeric name)
};

//probably vnodeops
struct node_ops2 // size is 0x74 (29 pointers)
{
  int (*func1)(void* ctx); // sceIoOpenForDriver (this function creates device handle) (It operates with normal block device name and unix mount)
  int (*func2)(void* ctx); // sceIoOpenForDriver (another one ?)
  int (*func3)(void* ctx); // sceIoOpenForDriver (another one ?) or sceIoCloseForDriver
  int (*func4)(void* ctx); // add partition (add vfsNode) (initialize partition entry in table) (for example happens on card insert exclusively) (operates with numeric names)
  int (*func5)(void* ctx); // sceIoReadForDriver
  int (*func6)(void* ctx); // sceIoWriteForDriver
  int (*func7)(void* ctx); // sceIoLseekForDriver or sceIoLseek32?
  int (*func8)(void* ctx); // sceIoIoctlForDriver
  int (*func9)(void* ctx); // remove partition (remove vfsNode) (deinitialize partition entry in table) (for example happens on card remove exclusively) (operates with numeric names)
  int (*func10)(void* ctx); // sceIoMkdirForDriver
  int (*func11)(void* ctx); // sceIoRmdirForDriver
  int (*func12)(void* ctx); // sceIoDopenForDriver
  int (*func13)(void* ctx); // sceIoDcloseForDriver
  int (*func14)(void* ctx); // sceIoDreadForDriver
  int (*func15)(void* ctx); // sceIoGetstatForDriver or sceIoGetstatByFdForDriver
  int (*func16)(void* ctx); // sceIoChstatForDriver or sceIoChstatByFdForDriver
  int (*func17)(void* ctx); // sceIoRenameForDriver
  int (*func18)(void* ctx); // not implemented by all
  int (*func19)(void* ctx); // sceIoPreadForDriver
  int (*func20)(void* ctx); // sceIoPwriteForDriver
  int (*func21)(void* ctx); // ?
  int (*func22)(void* ctx); // not referenced
  int (*func23)(void* ctx); // not referenced
  int (*func24)(void* ctx); // sceIoSyncForDriver or sceIoSyncByFdForDriver
  int (*func25)(void* ctx); // sceIoGetstatByFdForDriver
  int (*func26)(void* ctx); // sceIoChstatByFdForDriver
  int (*func27)(void* ctx); // ?
  int (*func28)(void* ctx); // ?
  int (*func29)(void* ctx); // not implemented by all
};

struct vfs_add_data
{
    node_ops1* funcs1;
    const char *name; //exfat etc. max size is 0x20
    int flags; //0x0E
    int unk_C; //0x01 / 0x00 (root, leaf ?)
    
    int unk_10; //0x10
    node_ops2* funcs2;
    int unk_18; //0x00
    vfs_add_data* next_element; //ptr to next element, confirmed
};

//this structure contains device specific data
//this definition applies only to SceSdif driver
//it is yet unknown what data is stored by SceExfatfs, ScePfsMgr and SceIofilemgr implementations

struct vfs_device_info //size is 0xC
{
   partition_entry* partition;
   sd_stor_device* device;
   uint32_t unk_8;
} vfs_device_info;

struct child_node_info
{
  vfs_node* node;
} child_node_info;

typedef struct vfs_fd_lock
{
   SceUID mutex_SceVfsFdLock;
   SceUID cond_SceVfsFdCond;
   uint32_t unk_8;
   uint32_t unk_C;

} vfs_fd_lock;

typedef struct vfs_mount_cc
{
   uint32_t unk_0;
   uint32_t unk_4;
   uint32_t unk_8; // pointer to data section, offset 34
   uint32_t unk_C; // pointer to data section, offset 1C
} vfs_mount_cc;

typedef struct vfs_mount //size is not known exactly, at least 0xD0 + 0x10 + 0x10
{
   uint32_t fast_mutex_SceVfsMnt;

   uint32_t unk_4;
   uint32_t unk_8;
   uint32_t unk_C;

   uint8_t data1[0x30];

   vfs_node* unk_40; // child ?

   SceUID pool;     // 0x44 - SceIoVfsHeap

   uint32_t unk_48; // = 0x101
   
   union _devMajor
   {
      struct _dmDword
      {
         uint32_t unk_4C;
      } dw;
      struct _dmWord
      {
         uint16_t unk_4C;
         uint16_t unk_4E;
      } w;
      struct _dmByte
      {
         uint8_t unk_4C;
         uint8_t unk_4D;
         uint8_t unk_4E;
         uint8_t unk_4F;
      } b;
   } devMajor;

   uint32_t devMinor; // 0x50

   vfs_node* unk_54;
   uint32_t unk_58;   // counter
   vfs_add_data* add_data; // 0x5C

   uint32_t unk_60;   // counter

   uint32_t unk_64;
   uint32_t unk_68;
   uint32_t unk_6C;

   vfs_mount* unk_70; // next ?
   vfs_mount* unk_74; // prev ?

   vfs_mount* unk_78; //singly linked list related to pointer 19D0 in data section

   vfs_block_dev_info* blockDev; // 0x7C

   char unixMount[0x40]; // 0x80 /gro/exfat, /ux/exfat etc

   uint32_t unk_C0;   

   void* unk_C4; // = mountInfo->unk_14

   vfs_fd_lock* fd_lock_ptr; // C8 - points to area in this structure

   vfs_mount_cc* unk_CC; // CC - points to area in this structure

   vfs_fd_lock fd_lock; // D0

   vfs_mount_cc unk_E0; //E0;

} vfs_mount;

typedef struct vfs_node_70
{
   uint32_t unk_0;
   uint32_t unk_4;
   uint32_t unk_8;
   vfs_node_70* unk_C; //zero or pointer to next element

   void* unk_10; //pointer to struct of at least size 0x94
   uint32_t unk_14; //number
   uint32_t len; // 18
   char* data; // 1C
} vfs_node_70;

struct vfs_node //size is 0x100
{
   uint32_t unk_0;
   uint32_t unk_4;  // most likely SceUID of current thread
   uint32_t unk_8;  // counter
   SceUID event_flag_SceVfsVnode; // 0xC - event flag SceVfsVnode

   uint32_t evid_bits; // 0x10
   uint32_t unk_14;
   uint32_t unk_18;
   uint32_t unk_1C;

   uint8_t data1[0x20];
   
   node_ops2 *ops;  // 0x40
   uint32_t unk_44;
   void* dev_info;  //allocated on heap with uid from uid field
                    //this is device specific / node specific data
                    //for partition node this will be vfs_device_info*
                    
                    //for pfs node it looks like to be child_node_info* 
                    //which probably points to partition node

   vfs_mount* node; // 0x4C

   vfs_node* prev_node; // 0x50

   vfs_node* unk_54; // copied from node base
   uint32_t unk_58;  // counter - probably counter of nodes
   uint32_t unk_5C;

   uint32_t unk_60;
   uint32_t unk_64;
   uint32_t unk_68;
   SceUID pool_uid;  // 0x6C - SceIoVfsHeap or other pool

   vfs_node_70* unk_70;
   uint32_t unk_74; // = 0x8000
   uint32_t unk_78; // some flag
   uint32_t unk_7C;

   uint32_t unk_80;
   uint32_t unk_84;
   uint32_t unk_88;
   uint32_t unk_8C;

   uint32_t unk_90; //void* objectBase ?
   uint32_t unk_94;
   vfs_node* unk_98; //some child node
   uint32_t unk_9C;

   uint8_t data2[0x30];
   
   uint32_t unk_D0; // devMajor.w.unk_4E

   uint8_t data3[0x2C];

}vfs_node;

struct vfs_node_info //size is 0x38
{
   char name[0x20];
   vfs_node* node; //can be zero
   uint32_t unk_24; // probably size of vfs_node
   uint32_t unk_28; // probably flags
   vfs_node_info* unk_2C; //can be zero
   vfs_node_info* unk_30; //can be zero
   vfs_node_info* unk_34; //can be zero
}vfs_node_info;

//looks like this structure is used to get some response into "error" field
//when executing sceKernelSignalCondTo calls
//this structure is used by SceIofileDaemon when it monitors mount/unmount async requests
//in SceIofilemgrMount thread using SceIofilemgrMount conditional variable
//upon completion it issues the signal and result of operation is stored in error field
//it looks like operations 1/2 are used for normal filesystems
//operations 3/4 are used for PFS_GDSD_INF filesystem
typedef struct cond_ctx
{
   uint32_t op_index; //operation index. 1,3 - mount. 2,4 - unmount
   uint32_t unk_4;
   uint32_t unk_8;
   uint32_t unk_C;
   uint32_t unk_10;
   uint32_t unk_14;
   uint32_t unk_18;
   uint32_t unk_1C;
   int error; //either error code or 0
   cond_ctx* next; //0 means end of list
} cond_ctx;

typedef struct ctx_19D4
{
   void* unk_0; 
   uint32_t unk_4;
   vfs_node* offset; // pool of vfs_nodes with 0x1000 elements.
                     // it is used in sceVfsGetNewNode, mount/unmount and node find routines
   uint32_t size;

   uint32_t count;
   uint32_t unk_14;
   uint32_t unk_18;
   uint32_t unk_1C;
}ctx_19D4;

typedef struct ctx_11C //size is 0x220
{
   void* unk_0; 
   uint32_t unk_4;
   void* offset; // pointer to array of byte size 0x10000 with 0x40 elements of size 0x400
   uint32_t size;

   uint32_t count;

   uint8_t data[0x20C];
}ctx_11C;

typedef struct io_scheduler_dispatcher //size is 0xB8
{
   char unk_0[0x50];

   io_scheduler* unk_50; // Internal
   io_scheduler* unk_54; // Game Card
   io_scheduler* unk_58; // Removable
   io_scheduler* unk_5C; // Host File System
   io_scheduler* unk_60; // Default
   
   uint32_t unk_64; // pointer to unknown module data section
   uint32_t unk_68; //SceIoSchedulerDispatcher fast mutex
   uint32_t unk_6C;
   
   char unk_70[0x30];
   
   uint32_t unk_A0;
   uint32_t unk_A4;
   
   SceUID unk_A8; //SceIoSchedulerDispatcher event flag uid
   uint32_t unk_AC; // counter
   uint32_t unk_B0; // flag
   uint32_t unk_B4; // 0
   
} io_scheduler_dispatcher;

typedef struct io_scheduler_item //size is 0x14 - allocated from SceIoScheduler heap
{
   io_scheduler* unk_0; // parent
   uint32_t unk_4; // 0
   uint32_t unk_8; // 0
   uint32_t unk_C; // 0
   uint32_t unk_10; // pointer to unknown module data section
}io_scheduler_item;

enum io_device_code
{
  Internal = 0x100,
  Game_Card = 0x201,
  Removable = 0x202,
  Host_File_System = 0x300,
  Default = 0x0
};

typedef struct io_scheduler //size is 0xA8 - allocated from SceIoScheduler heap
{
   io_device_code unk_0; 
   io_scheduler_item* unk_4; //item 0
   io_scheduler_item* unk_8; //item 1
   io_scheduler_item* unk_C; //item 2
   
   io_scheduler_item* unk_10; //item 3
   io_scheduler_item* unk_14; //item 4
   io_scheduler_item* unk_18; //item 5
   io_scheduler_item* unk_1C; //item 6
   
   io_scheduler_item* unk_20; //item 7
   io_scheduler_item* unk_24; //item 8
   io_scheduler_item* unk_28; //item 9
   io_scheduler_item* unk_2C; //item 10
   
   io_scheduler_item* unk_30; //item 11
   io_scheduler_item* unk_34; //item 12
   io_scheduler_item* unk_38; //item 13
   io_scheduler_item* unk_3C; //item 14
   io_scheduler_item* unk_40; //item 15
   
   uint32_t unk_44; // flag1 0x40000 or 0x00
   uint32_t unk_48; // flag2 0x40000 or 0x00
   io_scheduler_dispatcher* unk_4C; // parent
   
   SceUID unk_50; //SceIoScheduler mutex
   SceUID unk_54; //SceIoScheduler cond
   
   char unk_58; // 0
   char unk_59; // 0
   char unk_5A; // 0
   char unk_5B; // 0
   
   uint32_t unk_5C; // 0
   
   //this is probably separate structure
   SceUID unk_60; //SceIoSchedWorker thread id
   SceUID unk_64; //SceIoScheduler mutex from self
   SceUID unk_68; //SceIoScheduler cond from self
   io_scheduler* unk_6C; //pointer to self
   
   uint32_t unk_70; // 0
   uint16_t unk_74; // 0
   uint16_t unk_76; // 0
   uint32_t unk_78; // 0
   uint32_t unk_7C; // 0
   
   uint32_t unk_80; //
   uint32_t unk_84; // some flag
   
   uint32_t unk_88; //0x80
   uint32_t unk_8C; //0x80
   
   uint32_t unk_90; //0x80
   uint32_t unk_94; //0x80
   uint32_t unk_98; //0x80
   uint32_t unk_9C; //0x80
   
   uint32_t unk_A0; // 0
   uint32_t unk_A4; // 0

}io_scheduler;

//context that is used for dispatching i/o operations

typedef struct io_context //size is 0xB8
{
   uint32_t unk_0;
   uint32_t unk_4;
   uint32_t unk_8;
   uint32_t unk_C;
   
   uint32_t unk_10;
   uint32_t unk_14;
   uint32_t unk_18;
   uint32_t unk_1C;
   
   uint32_t unk_20;
   uint32_t io_op_index; // 0x24 - check "i/o operation index" section
   uint32_t unk_28;
   io_device_code device_code; // 0x2C
   
   char async; //0x30
   char unk_31;
   char unk_32;
   char unk_33
   uint32_t pid; //0x34 = ksceKernelGetProcessId
   uint32_t tid; //0x38 = ksceKernelGetThreadId
   uint32_t unk_3C; // = SceThreadmgrForDriver_fa54d49a
   
   uint32_t unk_40; // = SceThreadmgrForDriver_332e127c
   uint32_t cpu_mask; // 0x44 = ksceKernelGetThreadCpuAffinityMask
   uint32_t thread_priority; //0x48 = ksceKernelGetThreadCurrentPriority
   uint32_t unk_4C;
   
   uint32_t unk_50;
   uint32_t unk_54;
   uint32_t unk_58;
   uint16_t state; // 0x5C = bit 16 of state where state = (MRC p15, 0, state, c13, c0, 3)
   uint16_t unk_5E;
   
   uint32_t unk_60;
   uint32_t unk_64;
   uint32_t unk_68;
   uint32_t unk_6C;
   
   uint32_t unk_70;
   uint32_t unk_74;
   uint32_t unk_78; // = -1
   uint32_t unk_7C; // = -1
   
   uint32_t op_result; // 0x80 - result of i/o operation
   uint32_t unk_84;
   void* unk_88;
   uint32_t unk_8C;
   
   uint32_t unk_90;
   uint32_t unk_94;
   uint32_t unk_98;
   uint32_t unk_9C;
   
   uint32_t unk_A0;
   uint32_t unk_A4;
   uint32_t unk_A8;
   uint32_t unk_AC;
   
   uint64_t unk_B0; // = ksceKernelGetSystemTimeWide
   
}io_context;

Data segment layout

Address Size Description
0x0000 0x4 unknown
0x0004 0x8 pointer to SceIofile heap SceUID at offset 0x54
0x0008 0x4 unknown
0x000C 0x4 flag that enables usage of sceFiosKernel functions (like OverlayResolveSync) in i/o operations in transition from user to kernel
0x00010 0x4 flag that enables usage of sceFiosKernel functions (like OverlayResolveSync) in i/o operations in transition from user to kernel
0x00014 0x4 flag that enables usage of sceFiosKernel functions (like OverlayResolveSync) in i/o operations in transition from user to kernel
0x00018 0x4 flag that enables usage of sceFiosKernel functions (like OverlayResolveSync) in i/o operations in transition from user to kernel
0x0001C 0x4 unknown
0x0020 0x4 SceIofileDevWaitForVC event flag SceUID
0x0024 0x4 unknown
0x0028 0x4 SceIofileDevWaitForSD event flag SceUID
0x002C 0x4 pointed by vfs_mount_cc for SceIofileDevWaitForSD
0x0030 0x4 SceIofileDevWaitForMC event flag SceUID
0x0034 0x4 unknown
0x0038 0x4 pointed by vfs_mount_cc for SceIofileDevWaitForVC
0x003C 0x4 pointed by vfs_mount_cc for SceIofileDevWaitForMC
0x0040 0x10 unknown
0x0050 0x4 address of some callback function called in all vfs operations
0x0054 0x4 SceIofile heap SceUID
0x0058 0x80 unknown
0x00D8 0x4 SceIoVfsHeap heap SceUID
0x00DC 0x4 SceIoFileDebug memblock SceUID
0x00E0 0x3C unknown
0x011C 0x4 ctx_11C* pointer to structure
0x0120 0x4C unknown
0x016C 0xC structure used together with 19F8
0x0178 0x30 unknown
0x01A8 0x1500 array of 96 elements of vfs_node_info
0x16A8 0x4 SceVfsRfsLock fast mutex
0x16AC 0x74 unknown
0x1720 0x04 cond_ctx* pointer to the linked list
0x1724 0x4 SceIoScheduler heap SceUID
0x1728 0xB8 io_scheduler_dispatcher structure
0x17E0 0x70 unknown
0x1850 0x4 SceIofileDaemonLock fast mutex
0x1854 0x40 unknown
0x1894 0x4 SceIofile fast mutex
0x1898 0x80 unknown
0x1918 0x4 SceIofileFlock fast mutex
0x191C 0x44 unknown
0x1960 0x4 some i/o flag
0x1964 0x4 flag that indicates that any i/o operation happened 1/0. changed by each i/o operation. cleared on suspend.
0x1968 0x18 unknown
0x1980 0x4 counter of not finished i/o operations. changed by each i/o operation.
0x1984 0xC unknown
0x1990 0x4 SceVfsMntlistLock fast mutex
0x1994 0x3C unknown
0x19D0 0x4 vfs_mount* singly linked list
0x19D4 0x1C structure ctx_19D4
0x19F0 0x8 unknown
0x19F8 0x4 address used for ksceKernelCpuSuspendIntr
0x19FC 0x4 vfs_mount* pointer
0x1A00 0x4 SceVfsNcacheLock fast mutex
0x1A04 0x40 unknown
0x1A44 0x4 address used for ksceKernelCpuSuspendIntr
0x1A48 0x4 unknown
0x1A4C 0x4 SceVfsLock fast mutex
0x1A50 0x3C unknown
0x1A8C 0x04 SceIofilemgrMount thread SceUID
0x1A90 0x700 array of 32 elements of vfs_mount_point_info
0x2190 0x4 SceIofilemgrMount cond SceUID
0x2194 0x4 SceUID mutexid
0x2198 0x4 flag that indicates that IoSchedulerDispatcher functionality is initialized 1/0
0x219C 0x4 unknown
0x21A0 0x40 unknown
0x21E0 0x20 unknown
0x2200 0x04 SceIofilemgrDaemon thread SceUID
0x2204 0x8 unknown
0x220C 0x4 SceIofilemgrDaemon event flag SceUID
0x2210 0x4 void* to heap alloc of size 0x100
0x2214 0x4 void* to heap alloc of size 0x100
0x2218 0x4 = 3
0x221C 0x20 vfs_add_data dummy_ttyp_dev_fs node

SceIofilemgrForDriver

sceIoMountForDriver

Version NID
3.60 0xD070BC48

operation index 1 in cond_ctx

//intermediate function between sceAppMgrGameDataMountForDriver and sceVfsMount
int sceIoMountForDriver(int vshMountId);

sceIoUmountForDriver

Version NID
3.60 0x20574100

operation index 2 in cond_ctx

//intermediate function between sceAppMgrUmountForDriver and sceVfsUnmount
int sceIoUmountForDriver(int vshMountId, int unk1, int unk2, int unk3);

scePfsMgrVfsMountForDriver

Version NID
3.60 0xFEEE44A9

operation index 3 in cond_ctx

//this function can be used with PFS_GDSD_INF filesystem
int scePfsMgrVfsMountForDriver(int unk0, int unk1, int unk2);

scePfsMgrVfsUmountForDriver

Version NID
3.60 0xD220539D

operation index 4 in cond_ctx

int scePfsMgrVfsUmountForDriver(int unk0, int unk1, int unk2);

sceVfsNodeWaitEventFlag

Version NID
3.60 0xAA45010B

calls ksceKernelWaitEventFlag using event_flag_SceVfsVnode from vfs_node

int sceVfsNodeWaitEventFlag(vfs_node* node)

sceVfsNodeSetEventFlag

Version NID
3.60 0x6048F245

calls ksceKernelSetEventFlag using event_flag_SceVfsVnode from vfs_node

int sceVfsNodeSetEventFlag(vfs_node* node)

sceVfsUnmount

Version NID
1.69 0x9C7E7B76
3.60 0x9C7E7B76
struct vfs_unmount_data
{
    const char *mountpoint;
    int flags;
};
int sceVfsUnmount(struct vfs_unmount_data *data);

sceVfsDeleteVfs

Version NID
1.69 0x9CBFA725
3.60 0x9CBFA725
int sceVfsDeleteVfs(const char *name, void **deleted_node);

sceVfsAddVfs

Version NID
1.69 0x673D2FCD
3.60 0x673D2FCD
int sceVfsAddVfs(struct vfs_add_data *data);

sceVfsMount

Version NID
1.69 0xB62DE9A6
3.60 0xB62DE9A6

int sceVfsMount(struct vfs_mount_point_info_base* data);

sceVfsGetNewNode

Version NID
1.69 0xD60B5C63
3.60 0xD60B5C63
int sceVfsGetNewNode(vfs_mount* mount, node_ops2 *ops, int unused, vfs_node **node);

sceIoDreadForDriver

Version NID
1.69 0x20CF5FC7
3.60 0x20CF5FC7

Call interface is same as sceIoDread

int sceIoDreadForDriver(SceUID fd, SceIoDirent *dir);

sceIoDreadForDriver_2

Version NID
3.60 0x03051B02

Derived from i/o dispatcher, not from user function

Implementation is completely the same as sceIoDreadForDriver. The only difference is that st_attr in SceIoStat is not set.

int sceIoDreadForDriver_2(SceUID fd, SceIoDirent *dir);

sceIoWriteForDriver

Version NID
1.69 0x21EE91F0
3.60 0x21EE91F0

Call interface is same as sceIoWrite

int sceIoWriteForDriver(SceUID fd, const void *data, SceSize size);

sceIoDopenForDriver

Version NID
1.69 0x463B25CC
3.60 0x463B25CC

Call interface is same as sceIoDopen

SceUID sceIoDopenForDriver(const char *dirname);

sceIoLseekForDriver

Version NID
1.69 0x62090481
3.60 0x62090481

Call interface is same as sceIoLseek

 SceOff sceIoLseekForDriver(SceUID fd, SceOff offset, int whence);

sceIoOpenForDriver

Version NID
1.69 0x75192972
3.60 0x75192972

Call interface is same as sceIoOpen

SceUID sceIoOpenForDriver(const char *file, int flags, SceMode mode);

sceIoOpenForDriver_2

Version NID
3.60 0xC3D34965

This is a wrapper for sceIoOpenForDriver

Pid is used for sceFiosKernelOverlayResolveSyncForDriver

SceUID sceIoOpenForDriver_2(SceUID pid, const char *file, int flags, SceMode mode);

sceIoChstatForDriver

Version NID
1.69 0x7D42B8DC
3.60 0x7D42B8DC

Call interface is same as sceIoChstat

int sceIoChstatForDriver(const char *file, SceIoStat *stat, int bits);

sceIoChstatForDriver_2

Version NID
3.60 0x1F98BD50

Derived from i/o dispatcher, not from user function

Implementation is completely the same as sceIoChstatForDriver. The only difference is that (bits = bits & (~0x10000)) operation is not applied.

int sceIoChstatForDriver_2(const char *file, SceIoStat *stat, int bits);

sceIoGetstatForDriver

Version NID
1.69 0x75C96D25
3.60 0x75C96D25

Call interface is same as sceIoGetstat

int sceIoGetstatForDriver(const char *file, SceIoStat *stat);

sceIoGetstatForDriver_2

Version NID
3.60 0xD6503624

Derived from i/o dispatcher, not from user function

Implementation is completely the same as sceIoGetstatForDriver. The only difference is that st_attr in SceIoStat is not set.

int sceIoGetstatForDriver_2(const char *file, SceIoStat *stat);

sceIoMkdirForDriver

Version NID
1.69 0x7F710B25
3.60 0x7F710B25

Call interface is same as sceIoMkdir

int sceIoMkdirForDriver(const char *dir, SceMode mode);

sceIoReadForDriver

Version NID
1.69 0xE17EFC03
3.60 0xE17EFC03

Call interface is same as sceIoRead

int sceIoReadForDriver(SceUID fd, void *data, SceSize size);

sceIoCloseForDriver

Version NID
1.69 0xF99DD8A3
3.60 0xF99DD8A3

Call interface is same as sceIoClose

int sceIoCloseForDriver(SceUID fd);

sceIoRenameForDriver

Version NID
1.69 0xDC0C4997
3.60 0xDC0C4997

Call interface is same as sceIoRename

int sceIoRenameForDriver(const char *oldname, const char *newname);

sceIoRemoveForDriver

Version NID
1.69 0x0D7BB3E1
3.60 0x0D7BB3E1

Call interface is same as sceIoRemove

int sceIoRemoveForDriver(const char *file);

sceIoCancelForDriver

Version NID
3.60 0x6D59658D

Derived from sceIoCancel

sceIoChstatAsyncForDriver

Version NID
3.60 0x7EC442BF

Derived from _sceIoChstatAsync

sceIoChstatByFdAsyncForDriver

Version NID
3.60 0xEC974400

Derived from sceIoChstatByFdAsync

sceIoChstatByFdForDriver

Version NID
3.60 0xDF57A75F

Derived from _sceIoChstatByFd

int sceIoChstatByFdForDriver(SceUID fd, SceIoStat *stat, int bits);

sceIoCloseAsyncForDriver

Version NID
3.60 0x11C57CC6

Derived from sceIoCloseAsync

sceIoDevctlAsyncForDriver

Version NID
3.60 0xA9302946

Derived from _sceIoDevctlAsync

sceIoDevctlForDriver

Version NID
3.60 0x16882FC4

Derived from _sceIoDevctl

int sceIoDevctlForDriver(const char *dev, unsigned int cmd, void *indata, int inlen, void *outdata, int outlen);

sceIoDcloseForDriver

Version NID
3.60 0x19C81DD6

Derived from sceIoDclose

int sceIoDcloseForDriver(SceUID fd);

sceIoFlockForDriver

Version NID
3.60 0x16336A0D

Derived from sceIoFlockForSystem

sceIoGetstatByFdAsyncForDriver

Version NID
3.60 0x0FEE1238

Derived from sceIoGetstatByFdAsync

sceIoGetstatByFdForDriver

Version NID
3.60 0x462F059B

Derived from _sceIoGetstatByFd

int sceIoGetstatByFdForDriver(SceUID fd, SceIoStat *stat);

sceIoGetstatAsyncForDriver

Version NID
3.60 0x94A5304A

Derived from _sceIoGetstatAsync

sceIoIoctlAsyncForDriver

Version NID
3.60 0xB761E91B

Derived from _sceIoIoctlAsync

sceIoIoctlForDriver

Version NID
3.60 0x161CD33F

Derived from _sceIoIoctl

int sceIoIoctlForDriver(SceUID fd, unsigned int cmd, void *indata, int inlen, void *outdata, int outlen);

sceIoLseekAsyncForDriver

Version NID
3.60 0x541BAABD

Derived from _sceIoLseekAsync

sceIoMkdirAsyncForDriver

Version NID
3.60 0x27003443

Derived from _sceIoMkdirAsync

sceIoOpenAsyncForDriver

Version NID
3.60 0x451001DE

Derived from _sceIoOpenAsync

sceIoPreadAsyncForDriver

Version NID
3.60 0x64A46A2C

Derived from _sceIoPreadAsync

sceIoPreadForDriver

Version NID
3.60 0x2A17515D

Derived from _sceIoPread

 
//returns number of read bytes
int sceIoPreadForDriver(SceUID fd, char* buffer, SceSize size, int ignored, int offsetLo, int offsetHi)

sceIoPwriteAsyncForDriver

Version NID
3.60 0x202CDDE3

Derived from _sceIoPwriteAsync

sceIoPwriteForDriver

Version NID
3.60 0x5F1512C8

Derived from _sceIoPwrite

sceIoReadAsyncForDriver

Version NID
3.60 0x69047C81

Derived from sceIoReadAsync

sceIoRemoveAsyncForDriver

Version NID
3.60 0xF9D6507D

Derived from _sceIoRemoveAsync

sceIoRenameAsyncForDriver

Version NID
3.60 0xAACBC47A

Derived from _sceIoRenameAsync

sceIoRmdirAsyncForDriver

Version NID
3.60 0xF5B0B36C

Derived from _sceIoRmdirAsync

sceIoRmdirForDriver

Version NID
3.60 0x1CC9C634

Derived from _sceIoRmdir

int sceIoRmdirForDriver(const char *path);

sceIoSyncByFdAsyncForDriver

Version NID
3.60 0x041209CF

Derived from sceIoSyncByFdAsync

sceIoSyncByFdForDriver

Version NID
3.60 0x43170575

Derived from sceIoSyncByFd

int sceIoSyncByFdForDriver(SceUID fd, unsigned int unk);

sceIoSyncAsyncForDriver

Version NID
3.60 0x4F9EA8B0

Derived from _sceIoSyncAsync

sceIoSyncForDriver

Version NID
3.60 0xDDF78594

Derived from _sceIoSync

int sceIoSyncForDriver(const char *device, unsigned int unk);

sceIoWriteAsyncForDriver

Version NID
3.60 0xA1BD13D0

Derived from sceIoWriteAsync

sceIoGetProcessDefaultPriorityForSystem

Version NID
3.60 0xCE397158

sceIoSetProcessDefaultPriorityForSystem

Version NID
3.60 0xABE65071

sceIoDopenAsyncForDriver

Version NID
3.60 0x72F06BDE

sceIoDcloseAsyncForDriver

Version NID
3.60 0xC08F199F

sceIoDreadAsyncForDriver

Version NID
3.60 0x5982B0E3

t_sceIoOpenForDriver

Version NID
3.60 0x0E518FA9

thread callback for sceIoOpenForDriver

typedef struct sceIoOpenForDriver_args
{
 const char *file;
 int flags;
 SceMode mode;
}sceIoOpenForDriver_args;

SceUID t_sceIoOpenForDriver(sceIoOpenForDriver_args* args);

t_sceIoCloseForDriver

Version NID
3.60 0x1AE14011

thread callback for sceIoCloseForDriver

typedef struct sceIoCloseForDriver_args
{
  SceUID fd;
}sceIoCloseForDriver_args;

int t_sceIoCloseForDriver(sceIoCloseForDriver_args* args);

t_sceIoReadForDriver

Version NID
3.60 0x809892C1

thread callback for sceIoReadForDriver

typedef struct sceIoReadForDriver_args
{
  SceUID fd;
  void *data;
  SceSize size;
}sceIoReadForDriver_args;

int t_sceIoReadForDriver(sceIoReadForDriver_args* args);

t_sceIoWriteForDriver

Version NID
3.60 0x8598ADC3

thread callback for sceIoWriteForDriver

typedef struct sceIoWriteForDriver_args
{
  SceUID fd; 
  const void *data;
  SceSize size;
}sceIoWriteForDriver_args;

int t_sceIoWriteForDriver(sceIoWriteForDriver_args* args);

t_sceIoIoctlForDriver

Version NID
3.60 0xC1DD4317

thread callback for sceIoIoctlForDriver

typedef struct sceIoIoctlForDriver_args
{
  SceUID fd;
  unsigned int cmd;
  void *indata;
  int inlen;
  void *outdata;
  int outlen;
}sceIoIoctlForDriver_args;

SceOff t_sceIoLseekForDriver(sceIoIoctlForDriver* args);

t_sceIoChstatForDriver

Version NID
3.60 0xBCE4865B

thread callback for sceIoChstatForDriver

typedef struct sceIoChstatForDriver_args
{
   const char *file;
   SceIoStat *stat;
   int bits;
   uint32_t store_attr;
}sceIoChstatForDriver_args;

SceOff t_sceIoChstatForDriver(sceIoChstatForDriver_args* args);

t_sceIoChstatByFdForDriver

Version NID
3.60 0x7517FE29

thread callback for sceIoChstatByFdForDriver

struct sceIoChstatByFdForDriver_args
{
  SceUID uid;
  void *unk1;
  int unk2;
};

int t_sceIoChstatByFdForDriver(sceIoChstatByFdForDriver_args* args);

SceIofilemgrForDriver vfs callbacks

Vfs callbacks are harder to reverse since it looks like not all of them are exported. Looks like some of them are not even exposed as subroutines.

Here will go an attempt to desctibe interface of actual callbacks with single ctx argument (as opposed to exported functions that pack arguments into ctx)

vfs_func1


typedef struct vfs_func1_args
{
   vfs_mount* arg0;
   void* arg1;
}vfs_func1_args;

int vfs_func1(vfs_func1_args* ctx)

vfs_func2

typedef struct vfs_func2_args
{
   //fields are yet unknown
}vfs_func2_args;

int vfs_func2(vfs_func2_args* ctx)

vfs_func3


typedef struct vfs_func3_args
{
   vfs_mount* arg0;
   uint32_t arg1;
   vfs_node* arg2;

}vfs_func3_args;

int vfs_func3(vfs_func3_args* ctx)

vfs_func4

typedef struct vfs_func4_args
{
  vfs_node *node;
  uint32_t unk_4;
  uint32_t unk_8;

  //more fields?

}vfs_func4_args;

int vfs_func4(vfs_func4_args* ctx)

vfs_func7

typedef struct vfs_func7_args
{
   //fields are yet unknown
}vfs_func7_args;

int vfs_func7(vfs_func7_args* ctx)

vfs_func9

typedef struct vfs_func9_args
{
   //fields are yet unknown
}vfs_func9_args;

int vfs_func9(vfs_func9_args* ctx)

vfs_func10

typedef struct vfs_func10_args
{
   //fields are yet unknown
}vfs_func10_args;

int vfs_func10(vfs_func10_args* ctx)

vfs_func12

Version NID
3.60 0xB07B307D

int vfs_func12(vfs_mount* mount, const char *dev, unsigned int cmd, void *indata, int inlen, void *outdata, int outlen);

typedef struct vfs_func12_args
{
   uint32_t unk_0;
   uint32_t unk_4;
   uint32_t unk_8; // some switch number
   char* name;

   uint32_t nameLength;
   uint32_t unk_14;
   uint32_t unk_18;

   //more fields ?

}vfs_func12_args;

vfs_func13

Version NID
3.60 0xF7DAC0F5
typedef struct vfs_func13_args
{
   uint32_t unk_0;
   char* blockDeviceName;
   uint32_t unk_8;
   uint32_t unk_C;

   char* numericName;
   uint32_t blockDeviceNameLength;
   uint32_t* numericNameLength;
}vfs_func13_args;

int vfs_func13(vfs_func13_args* ctx)

SceIofilemgrForDriver vfs node callbacks

It looks like vfs callbacks are exported. Callbacks can be identified using these steps:

  • Find all functions that contain indirect calls
  • Locate only calls that use address, taken from table, that is pointed by vfs_node (offset 0x40, then valid offset inside pointer table)
  • Trace back to first exported function (usually this is single export, not far away in call stack)
  • Turns out ScePfsMgr and SceExfatfs use these exports from their vfs node function callbacks, so this information can be mapped/matched.

vfs_node_func1

Version NID
3.60 0x76B79BEC
int vfs_node_func1(vfs_node *node, vnf1_arg1* dev, int unk2, int unk3)

struct vnf1_arg1
{
  char* blockDevice;
  uint32_t nameLength;
  char* unixMount;
}vnf1_arg1;

//this type applies only to SceSdif

struct vnf1_arg3
{
  uint32_t unk_0;
  uint32_t unk_4;
  uint32_t unk_8;
  uint32_t unk_C;

  uint32_t unk_10;
  uint32_t unk_14;
  uint32_t unk_18;
  uint32_t unk_1C;

  sd_stor_device_handle* handle;

  //not sure about size, can be more fields ?

}vnf1_arg3;

struct vfs_node_func1_args
{
   vfs_node* node;
   vnf1_arg1* arg1; //ignored (applies to SceSdif)
   uint32_t arg2;
   vnf1_arg3* arg3; //result (applies to SceSdif)
}vfs_node_func1_args;

arguments are packed into vfs_node_func1_args and passed to vfs_node_func1 callback

vfs_node_func2

Version NID
3.60 0x9E347C7D
int vfs_node_func2(vfs_node *node, int unk1, int unk2, int unk3, int arg_0)

struct vfs_node_func2_args
{
   vfs_node* node;
   uint32_t arg1;
   uint32_t arg2;
   uint32_t arg3;
   uint32_t arg_0;
}vfs_node_func2_args;

arguments are packed into vfs_node_func2_args and passed to vfs_node_func2 callback

vfs_node_func3

Version NID
3.60 0x40944C2E
int vfs_node_func3(vfs_node *node, int unk1)

struct vfs_node_func3_args
{
   vfs_node* node;
   uint32_t arg1;
}vfs_node_func3_args;

arguments are packed into vfs_node_func3_args and passed to vfs_node_func3 callback

vfs_node_func4

Version NID
3.60 0xA5A6A55C
int vfs_node_func4(vfs_node *node, vfs_node** new_node, vnf4_arg2* dev, int unk3)

struct vnf4_arg2
{
   char* blockDeviceName;
   int nameLength;
} vnf4_arg2;

struct vfs_node_func4_args
{
   vfs_node* node; 
   vfs_node** new_node; //result
   vnf4_arg2* dev;
   uint32_t arg3; //ignored (applies to SceSdif)
}vfs_node_func4_args;

arguments are packed into vfs_node_func4_args and passed to vfs_node_func4 callback

vfs_node_func5_or_19

Version NID
3.60 0x570388A5
int vfs_node_func5_or_19(vfs_node *n0, int unk1, int unk2, int unk3, int arg_0)

vfs_node_func5_or_19

Version NID
3.60 0xABBC80E3
int vfs_node_func5_or_19(vfs_node *n0, int unk1, int unk2, int unk3, int arg_0, int arg_4, int arg_8)

vfs_node_func6_or_20

Version NID
3.60 0x9A68378D
int vfs_node_func6_or_20(vfs_node *n0, int unk1, int unk2, int unk3, int arg_0)

vfs_node_func6_or_20

Version NID
3.60 0xA53C040D
int vfs_node_func6_or_20(vfs_node *n0, int unk1, int unk2, int unk3, int arg_0, int arg_4, int arg_8)

vfs_node_func7

Version NID
3.60 0xB2B13818
int vfs_node_func7(vfs_node *node, vnf7_arg1* objectBase, SceOff offset, int whence)

struct vnf7_arg1
{
  uint32_t unk_0;
  uint32_t unk_4;
  uint32_t unk_8;
  uint32_t unk_C;

  uint32_t unk_10;
  uint32_t unk_14;
  uint32_t unk_18;
  uint32_t unk_1C;

  void* unk_20; // pointer to structure. most likely device specific that has fast_mutex as first field

} vnf7_arg1;

struct vfs_node_func7_args
{
   vfs_node* node;
   vnf7_arg1* objectBase; //some structure
   SceOff offset
   int whence
}vfs_node_func7_args;

arguments are packed into vfs_node_func7_args and passed to vfs_node_func7 callback

vfs_node_func8

Version NID
3.60 0x333C904D
int vfs_node_func8(vfs_node* node, void* objectBase, unsigned int cmd, void *indata, int inlen, void *outdata, int outlen)

struct vfs_node_func8_args
{
   vfs_node* node;
   void* objectBase;
   unsigned int cmd;
   void *indata;
   int inlen;
   void *outdata;
   int outlen;
}vfs_node_func8_args;

arguments are packed into vfs_node_func8_args and passed to vfs_node_func8 callback

vfs_node_func9

Version NID
3.60 0xDC1E7EE4
int vfs_node_func9(vfs_node *node0, vfs_node *node1, void *ctx, int unk)

need to confirm this type with dump

typedef struct vnf9_arg2 //most likely this type is also vfs_node (same partial layout of fields)
{
   char* blockDeviceName;
   int nameLength;
   uint32_t unk_8;
   uint32_t unk_C;
   
   uint32_t unk_10;
   uint32_t unk_14;
   uint32_t unk_18;
   uint32_t unk_1C;
   
   uint32_t unk_20;
   uint32_t unk_24;
   uint32_t unk_28;
   uint32_t unk_2C;
   
   uint32_t unk_30;
   uint32_t unk_34;
   uint32_t unk_38;
   uint32_t unk_3C;
   
   uint32_t unk_40;
   uint32_t unk_44;
   partition_entry** unk_48;
}vnf9_arg2;

struct vfs_node_func9_args
{
   vfs_node* node0;
   vfs_node* node1;
   vnf9_arg2* arg2;
   uint32_t arg3; //ignored (applies to SceSdif)
}vfs_node_func9_args;

arguments are packed into vfs_node_func9_args and passed to vfs_node_func9 callback

vfs_node_func10

Version NID
3.60 0x2F3F8C70
int vfs_node_func10(vfs_node* node, void* unk1, void* unk2, SceMode mode)

struct vfs_node_func10_args
{
   vfs_node* node;
   void* arg1;
   void* arg2;
   SceMode mode;
}vfs_node_func10_args;

arguments are packed into vfs_node_func10_args and passed to vfs_node_func10 callback

vfs_node_func11

Version NID
3.60 0x1D551105
int vfs_node_func11(vfs_node *node, int unk1, int unk2, int unused)

struct vfs_node_func11_args
{
   vfs_node* node;
   uint32_t arg1;
   uint32_t arg2;
}vfs_node_func11_args;

arguments are packed into vfs_node_func11_args and passed to vfs_node_func11 callback

vfs_node_func12

Version NID
3.60 0x00C9C2DD
int vfs_node_func12(vfs_node *node, int unk1, int unk2)

struct vfs_node_func12_args
{
   vfs_node* node;
   uint32_t arg1;
   uint32_t arg2;
}vfs_node_func12_args;

arguments are packed into vfs_node_func12_args and passed to vfs_node_func12 callback

vfs_node_func13

Version NID
3.60 0x1350F5C7
int vfs_node_func13(vfs_node *node, int unk1)

struct vfs_node_func13_args
{
   vfs_node* node;
   uint32_t arg1;
}vfs_node_func13_args;

arguments are packed into vfs_node_func13_args and passed to vfs_node_func13 callback

vfs_node_func14

Version NID
3.60 0x77584C8F
int vfs_node_func14(vfs_node* node, void* objectBase, SceIoDirent* dir)

struct vfs_node_func14_args
{
   vfs_node* node;
   void* objectBase;
   SceIoDirent* dir;
}vfs_node_func14_args;

arguments are packed into vfs_node_func14_args and passed to vfs_node_func14 callback

vfs_node_func15

Version NID
3.60 0x50A63ACF
int vfs_node_func15(vfs_node *node, vfs_node_func15_arg1* arg1, SceIoStat* stat)

typedef struct vfs_node_func15_arg1 //size is 0x10
{
   char* data; //from vfs_node_70 at 0x18
   int len;
   int unk_8;
   int unk_C;

}vfs_node_func15_arg1;

struct vfs_node_func15_args
{
   vfs_node* node;
   vfs_node_func15_arg1* arg1;
   SceIoStat* stat;
}vfs_node_func15_args;

arguments are packed into vfs_node_func15_args and passed to vfs_node_func15 callback

vfs_node_func16

Version NID
3.60 0x1974FA92
int vfs_node_func16(vfs_node *node, void *unk1, SceIoStat *stat, int bits)

struct vfs_node_func16_args
{
   vfs_node* node;
   uint32_t arg1;
   SceIoStat *stat;
   int bits;
}vfs_node_func16_args;

arguments are packed into vfs_node_func16_args and passed to vfs_node_func16 callback

vfs_node_func17

Version NID
3.60 0x36A794C7
int vfs_node_func17(vfs_node *node, int unk1, int unk2, int unk3, int arg_0, int arg_4)

struct vfs_node_func17_args
{
   vfs_node* node;
   uint32_t arg1;
   uint32_t arg2;
   uint32_t arg3;
   uint32_t arg_0;
   uint32_t arg_4;
}vfs_node_func17_args;

arguments are packed into vfs_node_func17_args and passed to vfs_node_func17 callback

vfs_node_func21

Version NID
3.60 0x8FB94521
int vfs_node_func21(vfs_node *node)

struct vfs_node_func21_args
{
   vfs_node* node;
}vfs_node_func21_args;

arguments are packed into vfs_node_func21_args and passed to vfs_node_func21 callback

vfs_node_func22

Version NID
3.60 0x942AA61F
int vfs_node_func22(vfs_node *node, int unk1)

struct vfs_node_func22_args
{
   vfs_node* node;
   uint32_t arg1;
}vfs_node_func22_args;

arguments are packed into vfs_node_func22_args and passed to vfs_node_func22 callback

vfs_node_func23

Version NID
3.60 0x0D8A806E
int vfs_node_func23(vfs_node *node, int unk1)

struct vfs_node_func23_args
{
   vfs_node* node;
   uint32_t arg1;
}vfs_node_func23_args;

arguments are packed into vfs_node_func23_args and passed to vfs_node_func23 callback

vfs_node_func24

Version NID
3.60 0x9CD96406
int vfs_node_func24(vfs_node *node, void *objectBase, int flag)

struct vfs_node_func24_args
{
   vfs_node* node;
   void *objectBase;
   int flag;
}vfs_node_func24_args;

arguments are packed into vfs_node_func24_args and passed to vfs_node_func24 callback

vfs_node_func25

Version NID
3.60 0x1DBCBB01

int vfs_node_func25(vfs_node *node, void* objectBase, SceIoStat *stat)

struct vfs_node_func25_args
{
   vfs_node* node;
   void* objectBase;
   SceIoStat *stat;
}vfs_node_func25_args;

arguments are packed into vfs_node_func25_args and passed to vfs_node_func25 callback

vfs_node_func26

Version NID
3.60 0x082AFD7F
int vfs_node_func26(vfs_node *node, void *objectBase, SceIoStat *stat, int bits)

struct vfs_node_func26_args
{
   vfs_node* node;
   void *objectBase;
   SceIoStat *stat;
   int bits;
}vfs_node_func26_args;

arguments are packed into vfs_node_func26_args and passed to vfs_node_func26 callback

vfs_node_func27

Version NID
3.60 0xF53399BC
int vfs_node_func27(int unk0, vfs_node *node, int unk2, int unk3)

struct vfs_node_func27_args
{
   uint32_t arg0;
   vfs_node* node;
   uint32_t arg2;
   uint32_t arg3;
   uint32_t unk_10; // zero
   uint32_t unk_14; // zero
}vfs_node_func27_args;

arguments are packed into vfs_node_func27_args and passed to vfs_node_func27 callback

vfs_node_func28

Version NID
3.60 0x0F7E1718
int vfs_node_func28(vfs_node *node, int unk1, int unused1, int unused2)

struct vfs_node_func28_args
{
   vfs_node* node;
   uint32_t arg1;
   uint32_t unk_8; // zero
   uint32_t unk_C; // zero
}vfs_node_func28_args;

arguments are packed into vfs_node_func28_args and passed to vfs_node_func28 callback

vfs_node_func29

Version NID
3.60 0xEEAE8B51
int vfs_node_func29(vfs_node *node, int unused, int unk2, int unk3, int arg_0, int arg_4, int arg_8, int arg_C)

struct vfs_node_func29_args
{
   uint32_t unk_0;
   uint32_t unk_4;
   uint32_t arg2;
   uint32_t arg3;
   uint32_t arg_0;
   uint32_t arg_4;
   uint32_t arg_8;
   uint32_t arg_C;
}vfs_node_func29_args;

arguments are packed into vfs_node_func29_args and passed to vfs_node_func29 callback

SceIofilemgr

_sceIoDcloseAsync

Version NID
1.69 0xB13031
3.60 different NID or not present

_sceIoOpenAsync

Version NID
1.69 0x9CD0FC8
3.60 0x9CD0FC8

sceIoGetProcessDefaultPriority

Version NID
1.69 0xDC4F1BB
3.60 0xDC4F1BB

_sceIoRmdirAsync

Version NID
1.69 0x13DC3244
3.60 0x13DC3244

sceIoSetPriority

Version NID
1.69 0x14B2D56C
3.60 0x14B2D56C

sceIoSyncByFd

Version NID
1.69 0x16512F59
3.60 0x16512F59
 int sceIoSyncByFd(SceUID fd, unsigned int unk);

_sceIoIoctl

Version NID
1.69 0x1D2988F1
3.60 0x1D2988F1

_sceIoLseekAsync

Version NID
1.69 0x2300858E
3.60 0x2300858E

sceIoSetPriorityForSystem

Version NID
1.69 0x27373135
3.60 0x27373135

_sceIoComplete

Version NID
1.69 0x34E6A06E
3.60 different NID or not present

sceIoWrite

Version NID
1.69 0x34EFD876
3.60 0x34EFD876
int sceIoWrite(SceUID fd, const void *data, SceSize size);

_sceIoGetThreadDefaultPriorityForSystem

Version NID
1.69 0x36CAF911
3.60 different NID or not present

_sceIoSetThreadDefaultPriorityForSystem

Version NID
1.69 0x38FE853B
3.60 different NID or not present

sceIoFlockForSystem

Version NID
1.69 0x3E98E422
3.60 0x3E98E422

_sceIoDevctlAsync

Version NID
1.69 0x3EE3F66E
3.60 0x3EE3F66E

sceIoDclose

Version NID
1.69 0x422A221A
3.60 0x422A221A
int sceIoDclose(SceUID fd);

_sceIoRename

Version NID
1.69 0x4912F748
3.60 0x4912F748
typedef struct sceIoRenameOpt
{
  uint32_t unk_0;
  uint32_t unk_4;
  uint32_t unk_8;
  uint32_t unk_C;
}sceIoRenameOpt;

int _sceIoRename(const char *oldname, const char *newname, sceIoRenameOpt *opt);

sceIoLseek32

Version NID
1.69 0x49252B9B
3.60 0x49252B9B
int sceIoLseek32(SceUID fd, int offset, int whence);

sceIoSetThreadDefaultPriority

Version NID
1.69 0x49312108
3.60 0x49312108

_sceIoDevctl

Version NID
1.69 0x515AC017
3.60 0x515AC017
typedef struct sceIoDevctlOpt
{
   uint32_t unk_0;
   uint32_t unk_4;
   uint32_t unk_8;
   uint32_t unk_C;
   uint32_t unk_10;
   uint32_t unk_14;
}sceIoDevctlOpt;

int _sceIoDevctl(const char *dev, unsigned int cmd, void *indata, sceIoDevctlOpt *args, int inlen, void *outdata, int outlen);

sceIoGetstatByFdAsync

Version NID
1.69 0x5167AC1E
3.60 0x5167AC1E

_sceIoPread

Version NID
1.69 0x539FD5C4
3.60 0x539FD5C4

_sceIoGetstatByFdAsync

Version NID
1.69 0x554292F0
3.60 different NID or not present

_sceIoChstatByFdAsync

Version NID
1.69 0x58010F40
3.60 different NID or not present

_sceIoGetThreadDefaultPriority

Version NID
1.69 0x5DC29460
3.60 different NID or not present

_sceIoSync

Version NID
1.69 0x5DD867F7
3.60 0x5DD867F7
typedef struct sceIoSyncOpt
{
  uint32_t unk_0;
  uint32_t unk_4;
}sceIoSyncOpt;

int _sceIoSync(const char* device, unsigned int unk, sceIoSyncOpt* opt);

_sceIoRemoveAsync

Version NID
1.69 0x5FFA47E2
3.60 0x5FFA47E2

_sceIoDreadAsync

Version NID
1.69 0x64B233B8
3.60 different NID or not present

_sceIoSetThreadDefaultPriority

Version NID
1.69 0x654E27B1
3.60 different NID or not present

_sceIoSyncByFdAsync

Version NID
1.69 0x6F78FAFE
3.60 different NID or not present

_sceIoGetPriorityForSystem

Version NID
1.69 0x70B7BB52
3.60 different NID or not present

sceIoReadAsync

Version NID
1.69 0x773EBD45
3.60 0x773EBD45

_sceIoRemove

Version NID
1.69 0x78955C65
3.60 0x78955C65
typedef struct sceIoRemoveOpt
{
  uint32_t unk_0;
  uint32_t unk_4;
}sceIoRemove;

int _sceIoRemove(const char *file, sceIoRemoveOpt* opt);

sceIoSyncByFdAsync

Version NID
1.69 0x7E1367CB
3.60 0x7E1367CB

sceIoSetProcessDefaultPriority

Version NID
1.69 0x7F2ABBAF
3.60 0x7F2ABBAF

_sceIoRenameAsync

Version NID
1.69 0x81794921
3.60 0x81794921

_sceIoSyncAsync

Version NID
1.69 0x86DB0C0E
3.60 0x86DB0C0E

_sceIoDread

Version NID
1.69 0x8713D662
3.60 0x8713D662
int _sceIoDread(SceUID fd, SceIoDirent *dir);

_sceIoWrite

Version NID
1.69 0x8C319CF0
3.60 different NID or not present

_sceIoGetstat

Version NID
1.69 0x8E7E11F2
3.60 0x8E7E11F2
struct sceIoGetstatOpt
{
  uint32_t unk_0;
  uint32_t unk_4;
};

int _sceIoGetstat(const char *file, SceIoStat *stat, sceIoGetstatOpt *opt);

sceIoCloseAsync

Version NID
1.69 0x8EA3616A
3.60 0x8EA3616A

_sceIoMkdir

Version NID
1.69 0x8F1ACC32
3.60 0x8F1ACC32
 
typedef struct sceIoMkdirOpt
{
  uint32_t unk_0;
  uint32_t unk_4;
}sceIoMkdirOpt;

int _sceIoMkdir(const char *dir, SceMode mode, sceIoMkdirOpt opt);

_sceIoCompleteMultiple

Version NID
1.69 0x9111D004
3.60 0x9111D004

_sceIoLseek32

Version NID
1.69 0x92BDA6DA
3.60 different NID or not present

_sceIoPwrite

Version NID
1.69 0x9654094B
3.60 0x9654094B

_sceIoGetPriority

Version NID
1.69 0x9E3F880D
3.60 different NID or not present

sceIoGetThreadDefaultPriority

Version NID
1.69 0xA176CD03
3.60 0xA176CD03

_sceIoLseek

Version NID
1.69 0xA604764A
3.60 0xA604764A
typedef struct _sceIoLseekOpt //size is 0x10
{
  SceOff offset;
  int whence;
  uint32_t unk;
}_sceIoLseekOpt;

SceOff _sceIoLseek(SceUID fd, _sceIoLseekOpt* opt);

sceIoChstatByFdAsync

Version NID
1.69 0xA9F89275
3.60 0xA9F89275

_sceIoGetProcessDefaultPriority

Version NID
1.69 0xB0486482
3.60 different NID or not present

_sceIoSetPriority

Version NID
1.69 0xB14192F0
3.60 different NID or not present

_sceIoReadAsync

Version NID
1.69 0xB2B891E6
3.60 different NID or not present

_sceIoPwriteAsync

Version NID
1.69 0xB2D0B2F4
3.60 0xB2D0B2F4

_sceIoChstatAsync

Version NID
1.69 0xB4B021D9
3.60 0xB4B021D9

sceIoSetThreadDefaultPriorityForSystem

Version NID
1.69 0xB9C9C9CF
3.60 0xB9C9C9CF

_sceIoPreadAsync

Version NID
1.69 0xBCF5684D
3.60 0xBCF5684D

sceIoDopenAsync

Version NID
1.69 0xC49C312F
3.60 0xC49C312F

sceIoClose

Version NID
1.69 0xC70B8886
3.60 0xC70B8886
 int sceIoClose(SceUID fd);

_sceIoWriteAsync

Version NID
1.69 0xC92AF88F
3.60 different NID or not present

_sceIoOpen

Version NID
1.69 0xCC67B6FD
3.60 0xCC67B6FD
struct sceIoOpenOpt
{
  uint32_t unk_0;
  uint32_t unk_4;
};

SceUID _sceIoOpen(const char *file, int flags, SceMode mode, sceIoOpenOpt *opt);

sceIoCancel

Version NID
1.69 0xCEF48835
3.60 0xCEF48835

sceIoComplete

Version NID
1.69 0xD1C49D2F
3.60 0xD1C49D2F

_sceIoChstat

Version NID
1.69 0xD2EE455F
3.60 0xD2EE455F
struct sceIoChstatOpt
{
  uint32_t unk_0;
  uint32_t unk_4;
};

int _sceIoChstat(const char *file, SceIoStat *stat, int bits, sceIoChstatOpt *opt);

_sceIoSetProcessDefaultPriority

Version NID
1.69 0xD302DCB9
3.60 different NID or not present

_sceIoGetstatAsync

Version NID
1.69 0xD414C89F
3.60 0xD414C89F

sceIoDcloseAsync

Version NID
1.69 0xDC2D7D38
3.60 0xDC2D7D38

_sceIoIoctlAsync

Version NID
1.69 0xE00DC256
3.60 0xE00DC256

_sceIoChstatByFd

Version NID
1.69 0xE0BE2A30
3.60 0xE0BE2A30
 int _sceIoChstatByFd(SceUID fd, SceIoStat *stat, int bits);

sceIoWriteAsync

Version NID
1.69 0xE0D63D2A
3.60 0xE0D63D2A

_sceIoGetstatByFd

Version NID
1.69 0xE6C53567
3.60 0xE6C53567
int _sceIoGetstatByFd(SceUID fd, SceIoStat *stat);

_sceIoSetPriorityForSystem

Version NID
1.69 0xE6C923B3
3.60 different NID or not present

_sceIoDopen

Version NID
1.69 0xE6E614B5
3.60 0xE6E614B5
struct sceIoDopenOpt
{
  uint32_t unk_0;
  uint32_t unk_4;
};

SceUID _sceIoDopen(const char *dirname, sceIoDopenOpt *opt);

sceIoGetPriorityForSystem

Version NID
1.69 0xEF5432ED
3.60 0xEF5432ED

sceIoGetPriority

Version NID
1.69 0xF2A472A1
3.60 0xF2A472A1

_sceIoRead

Version NID
1.69 0xF3C9E783
3.60 different NID or not present

_sceIoSyncByFd

Version NID
1.69 0xF437545D
3.60 different NID or not present

_sceIoCloseAsync

Version NID
1.69 0xF4E13260
3.60 different NID or not present

_sceIoDopenAsync

Version NID
1.69 0xF58286C3
3.60 different NID or not present

sceIoDreadAsync

Version NID
1.69 0xF59F37B0
3.60 0xF59F37B0

_sceIoMkdirAsync

Version NID
1.69 0xF5C58B21
3.60 0xF5C58B21

_sceIoCancel

Version NID
1.69 0xF5DEEA19
3.60 different NID or not present

_sceIoClose

Version NID
1.69 0xF69FB394
3.60 different NID or not present

_sceIoDclose

Version NID
1.69 0xFAFF0002
3.60 different NID or not present

sceIoGetThreadDefaultPriorityForSystem

Version NID
1.69 0xFCBCEAED
3.60 0xFCBCEAED

sceIoRead

Version NID
1.69 0xFDB32293
3.60 0xFDB32293
sceIoRead(SceUID fd, void *data, SceSize size);

_sceIoRmdir

Version NID
1.69 0xFFFB4D76
3.60 0xFFFB4D76
typedef struct sceIoRmdirOpt
{
  uint32_t unk_0;
  uint32_t unk_4;
}sceIoRmdirOpt;

int _sceIoRmdir(const char *path, sceIoRmdirOpt* opt);

Device Drivers