Filesystem services
Filesystem service "fs:USER"
You can at most have 32 FS archive handles.
Command Header | Available since system version | Description | Required exheader access info bitmask |
---|---|---|---|
0x000100C6 | ? | Dummy1 | None |
0x040100C4 | ? | Control | None |
0x08010002 | ? | Initialize | None |
0x080201C2 | ? | OpenFile | None |
0x08030204 | ? | OpenFileDirectly | None |
0x08040142 | ? | DeleteFile | None |
0x08050244 | ? | RenameFile | None |
0x08060142 | ? | DeleteDirectory | None |
0x08070142 | ? | DeleteDirectoryRecursively | None |
0x08080202 | ? | CreateFile | None |
0x08090182 | ? | CreateDirectory | None |
0x080A0244 | ? | RenameDirectory | None |
0x080B0102 | ? | OpenDirectory | None |
0x080C00C2 | ? | OpenArchive | Each archive ID code has separate access info bitmasks, if it has any |
0x080D0144 | ? | ControlArchive | None |
0x080E0080 | ? | CloseArchive | None |
0x080F0180 | ? | Obsoleted_2_0_FormatThisUserSaveData | None |
0x08100200 | ? | Obsoleted_3_0_CreateSystemSaveData | 0x4, for when the input saveID doesn't match the exheader saveID |
0x08110040 | ? | Obsoleted_3_0_DeleteSystemSaveData | 0x1004, for when the input saveID doesn't match the exheader saveID |
0x08120080 | ? | GetFreeBytes | None |
0x08130000 | ? | GetCardType | 0x1017 |
0x08140000 | ? | GetSdmcArchiveResource | None |
0x08150000 | ? | GetNandArchiveResource | 0x1007 |
0x08160000 | ? | GetSdmcFatfsError | 0x2 |
0x08170000 | ? | IsSdmcDetected | None |
0x08180000 | ? | IsSdmcWritable | None |
0x08190042 | ? | GetSdmcCid | 0x2 |
0x081A0042 | ? | GetNandCid | 0x2 |
0x081B0000 | ? | GetSdmcSpeedInfo | 0x2 |
0x081C0000 | ? | GetNandSpeedInfo | 0x2 |
0x081D0042 | ? | GetSdmcLog | 0x2 |
0x081E0042 | ? | GetNandLog | 0x2 |
0x081F0000 | ? | ClearSdmcLog | 0x2 |
0x08200000 | ? | ClearNandLog | 0x2 |
0x08210000 | ? | CardSlotIsInserted | 0x1017 |
0x08220000 | ? | CardSlotPowerOn | 0x2 |
0x08230000 | ? | CardSlotPowerOff | 0x2 |
0x08240000 | ? | CardSlotGetCardIFPowerStatus | 0x2 |
0x08250040 | ? | CardNorDirectCommand | 0x2 |
0x08260080 | ? | CardNorDirectCommandWithAddress | 0x2 |
0x08270082 | ? | CardNorDirectRead | 0x2 |
0x082800C2 | ? | CardNorDirectReadWithAddress | 0x2 |
0x08290082 | ? | CardNorDirectWrite | 0x2 |
0x082A00C2 | ? | CardNorDirectWriteWithAddress | 0x2 |
0x082B00C2 | ? | CardNorDirectRead_4xIO | 0x2 |
0x082C0082 | ? | CardNorDirectCpuWriteWithoutVerify | 0x2 |
0x082D0040 | ? | CardNorDirectSectorEraseWithoutVerify | 0x2 |
0x082E0040 | ? | GetProductInfo | 0x1005 |
0x082F0040 | ? | GetProgramLaunchInfo | 0x1005 |
0x08300182 | ? | Obsoleted_3_0_CreateExtSaveData | 0xC, for when the input extdataID doesn't match the exheader extdataID |
0x08310180 | ? | Obsoleted_3_0_CreateSharedExtSaveData | 0x1005 |
0x08320102 | ? | Obsoleted_3_0_ReadExtSaveDataIcon | 0x100D, for when the input extdataID doesn't match the exheader extdataID |
0x08330082 | ? | Obsoleted_3_0_EnumerateExtSaveData | 0x1005 |
0x08340082 | ? | Obsoleted_3_0_EnumerateSharedExtSaveData | 0x1005 |
0x08350080 | ? | Obsoleted_3_0_DeleteExtSaveData | 0x100D, for when the input extdataID doesn't match the exheader extdataID |
0x08360080 | ? | Obsoleted_3_0_DeleteSharedExtSaveData | 0x1005 |
0x08370040 | ? | SetCardSpiBaudRate | 0x2 |
0x08380040 | ? | SetCardSpiBusMode | 0x2 |
0x08390000 | ? | SendInitializeInfoTo9 | None |
0x083A0100 | ? | GetSpecialContentIndex | 0x1005 |
0x083B00C2 | ? | GetLegacyRomHeader | 0x1015 |
0x083C00C2 | ? | GetLegacyBannerData | 0x1015 |
0x083D0100 | ? | CheckAuthorityToAccessExtSaveData | 0x44 |
0x083E00C2 | ? | QueryTotalQuotaSize | None |
0x083F00C0 | ? | Obsoleted_3_0_GetExtDataBlockSize | None |
0x08400040 | ? | AbnegateAccessRight | ? |
0x08410000 | ? | DeleteSdmcRoot | 0x1005 |
0x08420040 | ? | DeleteAllExtSaveDataOnNand | 0x1005 |
0x08430000 | ? | InitializeCtrFileSystem | None |
0x08440000 | ? | CreateSeed | 0x2 |
0x084500C2 | ? | GetFormatInfo | ? |
0x08460102 | ? | GetLegacyRomHeader2 | 0x1015 |
0x08470180 | ? | Obsoleted_2_0_FormatCtrCardUserSaveData | 0x6 |
0x08480042 | ? | GetSdmcCtrRootPath | 0x100D |
0x08490040 | ? | GetArchiveResource | ? |
0x084A0002 | ? | ExportIntegrityVerificationSeed | 0x4000 |
0x084B0002 | ? | ImportIntegrityVerificationSeed | 0x4000 |
0x084C0242 | ? | FormatSaveData | 0x6, in some cases this write isn't needed however |
0x084D0102 | ? | GetLegacySubBannerData | 0x1015 |
0x084E0342 | ? | UpdateSha256Context | 0x5 |
0x084F0102 | ? | ReadSpecialFile | None |
0x08500040 | ? | GetSpecialFileSize | None |
0x08510242 | 3.0.0-5 | CreateExtSaveData | Shared extdata: 0x101005. Regular extdata in certain cases: 0xC |
0x08520100 | 3.0.0-5 | DeleteExtSaveData | Shared extdata: 0x101005. Regular extdata in certain cases: 0x10100D |
0x08530142 | 3.0.0-5 | ReadExtSaveDataIcon | 0x10100D (this doesn't apply in certain cases, however) |
0x085400C0 | 3.0.0-5 | GetExtDataBlockSize | 0x10100D (this doesn't apply in certain cases, however) |
0x08550102 | 3.0.0-5 | EnumerateExtSaveData | 0x101005 |
0x08560200 | 3.0.0-5 | CreateSystemSaveData | 0x4 (this doesn't apply in certain cases, however) |
0x08570080 | 3.0.0-5 | DeleteSystemSaveData | 0x1004 (this doesn't apply in certain cases, however) |
0x08580000 | 3.0.0-5 | GetMovableSedHashedKeyYRandomData | 0x2004 |
0x08590200 | 3.0.0-5 | SetMovableSedHashedKeyYRandomData | 0x2004 |
0x085A00C0 | 3.0.0-5 | SetArchivePriority | None |
0x085B0080 | 3.0.0-5 | GetArchivePriority | None |
0x085C00C0 | 3.0.0-5 | SetCtrCardLatencyParameter | 0xE |
0x085D0180 | 3.0.0-5 | SetFsCompatibilityInfo | 0x100001 |
0x085E0040 | 3.0.0-5 | ResetCardCompatibilityParameter | 0xE |
0x085F0040 | 3.0.0-5 | SwitchCleanupInvalidSaveData | 0x12004 |
0x08600042 | 3.0.0-5 | EnumerateSystemSaveData | 0x2004 |
0x08610042 | 3.0.0-5 | InitializeWithSdkVersion | None |
0x08620040 | 3.0.0-5 | SetPriority | None |
0x08630000 | 3.0.0-5 | GetPriority | None |
0x08640000 | 3.0.0-5 | Obsoleted_4_0_GetNandInfo | Stubbed, this returns an error |
0x08650140 | 4.0.0-7 | SetSaveDataSecureValue | 0x121004 (in certain cases this doesn't apply, however) |
0x086600C0 | 4.0.0-7 | GetSaveDataSecureValue | 0x121004 (in certain cases this doesn't apply, however) |
0x086700C4 | 4.0.0-7 | ControlSecureSave | 0x121004 |
0x08680000 | 4.0.0-7 | GetMediaType | None |
0x08690000 | 4.0.0-7 | Obsoleted_4_0_GetNandEraseCount | Stubbed, this returns an error. |
0x086A0082 | 4.0.0-7 | ReadNandReport | None |
0x086B00C2 | ? | ? | 00121004 |
0x086C00C2 | ? | ? | 00121004 |
0x086D0040 | ? | ? | 00020004 |
0x086E00C0 | ? | ? | None? |
0x086F0040 | ? | ? | 0xE |
0x087000C2 | ? | ? | None? |
0x08710100 | ? | ? | 0xC |
0x087201C0 | ? | ? | 00080004 |
0x087300C0 | ? | ? | 00080004 |
0x08740000 | ? | ? | 00080004 |
0x08750140 | ? | ? | None? |
0x087600C0 | ? | ? | None? |
0x08770100 | ? | ? | ? |
0x087800C0 | ? | ? | ? |
0x087900C2 | ? | Same as GetLegacyBannerData, except for the last parameter this passes u8 value 0x1 instead of 0x0, for the FSPXI command. | 0x00101015 |
0x087A.... | 9.6.0-X | ? | 0x00200000 |
0x087B.... | 9.6.0-X | Wrapper for the code internally used for command <0x087A....>. | 0x00200000 |
0x087C.... | 9.6.0-X | Eventually calls same code as command <0x087A....>. | 0x00200000 |
0x087D0000 | 9.6.0-X | Writes an u32 from state to cmdreply[2]. Probably the total number of titles in the SEEDDB? | 0x00200000 |
0x087E0042 | 9.6.0-X | Eventually calls same code as command <0x087A....>. Writes a list of titleIDs to the outbuf, this is for titles with content-lock-seed(s) stored in SEEDDB. (u32 total_titleids_probably, ((Size<<4) | 12), outbufptr) | 0x00200000 |
0x087F.... | 9.6.0-X | ? | 0x00200000 |
0x0880.... | 9.6.0-X | Eventually calls same code as command <0x087A....>. | 0x00200000 |
0x0881.... | 9.6.0-X | Eventually calls same code as command <0x087A....>. | 0x00200000 |
0x0882.... | 9.6.0-X | Eventually calls same code as command <0x087A....>. | 0x00200000 |
0x08830000 | 9.6.0-X | Writes an output value to cmdreply[2]. | 0x00200000 |
0x08840042 | 9.6.0-X | Eventually calls same code as command <0x087A....>. | 0x00200000 |
0x0885.... | 9.6.0-X | ? | 0x00200000 |
Note: The question marks from Dummy1 to GetSpecialFileSize on the "available since system version" field are mainly there because I think that most of these are necessary for the main system to function, so theoretically that would mean that since the creation of the 3DS these were available, or since launch if that makes more sense. But because of the peculiar nature of some of the functions, they will remain question marks until they can be confirmed 100%.
When access rights are required for a command, at least one of the bits in the process access info specified in the above table for the command must be set. Error 0xD9004676 is returned when a process attempts to use a command which it doesn't have access rights for the command. The exheader access info field is all zero's for most applications. Note that the permissions listed in the above table is for system-version v2.x, therefore permission bit(s) added with newer FIRM may be missing from this.
Each session for fs:USER has separate permissions, initially these are set to all zero's for new fs:USER sessions. The permissions/etc for fs:USER sessions are initialized via FS:Initialize(loaded from the user process exheader).
File service
Command Header | Description |
---|---|
0x000100C6 | Dummy1 |
0x040100C4 | Control |
0x08010100 | OpenSubFile |
0x080200C2 | Read |
0x08030102 | Write |
0x08040000 | GetSize |
0x08050080 | SetSize |
0x08060000 | GetAttributes |
0x08070040 | SetAttributes |
0x08080000 | Close |
0x08090000 | Flush |
0x080A0040 | SetPriority |
0x080B0000 | GetPriority |
0x080C0000 | OpenLinkFile |
0x0C010100 | ? (takes two u64(?), outputs u64) |
Directory service
Command Header | Available since system version | Description |
---|---|---|
0x000100C6 | 1.0.0-0 | Dummy1 |
0x040100C4 | 1.0.0-0 | Control |
0x08010042 | 1.0.0-0 | Read |
0x08020000 | 1.0.0-0 | Close |
0x08030040 | ? | SetPriority |
0x08040000 | ? | GetPriority |
Filesystem service "fs:LDR"
This service is identical to fs:USER, except FS:OpenArchive archive 0x2345678E can only be accessed with fs:LDR.
ProgramRegistry service "fs:REG"
Command Header | Description |
---|---|
0x000100C6 | Dummy1 |
0x040103C0 | Register |
0x04020040 | Unregister |
0x040300C0 | GetProgramInfo |
0x04040100 | LoadProgram |
0x04050080 | UnloadProgram |
0x04060080 | CheckHostLoadId |
Only one session can be opened for this service at a time, hence no other processes can use this due to pm-module using this.
SEEDDB
With 9.6.0-X new System_SaveData with saveID 0001000F was added, this seems to be handled by FS-module itself, probably via the new service-cmds added to fsuser. Home Menu and NIM module have access to those commands.
The SEEDDB savedata contains the title-unique seed-data used for the new NCCH keyY generation added with FIRM 9.6.0-X.
Common Types
MediaType
Value | Description |
---|---|
0 | NAND |
1 | SD |
2 | Game Card |
OpenFlags
Bit | Description |
---|---|
0 | Read |
1 | Write |
2 | Create |
Attributes
Flag | Description |
---|---|
0x00000001 | Is Read-Only |
0x00000100 | Is Archive |
0x00010000 | Is Hidden |
0x01000000 | Is Directory |
ArchiveResource
Offset | Size | Description |
---|---|---|
0x0 | 0x4 | Sector byte-size |
0x4 | 0x4 | Cluster byte-size |
0x8 | 0x4 | Partition capacity in clusters |
0xC | 0x4 | Available free space in clusters |
ArchiveId
Idcode | Description | Accessible via FS | Accessible via FSPXI | Requires binary Lowpath |
---|---|---|---|---|
0x00000003 | Application RomFS | Yes | No | No |
0x00000004 | SaveData (the saveID/mediatype for this is loaded from data originally from the user process' exheader) | Yes | No | No |
0x00000006 | ExtSaveData | Yes | No | Yes |
0x00000007 | Shared ExtSaveData | Yes | No | Yes |
0x00000008 | SystemSaveData | Yes | No | Yes |
0x00000009 | SDMC | Yes | Yes | No |
0x0000000A | SDMC Write-Only | Yes | No | No |
0x12345678 | ExtSaveData for BOSS | Yes | No | Yes |
0x12345679 | CARD SPI FS | Yes | Yes | No |
0x1234567B | ExtSaveData, and ExtSaveData for BOSS | No | Yes | Yes |
0x1234567C | SystemSaveData | No | Yes | Yes |
0x1234567D | NAND RW | Yes | Yes | No |
0x1234567E | NAND RO | Yes | Yes | No |
0x1234567F | NAND RO Write FS | No | Yes | No |
0x2345678A | User/GameCard SaveData (for check), and other uses (FS can only mount the latter) (lo hi mediatype reserved) | Yes | Yes | Yes |
0x2345678B | ? | No | No | Yes |
0x2345678C | ? | No | No | Yes |
0x2345678D | ? | No | No | No |
0x2345678E | SaveData, ExeFS, and RomFS (For fs:LDR, only ExeFS) | Yes | Yes | Yes |
0x567890AB | NAND CTR FS | No | Yes | No |
0x567890AC | TWL PHOTO | Yes | Yes | No |
0x567890AD | ? | No | Yes | No |
0x567890AE | NAND TWL FS | Yes | Yes | No |
0x567890AF | NAND W FS | Yes | Yes | No |
0x567890B0 | ? | No | Yes | No |
0x567890B1 | Gamecard SaveData (for check). This is a wrapper for UserSaveDataForCheck: the OpenArchive code for that is called with archive-lowpath TID=0/mediatype=2(gamecard). | Yes | No | No |
0x567890B2 | UserSaveData (for check). This is the same as the regular SaveData archive, except with this the savedata ID and mediatype is loaded from the input archive lowpath. | Yes | No | Yes |
0x567890B4 | ? SaveData from Demo Version of Retail Game | Yes | No | No |
Archives listed as not requiring a binary lowpath, use lowpath type empty.
Archives CTR NAND, NAND RO Write FS, TWL NAND, NAND W FS, and CARD SPI FS require the corresponding process exheader access control mount flag to be set, in the exheader for any of the currently running ARM11 processes, for FSPXI. The access rights checked by FS module for archive mounting with fs:USER, are stored in the process' exheader accessinfo.
The CARDSPI archive allows access to the gamecard CARD1 raw savedata flash(aka "cardspi:/" in Process9), the file lowpath must be WCHAR "/". The "NAND W FS" archive allows access to the raw NAND image(aka "wnand:/" in Process9), the file lowpath must be WCHAR "/".
PathType
Value | Description |
---|---|
0x0 | INVALID - Specifies an invalid path. |
0x1 | EMPTY - Specifies an empty path. |
0x2 | BINARY - Non-text based path. Meaning is per-archive. |
0x3 | CHAR - Text-based path with 8-bit characters. |
0x4 | WCHAR - Text-based path with 16-bit characters. |
Binary LowPath
The format of the data that a binary LowPath points to is custom per archive.
SystemSaveData Archive Path Data Format
FS
Index word | Description |
---|---|
0 | Mediatype (must be zero for NAND) |
1 | saveid |
The file/directory lowpath is a text lowpath in the savegame filesystem.
FSPXI
Index word | Description |
---|---|
0 | u8 Mediatype (must be zero for NAND) |
The file lowpath is a binary lowpath containing the u64 saveid, however the high word of the saveid is always zero. The mounted file is the cleartext savegame image. Up to 32 SystemSaveData image files can be opened under a single mounted FSPXI archive.
UserSaveDataForCheck Archive Path Data Format
Index word | Description |
---|---|
0 | Mediatype (must be non-zero) |
1 | Lower word saveid |
2 | Upper word saveid |
The file/directory lowpath for this FS archive is a text path in the savegame filesystem.
ExtSaveData Archive Path Data Format
Index word | Description |
---|---|
0 | Mediatype |
1 | Lower word saveid |
2 | Upper word saveid |
For FS, the file/directory lowpath is a text path in the extdata filesystem. For FSPXI, the file lowpath is a text path relative to the "/extdata/<ExtdataIDHigh>/<ExtdataIDLow>" directory on SD/NAND, for the cleartext extdata image to mount.
RomFS
The raw FS image for the main CXI RomFS(for the current app this is accessible via archiveid 0x3) can be accessed via an all-zero 0xc-byte binary file-lowpath. This allows access to the raw level-3 IVFC image: the user process must handle parsing the filesystem used in this image itself.
In this scenario, OpenFile returns a handle to the RomFS archive.
ProgramInfo
Offset | Size | Description |
---|---|---|
0x0 | 0x8 | Program ID |
0x8 | 0x1 | Media Type |
0xC | 0x4 | Reserved |
ProductInfo
Offset | Size | Description |
---|---|---|
0x0 | 0x10 | Product Code |
0x10 | 0x2 | Company Code |
0x12 | 0x2 | Remaster Version |
IntegrityVerificationSeed
Offset | Size | Description |
---|---|---|
0x0 | 0x10 | AES-CBC MAC over a SHA256 hash, which hashes the first 0x110-bytes of the cleartext SEED. |
0x10 | 0x120 | The nand/private/movable.sed, encrypted with AES-CTR using the above MAC for the counter. |
ExtSaveDataInfo
Offset | Size | Description |
---|---|---|
0x0 | 0x1 | Media Type |
0x1 | 0x1 | Unknown |
0x2 | 0x2 | Reserved |
0x4 | 0x8 | Save ID |
0xC | 0x4 | Reserved |
SystemSaveDataInfo
Offset | Size | Description |
---|---|---|
0x0 | 0x1 | Media Type |
0x1 | 0x1 | Unknown |
0x2 | 0x2 | Reserved |
0x4 | 0x4 | Save ID |
SecureValueSlot
Value | Description |
---|---|
0x1000 | SD Application |
CardSpiBaudRate
Value | Description |
---|---|
0x0 | 512KHz |
0x1 | 1MHz |
0x2 | 2MHz |
0x3 | 4MHz |
0x4 | 8MHz |
0x5 | 16MHz |
CardSpiBusMode
Value | Description |
---|---|
0x0 | 1-bit |
0x1 | 4-bit |
SpecialContentType
Value | Description |
---|---|
0x1 | Update |
0x2 | Manual |
0x3 | DLP Child |