Skip to content

Add fsDeviceOperator* types for IDeviceOperator#730

Open
borntohonk wants to merge 1 commit into
switchbrew:masterfrom
borntohonk:master
Open

Add fsDeviceOperator* types for IDeviceOperator#730
borntohonk wants to merge 1 commit into
switchbrew:masterfrom
borntohonk:master

Conversation

@borntohonk
Copy link
Copy Markdown

@borntohonk borntohonk commented May 2, 2026

helper for cleaner implementation of Atmosphere-NX/Atmosphere#2804 (and to allow the implementation to be more consistent with how other atmosphere IDeviceOperator related things are implemented.)

https://switchbrew.org/wiki/NS_services#GetGameCardPlatformRegion
https://switchbrew.org/wiki/Filesystem_services#GetGameCardHandle
https://switchbrew.org/wiki/Filesystem_services#IDeviceOperator

Comment thread nx/include/switch/services/fs.h Outdated
@borntohonk borntohonk force-pushed the master branch 2 times, most recently from ed4110a to efbc80a Compare May 2, 2026 15:39
@borntohonk
Copy link
Copy Markdown
Author

(intended use currently WIP borntohonk/Atmosphere@0f36778 but related to topic from closed PR linked above)

@borntohonk borntohonk marked this pull request as draft May 3, 2026 19:37
@borntohonk borntohonk changed the title Add fsDeviceOperatorGetGameCardCompatibilityType for IDeviceOperator Add fsDeviceOperator* types for IDeviceOperator May 3, 2026
@borntohonk
Copy link
Copy Markdown
Author

The scope of what has to be implemented on atmosphere end is the entirity of the IDeviceOperator interface, so the scope has changed a tiny bit

@borntohonk
Copy link
Copy Markdown
Author

This requires implementing some still undocumented entries within https://switchbrew.org/wiki/Filesystem_services#IDeviceOperator; those ones I am not entirely 100% sure on, but i am checking them with ghidra to

cmd 7; SetSdCardActivationMode
cmd 8; TryGetSdCardInfo
cmd 118; MarkBeforeEraseMmcPartitionUserData
cmd 119; CheckAfterEraseMmcPartitionUserData
cmd 225; RegisterGameCardConfigurationData
cmd 226; GetGameCardDetailedErrorReportInfo
cmd 303; SetGameCardClockRateForSpeedEmulation
cmd 304; ClearGameCardClockRateForSpeedEmulation

@hexkyz
Copy link
Copy Markdown
Contributor

hexkyz commented May 5, 2026

This requires implementing some still undocumented entries within https://switchbrew.org/wiki/Filesystem_services#IDeviceOperator; those ones I am not entirely 100% sure on, but i am checking them with ghidra to

cmd 7; SetSdCardActivationMode cmd 8; TryGetSdCardInfo cmd 118; MarkBeforeEraseMmcPartitionUserData cmd 119; CheckAfterEraseMmcPartitionUserData cmd 225; RegisterGameCardConfigurationData cmd 226; GetGameCardDetailedErrorReportInfo cmd 303; SetGameCardClockRateForSpeedEmulation cmd 304; ClearGameCardClockRateForSpeedEmulation

I've added the missing commands to switchbrew.
On a cursory inspection, the only mismatch seems to be "SetSdCardActivationMode" which takes a "nn::fs::SdCardActivationMode". This is an u8 enum (see the ninupdates entry) which should be added to the fs types ("FsSdCardActivationMode"). RE'ing the meaning of the enum's values is still TODO, but, if need be, leaving them with dummy names in the meantime should be fine.

@borntohonk
Copy link
Copy Markdown
Author

borntohonk commented May 6, 2026

This requires implementing some still undocumented entries within https://switchbrew.org/wiki/Filesystem_services#IDeviceOperator; those ones I am not entirely 100% sure on, but i am checking them with ghidra to
cmd 7; SetSdCardActivationMode cmd 8; TryGetSdCardInfo cmd 118; MarkBeforeEraseMmcPartitionUserData cmd 119; CheckAfterEraseMmcPartitionUserData cmd 225; RegisterGameCardConfigurationData cmd 226; GetGameCardDetailedErrorReportInfo cmd 303; SetGameCardClockRateForSpeedEmulation cmd 304; ClearGameCardClockRateForSpeedEmulation

I've added the missing commands to switchbrew. On a cursory inspection, the only mismatch seems to be "SetSdCardActivationMode" which takes a "nn::fs::SdCardActivationMode". This is an u8 enum (see the ninupdates entry) which should be added to the fs types ("FsSdCardActivationMode"). RE'ing the meaning of the enum's values is still TODO, but, if need be, leaving them with dummy names in the meantime should be fine.

upon testing, the current way i have implemented fsDeviceOperatorRegisterGameCardConfigurationData results in (nn::ns::detail::IApplicationManagerInterface:Cmd502, RequestCheckGameCardRegistration ) to crash.

(or similar, i am just working with the coincidence of words clashing and whats new as to identify the cause, and since that one is one of the new ones, i'm guessing it has to be that one)

so i am going to look over again with the updated information, as I most likely am mishandling RegisterGameCardConfigurationData (or something else)

@borntohonk borntohonk force-pushed the master branch 2 times, most recently from 364e4f6 to 7fd9a4e Compare May 10, 2026 09:14
@borntohonk borntohonk marked this pull request as ready for review May 10, 2026 09:14
@borntohonk
Copy link
Copy Markdown
Author

borntohonk commented May 10, 2026

Should be where it is supposed to be at, minus corrections for struct helpers, if necessary, comments, if necessary, and so on

(* aside from some consistency for declaring u8)
( and cross-referencing https://yls8.mtheall.com/ninupdates/sysupdatedl/autodl_sysupdates/2026-03-17_01-03-38-hac/0100000000000819/v1476396108/FS_swipcgen_server_modern.info )

i noticed some stray / inconsistent stuff while combing over, and noticed, example the wrong cmd
1011 #GetProgramIndexForAccessLog

was defined as 1007 which is supposed to be RegisterUpdatePartition
b8a095a
which apparently has been incorrect for 6 years, whoops?

@borntohonk borntohonk force-pushed the master branch 3 times, most recently from a411980 to 2e37cab Compare May 10, 2026 13:59
Comment thread nx/source/services/fs.c
Comment thread nx/include/switch/services/fs.h Outdated
Comment thread nx/source/services/fs.c
Comment thread nx/source/services/fs.c Outdated
@borntohonk
Copy link
Copy Markdown
Author

tiny adjustment to be able to call for them on atmosphere side as just
R_RETURN(fsDeviceOperatorGetMmcSpeedMode(std::addressof(m_operator), out.GetPointer()));
R_RETURN(fsDeviceOperatorGetSdCardSpeedMode(std::addressof(m_operator), out.GetPointer()))

@borntohonk
Copy link
Copy Markdown
Author

borntohonk commented May 18, 2026

i was having issues implementing this properly into atmosphere, so i ended up overhauling ghidra-switch-loader to assist me in correcting what I was doing wrong. (the game cartridge slot ceases to function, which is a problem)

edit: i ended up finding a 20.0.0 version cartridge and examining all the IDeviceOperator calls from the sdk nso0 from that.

example:
int nn::fs::GetGameCardAttribute2(GameCardAttribute2 *param_1,uint param_2)

iVar1 = (**(code **)(_Reset + 0x240))(0,&local_658);
0x240 is a VT offset, which aligns with nn::fssrv::sf::IFileSystemProxy::OpenDeviceOperator == CMD 400/VT Offset 0x240.

iVar1 = (**(code **)(*local_48 + 0x178))(local_48,&local_658,0x600,param_2)
0x178 is a VT offset, which alligns with nn::fssrv::sf::IDeviceOperator::GetGameCardCardHeader == CMD 222/VT Offset 0x178

deduction:
GetGameCardAttribute2 takes a GameCardHeader - but does not have its own IDeviceOperator concept

i corrected the ipc emulator within ghidra-switch-loader to be able to output this:

(examples from FS exfat binary 20.0.0)

/* IPC INFORMATION
   Dispatch Func:     0x7100094334
   Command:           0xDB
   Command Dec:       219
   Command Name:      ChallengeCardExistence
   LR:                0x710001F1B8
   VT Offset:         0x160
   Bytes In:          0x4
   Bytes Out:         0x0
   Buffer Count:      0x3
   Buffer Attrs:      [6, 5, 5]
   Buffer Directions: [out, in, in]
   Buffer Source:     legacy-compact/u8+0xA
   In Buffers:        0x2
   Out Buffers:       0x1
   In Interfaces:     0x0
   Out Interfaces:    0x0
   In Handles:        0x0
   Out Handles:       0x0
*/

compared to the ninupdates reports;
219: {"vt": 0x160, "func": 0x7100094334, "lr": 0x710001F1B8, "inbytes": 4, "outbytes": 0, "buffers": [6, 5, 5]},

part of this quest, also led to enhancing this now newfound identified information within the ipc analyzing/emulation, to mark the buffers positions in the pseudocode of the functions, which are all labeled now.

which led to this result, allowing me to discern, me implementing the wrong order might have been causing problems:

edit: exported prototypes from the 20.0.0 cartridge sdk nso0

nn::fssrv::sf::IDeviceOperator::IsSdCardInserted(IsSdCardInserted(fs * this))
nn::fssrv::sf::IDeviceOperator::GetSdCardSpeedMode(GetSdCardSpeedMode(SdCardSpeedMode * param_1))
nn::fssrv::sf::IDeviceOperator::GetSdCardCid(GetSdCardCid(void * param_1, ulong param_2))
nn::fssrv::sf::IDeviceOperator::GetSdCardUserAreaSize(GetSdCardUserAreaSize(long * param_1))
nn::fssrv::sf::IDeviceOperator::GetSdCardProtectedAreaSize(GetSdCardProtectedAreaSize(long * param_1))
nn::fssrv::sf::IDeviceOperator::GetAndClearSdCardErrorInfo(GetAndClearSdCardErrorInfo(StorageErrorInfo * param_1, ulong * param_2, char * param_3, ulong param_4))
nn::fssrv::sf::IDeviceOperator::GetSdCardHostControllerStatus(GetSdCardHostControllerStatus(HostControllerStatus * param_1))
nn::fssrv::sf::IDeviceOperator::SetSdCardActivationMode(SetSdCardActivationMode(SdCardActivationMode param_1))
nn::fssrv::sf::IDeviceOperator::TryGetSdCardInfo(TryGetSdCardInfo(SdCardInfo * param_1))
nn::fssrv::sf::IDeviceOperator::GetMmcCid(GetMmcCid(void * param_1, ulong param_2))
nn::fssrv::sf::IDeviceOperator::GetMmcSpeedMode(GetMmcSpeedMode(MmcSpeedMode * param_1))
nn::fssrv::sf::IDeviceOperator::EraseMmc(EraseMmc(MmcPartition param_1))
nn::fssrv::sf::IDeviceOperator::GetMmcPartitionSize(GetMmcPartitionSize(long * param_1, MmcPartition param_2))
nn::fssrv::sf::IDeviceOperator::GetMmcPatrolCount(GetMmcPatrolCount(uint * param_1))
nn::fssrv::sf::IDeviceOperator::GetAndClearMmcErrorInfo(GetAndClearMmcErrorInfo(StorageErrorInfo * param_1, ulong * param_2, char * param_3, ulong param_4))
nn::fssrv::sf::IDeviceOperator::GetMmcExtendedCsd(GetMmcExtendedCsd(void * param_1, ulong param_2))
nn::fssrv::sf::IDeviceOperator::SuspendMmcPatrol(SuspendMmcPatrol(fs * this))
nn::fssrv::sf::IDeviceOperator::ResumeMmcPatrol(ResumeMmcPatrol(fs * this))
nn::fssrv::sf::IDeviceOperator::MarkBeforeEraseMmcPartitionUserData(MarkBeforeEraseMmcPartitionUserData(fs * this))
nn::fssrv::sf::IDeviceOperator::CheckAfterEraseMmcPartitionUserData(CheckAfterEraseMmcPartitionUserData(fs * this))
nn::fssrv::sf::IDeviceOperator::IsGameCardInserted(IsGameCardInserted(fs * this))
nn::fssrv::sf::IDeviceOperator::EraseGameCard(EraseGameCard(GameCardSize param_1, ulong param_2))
nn::fssrv::sf::IDeviceOperator::GetGameCardHandle(GetGameCardHandle(uint * param_1))
nn::fssrv::sf::IDeviceOperator::GetGameCardUpdatePartitionInfo(GetGameCardUpdatePartitionInfo(bool * param_1, GameCardUpdatePartitionInfo * param_2, uint param_3))
nn::fssrv::sf::IDeviceOperator::FinalizeGameCardDriver(FinalizeGameCardDriver(fs * this))
nn::fssrv::sf::IDeviceOperator::GetGameCardAttribute(GetGameCardAttribute(GameCardAttribute * param_1, uint param_2))
nn::fssrv::sf::IDeviceOperator::GetGameCardDeviceCertificate(GetGameCardDeviceCertificate(void * param_1, ulong param_2, uint param_3))
nn::fssrv::sf::IDeviceOperator::GetGameCardDeviceCertificate(GetGameCardDeviceCertificate(long * param_1, void * param_2, ulong param_3, uint param_4))
nn::fssrv::sf::IDeviceOperator::GetGameCardAsicInfo(GetGameCardAsicInfo(RmaInformation * param_1, void * param_2, ulong param_3))
nn::fssrv::sf::IDeviceOperator::GetGameCardIdSet(GetGameCardIdSet(GameCardIdSet * param_1))
nn::fssrv::sf::IDeviceOperator::WriteToGameCard(WriteToGameCard(long param_1, void * param_2, ulong param_3))
nn::fssrv::sf::IDeviceOperator::SetVerifyWriteEnableFlag(SetVerifyWriteEnableFlag(bool param_1))
nn::fssrv::sf::IDeviceOperator::GetGameCardImageHash(GetGameCardImageHash(void * param_1, ulong param_2, uint param_3))
nn::fssrv::sf::IDeviceOperator::GetGameCardDeviceIdForProdCard(GetGameCardDeviceIdForProdCard(void * param_1, ulong param_2, void * param_3, ulong param_4))
nn::fssrv::sf::IDeviceOperator::EraseAndWriteParamDirectly(EraseAndWriteParamDirectly(void * param_1, ulong param_2))
nn::fssrv::sf::IDeviceOperator::ReadParamDirectly(ReadParamDirectly(void * param_1, ulong param_2))
nn::fssrv::sf::IDeviceOperator::ForceEraseGameCard(ForceEraseGameCard(fs * this))
nn::fssrv::sf::IDeviceOperator::GetGameCardErrorInfo(GetGameCardErrorInfo(GameCardErrorInfo * param_1))
nn::fssrv::sf::IDeviceOperator::GetGameCardErrorReportInfo(GetGameCardErrorReportInfo(GameCardErrorReportInfo * param_1))
nn::fssrv::sf::IDeviceOperator::GetGameCardDeviceId(GetGameCardDeviceId(void * param_1, ulong param_2))
nn::fssrv::sf::IDeviceOperator::ChallengeCardExistence(ChallengeCardExistence(void * param_1, ulong param_2, void * param_3, ulong param_4, void * param_5, ulong param_6, uint param_7))
nn::fssrv::sf::IDeviceOperator::GetGameCardCompatibilityType(GetGameCardCompatibilityType(GameCardCompatibilityType * param_1, uint param_2))
nn::fssrv::sf::IDeviceOperator::GetGameCardAsicCertificate(GetGameCardAsicCertificate(GameCardAsicCertificateSet * param_1))
nn::fssrv::sf::IDeviceOperator::GetGameCardCardHeaderSet(GetGameCardCardHeaderSet(void * param_1, ulong param_2, uint param_3))
nn::fssrv::sf::IDeviceOperator::SetGameCardSessionCreationDelay(SetGameCardSessionCreationDelay(bool param_1, uint param_2, bool param_3))
nn::fssrv::sf::IDeviceOperator::GetGameCardApplicationIdList(GetGameCardApplicationIdList(ushort * param_1, void * param_2, ulong param_3, uint param_4))
nn::fssrv::sf::IDeviceOperator::RegisterGameCardConfigurationData(RegisterGameCardConfigurationData(void * param_1, ulong param_2))
nn::fssrv::sf::IDeviceOperator::GetGameCardDetailedErrorReportInfo(GetGameCardDetailedErrorReportInfo(GameCardDetailedErrorReportInfo * param_1))
nn::fssrv::sf::IDeviceOperator::SetSpeedEmulationMode(SetSpeedEmulationMode(SpeedEmulationMode param_1))
nn::fssrv::sf::IDeviceOperator::GetSpeedEmulationMode(GetSpeedEmulationMode(SpeedEmulationMode * param_1))
nn::fssrv::sf::IDeviceOperator::SetApplicationStorageSpeed(SetApplicationStorageSpeed(ApplicationStorageSpeed param_1))
nn::fssrv::sf::IDeviceOperator::SetGameCardClockRateForSpeedEmulation(SetGameCardClockRateForSpeedEmulation(ApplicationGameCardClockRate param_1))
nn::fssrv::sf::IDeviceOperator::ClearGameCardClockRateForSpeedEmulation(ClearGameCardClockRateForSpeedEmulation(fs * this))
nn::fssrv::sf::IDeviceOperator::SuspendSdmmcControl(SuspendSdmmcControl(fs * this))
nn::fssrv::sf::IDeviceOperator::ResumeSdmmcControl(ResumeSdmmcControl(fs * this))
nn::fssrv::sf::IDeviceOperator::GetSdmmcConnectionStatus(GetSdmmcConnectionStatus(SdmmcSpeedMode * param_1, SdmmcBusWidth * param_2, SdmmcPort param_3))
nn::fssrv::sf::IDeviceOperator::SetGameCardSimulationEvent(SetGameCardSimulationEvent(SimulatingDeviceTargetOperation param_1, SimulatingDeviceAccessFailureEventType param_2))
nn::fssrv::sf::IDeviceOperator::SetGameCardSimulationEvent(SetGameCardSimulationEvent(SimulatingDeviceTargetOperation param_1, SimulatingDeviceAccessFailureEventType param_2, bool param_3))
nn::fssrv::sf::IDeviceOperator::SetGameCardSimulationEvent(SetGameCardSimulationEvent(SimulatingDeviceTargetOperation param_1, Result param_2, bool param_3))
nn::fssrv::sf::IDeviceOperator::SetSdCardSimulationEvent(SetSdCardSimulationEvent(SimulatingDeviceTargetOperation param_1, SimulatingDeviceAccessFailureEventType param_2))
nn::fssrv::sf::IDeviceOperator::SetSdCardSimulationEvent(SetSdCardSimulationEvent(SimulatingDeviceTargetOperation param_1, SimulatingDeviceAccessFailureEventType param_2, bool param_3))
nn::fssrv::sf::IDeviceOperator::SetSdCardSimulationEvent(SetSdCardSimulationEvent(SimulatingDeviceTargetOperation param_1, Result param_2, bool param_3))
nn::fssrv::sf::IDeviceOperator::ClearGameCardSimulationEvent(ClearGameCardSimulationEvent(fs * this))
nn::fssrv::sf::IDeviceOperator::ClearSdCardSimulationEvent(ClearSdCardSimulationEvent(fs * this))

(this improvement to ghidra-switch-loader should also be applicable to all the other interfaces FS has, not just IDeviceOperator)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants